diff options
Diffstat (limited to 'configs/shared/emacs/.emacs.d/elpa/slack-20180913.651')
107 files changed, 12234 insertions, 0 deletions
diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/helm-slack.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/helm-slack.el new file mode 100644 index 000000000000..8ee39d4b948b --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/helm-slack.el @@ -0,0 +1,201 @@ +;;; helm-slack.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2018 + +;; Author: <yuya373@yuya373> +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: + +(require 'helm) +(require 'slack-team) +(require 'slack-room-info-buffer) +(require 'slack-conversations) +(require 'slack-user-profile-buffer) + +(defvar helm-slack-actions + (helm-make-actions + "Display channel" #'helm-slack-display-room + "Archive channel" #'helm-slack-archive-room + "Invite user to channel" #'helm-slack-invite-to-room + "Kick user from channel" #'helm-slack-kick-from-room + "List user in channel" #'helm-slack-list-member-in-room + "Join channel" #'helm-slack-join-room + "Leave channel" #'helm-slack-leave-room + "Rename channel" #'helm-slack-rename-room + "Set purpose for channel" #'helm-slack-set-purpose-for-room + "Set topic of channel" #'helm-slack-set-topic-of-room + )) + +(defvar helm-slack-members-actions + (helm-make-actions "Display User" #'helm-slack-display-user)) + + +(defvar helm-slack-channels-source (helm-build-sync-source "Channels (Slack)" + :persistent-action #'helm-slack-persistent-action + :action helm-slack-actions + :candidates #'helm-slack-build-channels-candidates)) + +(defvar helm-slack-groups-source (helm-build-sync-source "Private Channels (Slack)" + :persistent-action #'helm-slack-persistent-action + :action helm-slack-actions + :candidates #'helm-slack-build-groups-candidates)) + +(defvar helm-slack-ims-source (helm-build-sync-source "Direct Messages (Slack)" + :persistent-action #'helm-slack-persistent-action + :action helm-slack-actions + :candidates #'helm-slack-build-ims-candidates)) + +(defvar helm-slack-source (helm-build-sync-source "Slack" + :persistent-action #'helm-slack-persistent-action + :action helm-slack-actions + :candidates #'helm-slack-build-candidates)) + +(defcustom helm-slack-sources + '(helm-slack-source) + "Default helm sources. +pre defined sources are `helm-slack-channels-source', `helm-slack-groups-source', `helm-slack-ims-source', `helm-slack-source'" + :type 'list + :group 'slack) + +(defun helm-slack-build-channels-candidates () + (helm-slack-build--candidates #'(lambda (team) (oref team channels)))) + +(defun helm-slack-build-groups-candidates () + (helm-slack-build--candidates #'(lambda (team) (oref team groups)))) + +(defun helm-slack-build-ims-candidates () + (helm-slack-build--candidates #'(lambda (team) (oref team ims)))) + +(defun helm-slack-build-candidates () + (helm-slack-build--candidates #'(lambda (team) (with-slots (channels groups ims) team + (append channels groups ims))))) + +(defun helm-slack-build--candidates (rooms-selector) + (cl-loop for team in slack-teams + as rooms = (funcall rooms-selector team) + nconc (cl-labels + ((filter (rooms) (cl-remove-if #'slack-room-hidden-p + rooms)) + (collector (label room) (list label room team))) + (let ((slack-display-team-name + (< 1 (length slack-teams)))) + (slack-room-names (append rooms nil) team + #'filter #'collector))))) + +(defmacro helm-slack-bind-room-and-team (candidate &rest body) + (declare (indent 2) (debug t)) + `(let ((room (car ,candidate)) + (team (cadr ,candidate))) + ,@body)) + +(defmacro helm-slack-bind-user-and-team (candidate &rest body) + (declare (indent 2) (debug t)) + `(let ((user (car ,candidate)) + (team (cadr ,candidate))) + ,@body)) + +(defun helm-slack-persistent-action (candidate) + (helm-slack-bind-room-and-team candidate + (let* ((buffer (slack-create-room-info-buffer room team))) + (switch-to-buffer (slack-buffer-buffer buffer))))) + +(defun helm-slack-display-room (candidate) + (helm-slack-bind-room-and-team candidate + (slack-room-display room team))) + +(defun helm-slack-archive-room (candidate) + (helm-slack-bind-room-and-team candidate + (slack-conversations-archive room team))) + +(defun helm-slack-invite-to-room (candidate) + (helm-slack-bind-room-and-team candidate + (slack-conversations-invite room team))) + +(defun helm-slack-join-room (candidate) + (helm-slack-bind-room-and-team candidate + (slack-conversations-join room team))) + +(defun helm-slack-leave-room (candidate) + (helm-slack-bind-room-and-team candidate + (slack-conversations-leave room team))) + +(defun helm-slack-rename-room (candidate) + (helm-slack-bind-room-and-team candidate + (slack-conversations-rename room team))) + +(defun helm-slack-set-purpose-for-room (candidate) + (helm-slack-bind-room-and-team candidate + (slack-conversations-set-purpose room team))) + +(defun helm-slack-set-topic-of-room (candidate) + (helm-slack-bind-room-and-team candidate + (slack-conversations-set-topic room team))) + +(defun helm-slack-kick-from-room (candidate) + (helm-slack-bind-room-and-team candidate + (slack-conversations-kick room team))) + +(defun helm-slack-list-member-in-room (candidate) + (helm-slack-bind-room-and-team candidate + (helm-slack-members-in-room room team))) + +(defun helm-slack-members-in-room (room team) + (let ((candidates nil) + (cursor nil)) + (cl-labels + ((inject-team (candidates) + (mapcar #'(lambda (candidate) + (list (car candidate) + (cdr candidate) + team)) + candidates)) + (on-members-success (members next-cursor) + (setq candidates (append candidates + members)) + (setq cursor next-cursor))) + (while (or (null cursor) + (< 0 (length cursor))) + (slack-conversations-members room + team + cursor + #'on-members-success)) + (helm + :prompt "Select Member : " + :sources (helm-build-sync-source "Members" + :candidates (inject-team candidates) + :action helm-slack-members-actions))))) + +(defun helm-slack-display-user (candidate) + (helm-slack-bind-user-and-team candidate + (let* ((user-id (plist-get user :id)) + (buffer (slack-create-user-profile-buffer team + user-id))) + (slack-buffer-display buffer)))) + +(defun helm-slack () + "Helm Slack" + (interactive) + (helm + :prompt "Select Channel : " + :sources helm-slack-sources)) + +(provide 'helm-slack) +;;; helm-slack.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-action.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-action.el new file mode 100644 index 000000000000..b3fc1b41203d --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-action.el @@ -0,0 +1,90 @@ +;;; slack-action.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2018 + +;; Author: <yuya373@yuya373> +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: +(require 'slack-util) + +(defvar slack-action-keymap + (let ((keymap (make-sparse-keymap))) + (define-key keymap (kbd "RET") #'slack-action-run) + (define-key keymap [mouse-1] #'slack-action-run) + keymap)) + +(defface slack-message-action-face + '((t (:box (:line-width 1 :style released-button)))) + "Face used to action." + :group 'slack) + +(defun slack-message-run-action () + (interactive) + (slack-if-let* ((buffer slack-current-buffer) + (room (oref buffer room)) + (ts (slack-get-ts)) + (message (slack-room-find-message room ts)) + (_not-ephemeral-messagep (not (oref message is-ephemeral)))) + (slack-buffer-execute-message-action buffer ts))) + +(defun slack-action-run () + (interactive) + (slack-if-let* ((bot (get-text-property (point) 'bot)) + (payload (get-text-property (point) 'payload)) + (buffer slack-current-buffer) + (team (oref buffer team))) + (let ((url "https://slack.com/api/chat.action") + (params (list (cons "bot" bot) + (cons "payload" payload)))) + (cl-labels + ((log-error (err) (format "Error: %s, URL: %s, PARAMS: %s" + err + url + params)) + (on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-action-run" #'log-error)))) + (slack-request + (slack-request-create + url + team + :type "POST" + :params params + :success #'on-success)))))) + +(defun slack-display-inline-action () + (goto-char (point-min)) + (let ((regexp "<slack-action://\\(.*?\\)/\\(.*?\\)|\\(.*?\\)>")) + (while (re-search-forward regexp (point-max) t) + (let ((bot (match-string 1)) + (payload (match-string 2)) + (label (match-string 3)) + (beg (- (match-beginning 1) 16)) + (end (+ (match-end 3) 1))) + (replace-match (propertize label + 'face 'slack-message-action-face + 'bot bot + 'payload payload + 'org-text (match-string 0) + 'keymap slack-action-keymap)))))) + +(provide 'slack-action) +;;; slack-action.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-action.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-action.elc new file mode 100644 index 000000000000..7f670126b659 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-action.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-attachment.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-attachment.el new file mode 100644 index 000000000000..c51f8851843b --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-attachment.el @@ -0,0 +1,529 @@ +;;; slack-attachment.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 ๅๅชไน + +;; Author: ๅๅชไน <yuyaminami@minamiyuuya-no-MacBook.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 'slack-util) +(require 'slack-request) +(require 'slack-selectable) + +(defclass slack-attachment () + ((fallback :initarg :fallback :initform nil) + (title :initarg :title :initform nil) + (title-link :initarg :title_link :initform nil) + (pretext :initarg :pretext :initform nil) + (text :initarg :text :initform nil) + (author-name :initarg :author_name :initform nil) + (author-link :initarg :author_link) + (author-icon :initarg :author_icon) + (fields :initarg :fields :initform '()) + (image-url :initarg :image_url :initform nil) + (image-width :initarg :image_width :initform nil) + (image-height :initarg :image_height :initform nil) + (thumb-url :initarg :thumb_url) + (is-share :initarg :is_share :initform nil) + (footer :initarg :footer :initform nil) + (color :initarg :color :initform nil) + (ts :initarg :ts :initform nil) + (author-subname :initarg :author_subname :initform nil) + (callback-id :initarg :callback_id :initform nil) + (id :initarg :id :initform nil) + (actions :initarg :actions :initform '()))) + +(defclass slack-shared-message (slack-attachment) + ((channel-id :initarg :channel_id :initform nil) + (channel-name :initarg :channel_name :initform nil) + (from-url :initarg :from_url :initform nil))) + +(defclass slack-attachment-field () + ((title :initarg :title :initform nil) + (value :initarg :value :initform nil) + (short :initarg :short :initform nil))) + +(defclass slack-attachment-action-confirmation () + ((title :initarg :title :initform nil) + (text :initarg :text :type string) + (ok-text :initarg :ok_text :type string :initform "Okay") + (dismiss-text :initarg :dismiss_text :type string :initform "Cancel"))) + +(defclass slack-attachment-action () + ((id :initarg :id :type string) + (name :initarg :name :type string) + (text :initarg :text :type string) + (type :initarg :type :type string) + (value :initarg :value :initform nil) + (confirm :initarg :confirm :initform nil + :type (or null slack-attachment-action-confirmation)) + (style :initarg :style :type string :initform "default") + (url :initarg :url :type (or null string) :initform nil))) + +(defclass slack-attachment-select-action (slack-attachment-action slack-selectable) + ((min-query-length :initarg :min_query_length :type (or null number) :initform nil))) + +(defclass slack-attachment-select-action-option (slack-selectable-option) ()) + +(defclass slack-attachment-select-action-option-group + (slack-selectable-option-group) ()) + + + +(defun slack-attachment-action-create (payload) + (cl-labels + ((create-option (option) + (apply #'make-instance + 'slack-attachment-select-action-option + (slack-collect-slots + 'slack-attachment-select-action-option + option))) + (create-option-group + (option-group) + (when (plist-get option-group :options) + (setq option-group + (plist-put option-group + :options + (mapcar #'create-option + (plist-get option-group :options))))) + (apply #'make-instance + 'slack-attachment-select-action-option-group + (slack-collect-slots + 'slack-attachment-select-action-option-group + option-group)))) + (let* ((properties payload) + (type (plist-get payload :type))) + + (when (plist-get payload :confirm) + (setq properties (plist-put properties + :confirm + (apply #'make-instance + 'slack-attachment-action-confirmation + (slack-collect-slots + 'slack-attachment-action-confirmation + (plist-get payload :confirm)))))) + (cond + ((string= type "select") + (progn + (setq properties + (plist-put properties + :options + (mapcar #'create-option + (plist-get properties :options)))) + (setq properties + (plist-put properties + :option_groups + (mapcar #'create-option-group + (plist-get properties :option_groups)))) + (setq properties + (plist-put properties + :selected_options + (mapcar #'create-option + (plist-get properties :selected_options)))) + (apply #'make-instance 'slack-attachment-select-action + (slack-collect-slots 'slack-attachment-select-action properties)))) + (t + (apply #'make-instance 'slack-attachment-action + (slack-collect-slots 'slack-attachment-action properties))))))) + +(defun slack-attachment-create (payload) + (let ((properties payload)) + (setq payload + (plist-put payload :fields + (mapcar #'(lambda (field) + (apply #'slack-attachment-field + (slack-collect-slots 'slack-attachment-field + field))) + (append (plist-get payload :fields) nil)))) + (setq payload + (plist-put payload :actions + (mapcar #'slack-attachment-action-create + (plist-get payload :actions)))) + + (when (numberp (plist-get payload :ts)) + (setq payload + (plist-put payload :ts (number-to-string (plist-get payload :ts))))) + + ;; (message "PAYLOAD: %s" payload) + + (if (plist-get payload :is_share) + (apply #'slack-shared-message "shared-attachment" + (slack-collect-slots 'slack-shared-message payload)) + (apply #'slack-attachment "attachment" + (slack-collect-slots 'slack-attachment payload))))) + +(defmethod slack-image-spec ((this slack-attachment)) + (with-slots (image-url image-height image-width) this + (when image-url + (list image-url image-width image-height slack-image-max-height)))) + +(defface slack-message-action-primary-face + '((t (:box (:line-width 1 :style released-button) + :foreground "#2aa198"))) + "Face used to primary action." + :group 'slack) + +(defface slack-message-action-danger-face + '((t (:box (:line-width 1 :style released-button) + :foreground "#FF6E64"))) + "Face used to danger action." + :group 'slack) + +(defvar slack-attachment-action-keymap + (let ((keymap (make-sparse-keymap))) + (define-key keymap (kbd "RET") #'slack-attachment-action-run) + (define-key keymap [mouse-1] #'slack-attachment-action-run) + keymap)) + +(defmethod slack-attachment-action-run-payload ((this slack-attachment-action) + team + common-payload + service-id) + (with-slots (id name text type value style) this + (cons (cons "actions" (list (list (cons "id" id) + (cons "name" name) + (cons "text" text) + (cons "type" type) + (cons "value" value) + (cons "style" style)))) + common-payload))) + +(defmethod slack-attachment-action-get-suggestions ((this + slack-attachment-select-action) + team + common-payload + service-id + after-success) + (with-slots (name) this + (let ((url "https://slack.com/api/chat.attachmentSuggestion") + (params (list (cons "service_id" service-id) + (cons "payload" + (json-encode-alist + (cons + (cons "name" name) + (cons (cons "value" + (read-from-minibuffer + (format "Start typing to see results... (minimum: %s) " + (oref this min-query-length)))) + common-payload))))))) + + (cl-labels + ((log-error (err) + (slack-log (format "Error: %s, URL: %s, PARAMS: %s" + err + url + params) + team :level 'error)) + (on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-attachment-action-get-suggestions" + #'log-error)) + (funcall after-success (plist-get data :options)))) + (slack-request + (slack-request-create + url + team + :type "POST" + :success #'on-success + :params params + :sync t)))))) + +(defmethod slack-attachment-action-selected-options ((this + slack-attachment-select-action) + team + common-payload + service-id) + (with-slots (data-source) this + (cond + ((string= data-source "external") + (let ((option)) + (cl-labels + ((on-success (options) + (let ((selected + (funcall slack-completing-read-function + "" + (cons "" (mapcar #'(lambda (e) + (plist-get e :text)) + options)) + nil t))) + + (setq option + (cl-find-if #'(lambda (e) + (string= selected + (plist-get e :text))) + options))))) + (slack-attachment-action-get-suggestions this + team + common-payload + service-id + #'on-success) + (if option + (list (list (cons "value" (plist-get option :value)))) + (slack-attachment-action-selected-options + this team common-payload service-id))))) + ((string= data-source "conversations") + (let ((room-id (oref (slack-room-select (append (oref team channels) + (oref team groups) + (oref team ims)) + team) + id))) + (list (list (cons "value" room-id))))) + ((string= data-source "channels") + (let ((channel-id (oref (slack-room-select (oref team channels) + team) id))) + (list (list (cons "value" channel-id))))) + ((string= data-source "users") + (let ((user-id (plist-get (slack--user-select team) :id))) + (list (list (cons "value" user-id))))) + ((string= data-source "static") + (slack-if-let* + ((option (slack-selectable-select-from-static-data-source this)) + (selected-options (list (list (cons "value" + (oref option value)))))) + selected-options + (error "Option is not selected"))) + (t (error "%s's data-source: %s is not implemented" + (oref this name) + (oref this data-source)))))) + +(defmethod slack-attachment-action-run-payload ((this slack-attachment-select-action) + team + common-payload + service-id) + (with-slots (id name text type value style data-source min-query-length) this + (slack-if-let* + ((selected-options (slack-attachment-action-selected-options this + team + common-payload + service-id))) + (cons (cons "actions" + (list (list (cons "id" id) + (cons "name" name) + (cons "text" text) + (cons "type" type) + (cons "style" style) + (cons "data_source" data-source) + (cons "min_query_length" min-query-length) + (cons "selected_options" selected-options)))) + common-payload) + (error "Option is not selected")))) + +(defmethod slack-attachment-action-confirm ((this slack-attachment-action)) + (with-slots (confirm) this + (if confirm + (with-slots (title text ok-text dismiss-text) confirm + (yes-or-no-p (format "%s%s" + (if title + (format "%s\n" title) + "") + text))) + t))) + +(defun slack-attachment-action-run () + (interactive) + (slack-if-let* ((buffer slack-current-buffer) + (room (oref buffer room)) + (team (oref buffer team)) + (type (get-text-property (point) 'type)) + (attachment-id (get-text-property (point) 'attachment-id)) + (ts (slack-get-ts)) + (message (slack-room-find-message room ts)) + (action (get-text-property (point) 'action))) + (when (slack-attachment-action-confirm action) + (slack-if-let* ((callback-id (get-text-property (point) 'callback-id)) + (common-payload (list + (cons "attachment_id" (number-to-string + attachment-id)) + (cons "callback_id" callback-id) + (cons "is_ephemeral" (oref message + is-ephemeral)) + (cons "message_ts" ts) + (cons "channel_id" (oref room id)))) + (service-id (if (slack-bot-message-p message) + (slack-message-bot-id message) + "B01"))) + (let ((url "https://slack.com/api/chat.attachmentAction") + (params (list (cons "payload" + (json-encode-alist + (slack-attachment-action-run-payload + action + team + common-payload + service-id))) + (cons "service_id" service-id) + (cons "client_token" + (slack-team-client-token team))))) + (cl-labels + ((log-error (err) + (slack-log (format "Error: %s, URL: %s, PARAMS: %s" + err + url + params) + team + :level 'error)) + (on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-attachment-action-run" #'log-error)))) + (slack-request + (slack-request-create + url + team + :type "POST" + :params params + :success #'on-success)))) + (slack-if-let* ((url (oref action url))) + (browse-url url)))))) + +(defmethod slack-attachment-callback-id ((this slack-attachment)) + (oref this callback-id)) + +(defmethod slack-attachment-id ((this slack-attachment)) + (oref this id)) + +(defmethod slack-attachment-action-face ((this slack-attachment-action)) + (with-slots (style) this + (or (and (string= "danger" style) + 'slack-message-action-danger-face) + (and (string= "primary" style) + 'slack-message-action-primary-face) + 'slack-message-action-face))) + +(defmethod slack-attachment-action-display-text ((this slack-attachment-action)) + (replace-regexp-in-string ":" " " (oref this text))) + + +(defmethod slack-attachment-action-display-text ((this slack-attachment-select-action)) + (let ((base (call-next-method))) + (with-slots (selected-options) this + (format "%s%s" base (if (and selected-options (car selected-options)) + (format " (%s)" + (slack-selectable-text (car selected-options))) + ""))))) + + +(defmethod slack-attachment-action-to-string ((action slack-attachment-select-action) + attachment team) + (with-slots (id name text type data-source style options option-groups) action + (let* ((callback-id (slack-attachment-callback-id attachment)) + (attachment-id (slack-attachment-id attachment)) + (face (slack-attachment-action-face action))) + (propertize (slack-attachment-action-display-text action) + 'type type + 'face face + 'attachment-id attachment-id + 'callback-id callback-id + 'action action + 'keymap slack-attachment-action-keymap)))) + +(defmethod slack-attachment-action-to-string ((action slack-attachment-action) + attachment team) + (with-slots (id name text type value style) action + (let* ((callback-id (slack-attachment-callback-id attachment)) + (attachment-id (slack-attachment-id attachment)) + (face (slack-attachment-action-face action))) + (propertize (slack-attachment-action-display-text action) + 'type type + 'face face + 'keymap slack-attachment-action-keymap + 'attachment-id attachment-id + 'callback-id callback-id + 'action action)))) + +(defmethod slack-message-to-string ((attachment slack-attachment) team) + (with-slots + (fallback text ts color from-url footer fields pretext actions) attachment + (let* ((pad-raw (propertize "|" 'face 'slack-attachment-pad)) + (pad (or (and color (propertize pad-raw 'face (list :foreground (concat "#" color)))) + pad-raw)) + (header-raw (slack-attachment-header attachment)) + (header (and (not (slack-string-blankp header-raw)) + (format "%s\t%s" pad + (propertize header-raw + 'face 'slack-attachment-header)))) + (pretext (and pretext (format "%s\t%s" pad pretext))) + (body (and text (format "%s\t%s" pad (mapconcat #'identity + (split-string text "\n") + (format "\n\t%s\t" pad))))) + (fields (if fields (mapconcat #'(lambda (field) + (slack-attachment-field-to-string field + (format "\t%s" pad))) + fields + (format "\n\t%s\n" pad)))) + (actions (if actions + (format "%s\t%s" + pad + (mapconcat #'(lambda (action) + (slack-attachment-action-to-string + action + attachment + team)) + actions + " ")))) + (footer (if footer + (format "%s\t%s" + pad + (propertize + (format "%s%s" footer + (or (and ts (format "|%s" (slack-message-time-to-string ts))) + "")) + 'face 'slack-attachment-footer)))) + (image (slack-image-string (slack-image-spec attachment) + (format "\t%s\t" pad)))) + (slack-message-unescape-string + (slack-format-message + (or (and header (format "\t%s\n" header)) "") + (or (and pretext (format "\t%s\n" pretext)) "") + (or (and body (format "\t%s" body)) "") + (or (and fields fields) "") + (or (and actions (format "\t%s" actions)) "") + (or (and footer (format "\n\t%s" footer)) "") + (or (and image (< 0 (length image)) + (format "\n\t%s\t%s" pad image)) "")) + team)))) + +(defmethod slack-attachment-header ((attachment slack-attachment)) + (with-slots (title title-link author-name author-subname) attachment + (concat (or (and title title-link (slack-linkfy title title-link)) + title + "") + (or author-name author-subname "")))) + +(defmethod slack-attachment-field-to-string ((field slack-attachment-field) &optional pad) + (unless pad (setq pad "")) + (let ((title (propertize (or (oref field title) "") 'face 'slack-attachment-field-title)) + (value (mapconcat #'(lambda (e) (format "\t%s" e)) + (split-string (or (oref field value) "") "\n") + (format "\n%s\t" pad)))) + (format "%s\t%s\n%s\t%s" pad title pad value))) + +(defmethod slack-attachment-to-alert ((a slack-attachment)) + (with-slots (title fallback pretext) a + (if (and title (< 0 (length title))) + title + (if (and pretext (< 0 (length pretext))) + (format "%s\n%s" pretext fallback) + fallback)))) + +(defmethod slack-selectable-prompt ((this slack-attachment-select-action)) + (format "%s :" (oref this text))) + +(provide 'slack-attachment) +;;; slack-attachment.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-attachment.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-attachment.elc new file mode 100644 index 000000000000..555a22489773 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-attachment.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-autoloads.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-autoloads.el new file mode 100644 index 000000000000..8ab3abc48d75 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-autoloads.el @@ -0,0 +1,59 @@ +;;; slack-autoloads.el --- automatically extracted autoloads +;; +;;; Code: +(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path)))) + +;;;### (autoloads nil "slack" "slack.el" (23450 31802 42642 184000)) +;;; Generated autoloads from slack.el + +(autoload 'slack-start "slack" "\ + + +\(fn &optional TEAM)" t nil) + +;;;*** + +;;;### (autoloads nil "slack-team" "slack-team.el" (23450 31802 96924 +;;;;;; 354000)) +;;; Generated autoloads from slack-team.el + +(autoload 'slack-register-team "slack-team" "\ +PLIST must contain :name :client-id :client-secret with value. +setting :token will reduce your configuration step. +you will notified when receive message with channel included in subscribed-channels. +if :default is t and `slack-prefer-current-team' is t, skip selecting team when channels listed. +you can change current-team with `slack-change-current-team' + +\(fn &rest PLIST)" t nil) + +;;;*** + +;;;### (autoloads nil nil ("helm-slack.el" "slack-action.el" "slack-attachment.el" +;;;;;; "slack-bot-message.el" "slack-buffer.el" "slack-channel.el" +;;;;;; "slack-conversations.el" "slack-dialog-buffer.el" "slack-dialog-edit-element-buffer.el" +;;;;;; "slack-dialog.el" "slack-emoji.el" "slack-file-info-buffer.el" +;;;;;; "slack-file-list-buffer.el" "slack-file.el" "slack-group.el" +;;;;;; "slack-im.el" "slack-message-buffer.el" "slack-message-compose-buffer.el" +;;;;;; "slack-message-edit-buffer.el" "slack-message-editor.el" +;;;;;; "slack-message-formatter.el" "slack-message-notification.el" +;;;;;; "slack-message-reaction.el" "slack-message-sender.el" "slack-message-share-buffer.el" +;;;;;; "slack-message.el" "slack-pinned-item.el" "slack-pinned-items-buffer.el" +;;;;;; "slack-pkg.el" "slack-reaction.el" "slack-reminder.el" "slack-reply.el" +;;;;;; "slack-request-worker.el" "slack-request.el" "slack-room-buffer.el" +;;;;;; "slack-room-info-buffer.el" "slack-room-message-compose-buffer.el" +;;;;;; "slack-room.el" "slack-search-result-buffer.el" "slack-search.el" +;;;;;; "slack-selectable.el" "slack-slash-commands.el" "slack-star.el" +;;;;;; "slack-stars-buffer.el" "slack-thread-message-buffer.el" +;;;;;; "slack-thread-message-compose-buffer.el" "slack-thread.el" +;;;;;; "slack-user-message.el" "slack-user-profile-buffer.el" "slack-user.el" +;;;;;; "slack-util.el" "slack-websocket.el") (23450 31802 126602 +;;;;;; 293000)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; End: +;;; slack-autoloads.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-bot-message.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-bot-message.el new file mode 100644 index 000000000000..1f60ff281a2b --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-bot-message.el @@ -0,0 +1,102 @@ +;;; slack-bot-message.el --- bot message class -*- lexical-binding: t; -*- + +;; Copyright (C) 2015 yuya.minami + +;; Author: yuya.minami <yuya.minami@yuyaminami-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 'slack-message) +(require 'slack-message-formatter) +(require 'slack-util) + +(defmethod slack-message-bot-id ((this slack-bot-message)) + (oref this bot-id)) + +(defun slack-find-bot (id team) + (with-slots (bots) team + (cl-find-if (lambda (bot) + (string= id (plist-get bot :id))) + bots))) + +(defun slack-find-bot-by-name (name team) + (with-slots (bots) team + (cl-find-if #'(lambda (bot) + (string= name (plist-get bot :name))) + bots))) + +(defmethod slack-bot-name ((m slack-bot-message) team) + (or (unless (slack-string-blankp (oref m username)) + (oref m username)) + (when (slot-boundp m 'bot-id) + (let ((bot (slack-find-bot (oref m bot-id) team))) + (plist-get bot :name))) + "Unknown Bot")) + +(defmethod slack-message-to-alert ((m slack-bot-message) team) + (let ((text (if (slot-boundp m 'text) + (oref m text)))) + (with-slots (attachments) m + (if (and text (< 0 (length text))) + (slack-message-unescape-string text team) + (let ((attachment-string (mapconcat #'slack-attachment-to-alert attachments " "))) + (slack-message-unescape-string attachment-string team)))))) + +(defmethod slack-message-sender-name ((m slack-bot-message) team) + (slack-bot-name m team)) + +(defmethod slack-message-sender-id ((m slack-bot-message)) + (oref m bot-id)) + +(defun slack-bot-image-url (bot size) + (let ((icons (plist-get bot :icons))) + (cond + ((eq size 36) (plist-get icons :image_36)) + ((eq size 48) (plist-get icons :image_48)) + ((eq size 72) (plist-get icons :image_72)) + (t (plist-get icons :image_36))))) + +(defun slack-bot-fetch-image (bot size team) + (let* ((image-url (slack-bot-image-url bot size)) + (file-path (and image-url (slack-profile-image-path image-url team)))) + (when file-path + (if (file-exists-p file-path) file-path + (slack-url-copy-file image-url file-path)) + file-path))) + +(cl-defun slack-bot-image (bot team &optional (size 36)) + (when bot + (let ((image (slack-bot-fetch-image bot size team))) + (when image + (create-image image nil nil :ascent 80))))) + +(defmethod slack-bot-find ((m slack-bot-message) team) + (or (and (slot-boundp m 'bot-id) + (slack-find-bot (slack-message-sender-id m) team)) + (slack-user-find-by-name (oref m username) team))) + +(defmethod slack-message-profile-image ((m slack-bot-message) team) + (let ((bot (slack-bot-find m team))) + (slack-bot-image bot team))) + +(provide 'slack-bot-message) +;;; slack-bot-message.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-bot-message.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-bot-message.elc new file mode 100644 index 000000000000..f63e5596a7c4 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-bot-message.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-buffer.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-buffer.el new file mode 100644 index 000000000000..ea56844e177f --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-buffer.el @@ -0,0 +1,448 @@ +;;; slack-buffer.el --- slack buffer -*- 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-room) + +(define-derived-mode slack-buffer-mode lui-mode "Slack Buffer" + (setq-local default-directory slack-default-directory) + (add-hook 'lui-pre-output-hook 'slack-buffer-buttonize-link nil t) + (add-hook 'lui-pre-output-hook 'slack-add-face-lazy nil t) + (add-hook 'lui-post-output-hook 'slack-display-image t t) + (lui-set-prompt " ")) + +(defvar-local slack-current-buffer nil) + +(defclass slack-buffer () + ((team :initarg :team :type slack-team))) + +(defun slack-buffer-push-new-3 (class a team) + (let ((buf (get-buffer (slack-buffer-name class a team)))) + (unless (slack-buffer-find class a team) + (push buf + (slot-value team class))) + buf)) + +(defun slack-buffer-push-new-4 (class a b team) + (let ((buf (get-buffer (slack-buffer-name class a b team)))) + (unless (slack-buffer-find class a b team) + (push buf (slot-value team class))) + buf)) + +(defmethod slack-buffer-find :static ((class slack-buffer) room team) + (slack-if-let* ((buf (cl-find-if + #'(lambda (buf) + (string= (buffer-name buf) + (slack-buffer-name class room team))) + (slot-value team class)))) + (with-current-buffer buf slack-current-buffer))) + +(defmethod slack-buffer-buffer ((this slack-buffer)) + (or (get-buffer (slack-buffer-name this)) + (slack-buffer-init-buffer this))) + +(defmethod slack-buffer-display ((this slack-buffer)) + (condition-case err + (funcall slack-buffer-function (slack-buffer-buffer this)) + (error (progn + (slack-if-let* ((buf (get-buffer (slack-buffer-name this)))) + (kill-buffer buf)) + (signal (car err) (cdr err)))))) + +(defmethod slack-buffer-name ((this slack-buffer)) + "*Slack*") + +(defun slack-message-buffer-on-killed () + (slack-if-let* ((buf slack-current-buffer) + (class (eieio-object-class-name buf)) + (cb (current-buffer))) + (set-slot-value (oref buf team) class + (cl-remove-if #'(lambda (e) (equal e cb)) + (slot-value (oref buf team) class))))) + +(defun slack-buffer-replace-image (buffer ts) + (and (buffer-live-p buffer) + (with-current-buffer buffer + (slack-buffer--replace slack-current-buffer ts)))) + +(defun slack-display-image () + (goto-char (point-min)) + (while (re-search-forward "\\[Image\\]" (point-max) t) + (slack-if-let* ((spec (get-text-property (1- (point)) 'slack-image-spec)) + (end (point)) + (beg (previous-single-property-change end 'slack-image-spec)) + (cur-buffer (current-buffer)) + (url (car spec)) + (ts (get-text-property beg 'ts)) + (path (slack-image-path url))) + (let* ((no-token-p (get-text-property (1- (point)) 'no-token)) + (token (and (not no-token-p) + (oref (oref slack-current-buffer team) + token)))) + (cl-labels + ((on-success () + (slack-buffer-replace-image cur-buffer ts))) + (unless (file-exists-p path) + (slack-url-copy-file url + path + :success #'on-success + :token token))))))) + +(defmethod slack-buffer-init-buffer :after (this) + (slack-if-let* ((buf (get-buffer (slack-buffer-name this)))) + (progn + (with-current-buffer buf + (slack-buffer-enable-emojify) + (add-hook 'kill-buffer-hook 'slack-message-buffer-on-killed nil t)) + buf))) + +(defmethod slack-buffer-set-current-buffer ((this slack-buffer)) + (setq-local slack-current-buffer this)) + + +(defmethod slack-buffer-init-buffer ((this slack-buffer)) + (generate-new-buffer (slack-buffer-name this))) + +(defmethod slack-buffer-replace ((this slack-buffer) message) + (with-slots (team) this + (with-current-buffer (slack-buffer-buffer this) + (lui-replace (slack-message-to-string message team) + (lambda () + (equal (get-text-property (point) 'ts) + (slack-ts message))))))) + +(defun slack-buffer-subscribe-cursor-event (window prev-point type) + (slack-if-let* ((buffer slack-current-buffer)) + (progn + (slack-log (format "CURSOR-EVENT: BUFFER: %s, PREV-POINT: %s, POINT: %s, TYPE: %s" + (buffer-name (window-buffer window)) + prev-point + (point) + type) + (oref buffer team) + :level 'trace) + + (when (eq type 'entered) + (unless (slack-team-mark-as-read-immediatelyp (oref buffer team)) + (slack-buffer-update-mark buffer)) + (add-hook 'post-command-hook 'slack-reaction-echo-description t t)) + + (when (eq type 'left) + (remove-hook 'post-command-hook 'slack-reaction-echo-description t))))) + +(defmethod slack-buffer-insert ((this slack-buffer) message &optional not-tracked-p) + (let ((lui-time-stamp-time (slack-message-time-stamp message)) + (team (oref this team))) + (lui-insert-with-text-properties + (slack-message-to-string message team) + 'not-tracked-p not-tracked-p + 'ts (slack-ts message) + 'slack-last-ts lui-time-stamp-last + 'cursor-sensor-functions '(slack-buffer-subscribe-cursor-event)) + (lui-insert "" t) + )) + +(defmethod slack-buffer-insert-load-more ((this slack-buffer)) + (let ((str (propertize "(load more)\n" + 'face '(:underline t :weight bold) + 'keymap (let ((map (make-sparse-keymap))) + (define-key map (kbd "RET") + #'(lambda () + (interactive) + (slack-buffer-load-more this))) + map) + 'loading-message t))) + (let ((lui-time-stamp-position nil)) + (lui-insert str)))) + +(defmethod slack-buffer-loading-message-end-point ((this slack-buffer)) + (next-single-property-change (point-min) 'loading-message)) + +(defmethod slack-buffer-delete-load-more-string ((this slack-buffer)) + (let ((loading-message-end + (slack-buffer-loading-message-end-point this))) + (delete-region (point-min) loading-message-end))) + +(defmethod slack-buffer-prepare-marker-for-history ((_this slack-buffer)) + (set-marker lui-output-marker (point-min))) + +(defmethod slack-buffer-insert--history ((this slack-buffer)) + (if (slack-buffer-has-next-page-p this) + (slack-buffer-insert-load-more this) + (let ((lui-time-stamp-position nil)) + (lui-insert "(no more messages)\n"))) + + (slack-buffer-insert-history this)) + +(defmethod slack-buffer-load-more ((this slack-buffer)) + (with-slots (team) this + (let ((cur-point (point))) + (if (slack-buffer-has-next-page-p this) + (cl-labels + ((after-success + () + (with-current-buffer (slack-buffer-buffer this) + (let ((inhibit-read-only t)) + (slack-buffer-delete-load-more-string this) + (slack-buffer-prepare-marker-for-history this) + (slack-buffer-insert--history this) + (lui-recover-output-marker))))) + (slack-buffer-request-history this #'after-success)) + (message "No more items."))))) + +(defmethod slack-buffer-display-file ((this slack-buffer) file-id) + (with-slots (team) this + (cl-labels + ((open (file _) + (slack-buffer-display + (slack-create-file-info-buffer team file)))) + (slack-file-request-info file-id 1 team #'open)))) + +(defmethod slack-buffer-cant-execute ((this slack-buffer)) + (error "Can't execute this command from %s" (eieio-object-class-name this))) + +(defmethod slack-buffer-display-pins-list ((this slack-buffer)) + (slack-buffer-cant-execute this)) +(defmethod slack-buffer-pins-add ((this slack-buffer) ts) + (slack-buffer-cant-execute this)) +(defmethod slack-buffer-pins-remove ((this slack-buffer) ts) + (slack-buffer-cant-execute this)) +(defmethod slack-buffer-display-user-profile ((this slack-buffer)) + (slack-buffer-cant-execute this)) +(defmethod slack-buffer-copy-link ((this slack-buffer) ts) + (slack-buffer-cant-execute this)) +(defmethod slack-file-upload-params ((this slack-buffer)) + (slack-buffer-cant-execute this)) +(defmethod slack-buffer-execute-message-action ((this slack-buffer) _ts) + (slack-buffer-cant-execute this)) + +(defvar lui-prompt-string "> ") + +(defvar slack-mode-map + (let ((map (make-sparse-keymap))) + ;; (define-key map (kbd "C-s C-r") #'slack-room-update-messages) + ;; (define-key map (kbd "C-s C-b") #'slack-message-write-another-buffer) + map)) + +(defcustom slack-default-directory + (expand-file-name (concat (or (getenv "HOME") "~") "/")) + "default directory at Slack Buffer.") + +(define-derived-mode slack-mode lui-mode "Slack" + "" + (setq-local default-directory slack-default-directory) + (lui-set-prompt lui-prompt-string) + (setq lui-input-function 'slack-message--send)) + +(define-derived-mode slack-info-mode lui-mode "Slack Info" + "" + (setq-local default-directory slack-default-directory) + (lui-set-prompt lui-prompt-string)) + +(defcustom slack-buffer-emojify nil + "Show emoji with `emojify' if true." + :group 'slack) + +(defcustom slack-buffer-create-on-notify nil + "Create a room buffer when notification received if it does not yet exist" + :group 'slack) + +(defmacro slack-buffer-widen (&rest body) + `(save-excursion + (save-restriction + (widen) + ,@body))) + +(defun slack-buffer-enable-emojify () + (if slack-buffer-emojify + (let ((emojify (require 'emojify nil t))) + (unless emojify + (error "Emojify is not installed")) + (emojify-mode t)))) + +(defun slack-buffer-goto (ts) + (let ((point (slack-buffer-ts-eq (point-min) (point-max) ts))) + (when point + (goto-char point)))) + +(defface slack-preview-face + (let* ((default-bg (or (face-background 'default) "unspecified-bg")) + (light-bg (if (equal default-bg "unspecified-bg") + "unspecified-bg" + (color-darken-name default-bg 3))) + (dark-bg (if (equal default-bg "unspecified-bg") + "unspecified-bg" + (color-lighten-name default-bg 3)))) + `((default :inherit (fixed-pitch shadow) :slant normal :weight normal) + (((type graphic) (class color) (background dark)) (:background ,dark-bg)) + (((type graphic) (class color) (background light)) (:background ,light-bg)))) + "Used preview text and code blocks" + :group 'slack) + +(defun slack-put-preview-overlay (start end) + (let ((overlay (make-overlay start end))) + (overlay-put overlay 'face 'slack-preview-face))) + +(defalias 'slack-put-email-body-overlay 'slack-put-preview-overlay) +(defalias 'slack-put-code-block-overlay 'slack-put-preview-overlay) + +(defun slack-search-code-block () + (while (re-search-forward "`\\([^`]\\|\n\\)" (point-max) t) + (let* ((block-begin (- (point) 4)) + (block-p (and (<= (point-min) block-begin) + (string= (buffer-substring-no-properties block-begin + (+ block-begin 3)) + "```"))) + (beg (or (and block-p block-begin) (- (point) 2))) + (end-regex (or (and block-p "```") "[^`]`[^`]"))) + + (goto-char (+ beg (or (and block-p 3) 1))) + + (if (re-search-forward end-regex (point-max) t) + (let* ((end (or (and block-p (1+ (point))) (- (point) 1)))) + (slack-put-code-block-overlay beg end) + (put-text-property beg end 'slack-disable-buttonize t) + (goto-char end)))))) + + +(defun slack-add-face-lazy () + (let* ((start (or (get-text-property (point-min) 'slack-defer-face) + (next-single-property-change (point-min) 'slack-defer-face))) + (end (and start (next-single-property-change start 'slack-defer-face)))) + (when (and start end) + (let ((face-or-func (get-text-property start 'slack-defer-face))) + (if (functionp face-or-func) + (funcall face-or-func start end) + (add-text-properties start end (list 'face face))))))) + +(defun slack-buffer-buttonize-link () + (let ((regex "<\\(http://\\|https://\\)\\(.*?\\)|\\([[:ascii:][:nonascii:]]*?\\)>")) + (ignore-errors + (goto-char (point-min)) + (while (re-search-forward regex nil t) + (let* ((url-begin (match-beginning 1)) + (cur-point (point)) + (disabled (get-text-property cur-point 'slack-disable-buttonize)) + (replace (match-string 3))) + (if disabled + (replace-match replace nil) + (let ((url (concat (match-string 1) (match-string 2)))) + (replace-match replace nil) + (make-button (1- url-begin) + (+ (1- url-begin) (length replace)) + 'type 'lui-button + 'action 'lui-button-activate + 'lui-button-function 'browse-url + 'lui-button-arguments (list url))))))))) + +(defun slack-buffer-show-typing-p (buffer) + (cl-case slack-typing-visibility + ('frame (slack-buffer-in-current-frame buffer)) + ('buffer (slack-buffer-current-p buffer)) + ('never nil))) + +(defun slack-buffer-current-p (buffer) + (if buffer + (string= (buffer-name buffer) + (buffer-name (current-buffer))))) + +(defun slack-buffer-in-current-frame (buffer) + (if buffer + (cl-member (buffer-name buffer) + (mapcar #'buffer-name + (mapcar #'window-buffer (window-list))) + :test #'string=))) + +(defmacro slack-buffer-goto-char (find-point &rest else) + `(let* ((cur-point (point)) + (ts (get-text-property cur-point 'ts))) + (let ((next-point ,find-point)) + (if next-point + (goto-char next-point) + (if (< 0 (length ',else)) + ,@else))))) + +(defun slack-buffer-goto-next-message () + (interactive) + (slack-buffer-goto-char + (slack-buffer-next-point cur-point (point-max) ts) + (message "You are on Last Message."))) + +(defun slack-buffer-goto-prev-message () + (interactive) + (slack-buffer-goto-char + (slack-buffer-prev-point cur-point (point-min) ts) + (message "You are on First Message."))) + +(defun slack-buffer-goto-first-message () + (interactive) + (goto-char + (slack-buffer-next-point (point-min) (point-max) "0"))) + +(defun slack-buffer-goto-last-message () + (interactive) + (goto-char + (slack-buffer-prev-point (point-max) (point-min) (format-time-string "%s")))) + +(defun slack-buffer-header-p (point) + (let ((face (get-text-property point 'face))) + (string= (format "%s" face) "slack-message-output-header"))) + +(defun slack-buffer-next-point (start end ts) + (cl-loop for i from start to end + if (and (string< ts + (get-text-property i 'ts)) + (slack-buffer-header-p i)) + return i)) + +(defun slack-buffer-prev-point (start end ts) + (cl-loop for i from start downto end + if (and (string< (get-text-property i 'ts) + ts) + (slack-buffer-header-p i)) + return i)) + +(defun slack-buffer-ts-eq (start end ts) + (if (and start end) + (cl-loop for i from start to end + if (string= (get-text-property i 'ts) + ts) + return i))) + +(defun slack--get-channel-id () + (interactive) + (with-current-buffer (current-buffer) + (slack-if-let* ((buffer slack-current-buffer) + (boundp (slot-boundp buffer 'room)) + (room (oref buffer room))) + (progn + (kill-new (oref room id)) + (message "%s" (oref room id)))))) + +(provide 'slack-buffer) +;;; slack-buffer.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-buffer.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-buffer.elc new file mode 100644 index 000000000000..d56ceafe7bbb --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-buffer.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-channel.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-channel.el new file mode 100644 index 000000000000..d41fcbb4728b --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-channel.el @@ -0,0 +1,277 @@ +;;; slack-channel.el ---slack channel implement -*- lexical-binding: t; -*- + +;; Copyright (C) 2015 yuya.minami + +;; Author: yuya.minami <yuya.minami@yuyaminami-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 'slack-room) +(require 'slack-group) +(require 'slack-buffer) +(require 'slack-util) +(require 'slack-request) + +(defvar slack-buffer-function) + +(defconst slack-channel-history-url "https://slack.com/api/channels.history") +(defconst slack-channel-list-url "https://slack.com/api/channels.list") +(defconst slack-channel-buffer-name "*Slack - Channel*") +(defconst slack-channel-update-mark-url "https://slack.com/api/channels.mark") +(defconst slack-create-channel-url "https://slack.com/api/channels.create") +(defconst slack-channel-rename-url "https://slack.com/api/channels.rename") +(defconst slack-channel-invite-url "https://slack.com/api/channels.invite") +(defconst slack-channel-leave-url "https://slack.com/api/channels.leave") +(defconst slack-channel-join-url "https://slack.com/api/channels.join") +(defconst slack-channel-info-url "https://slack.com/api/channels.info") +(defconst slack-channel-archive-url "https://slack.com/api/channels.archive") +(defconst slack-channel-unarchive-url "https://slack.com/api/channels.unarchive") +(defconst slack-channel-info-url "https://slack.com/api/channels.info") + +(defclass slack-channel (slack-group) + ((is-member :initarg :is_member :initform nil) + (num-members :initarg :num_members :initform 0))) + +(defmethod slack-merge ((this slack-channel) other) + (call-next-method) + (with-slots (is-member num-members) this + (setq is-member (oref other is-member)) + (setq num-members (oref other num-members)))) + +(defmethod slack-room-buffer-name ((room slack-channel) team) + (concat slack-channel-buffer-name + " : " + (slack-room-display-name room team))) + +(defun slack-channel-names (team &optional filter) + (with-slots (channels) team + (slack-room-names channels team filter))) + +(defmethod slack-room-member-p ((room slack-channel)) + (oref room is-member)) + +(defun slack-channel-select () + (interactive) + (let* ((team (slack-team-select)) + (room (slack-room-select + (cl-loop for team in (list team) + for channels = (oref team channels) + nconc channels) + team))) + (slack-room-display room team))) + +(defun slack-channel-list-update (&optional team after-success) + (interactive) + (let ((team (or team (slack-team-select)))) + (cl-labels ((on-list-update + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-channel-list-update") + (slack-merge-list (oref team channels) + (mapcar #'(lambda (d) + (slack-room-create d + team + 'slack-channel)) + (plist-get data :channels))) + + (if after-success + (funcall after-success team)) + (mapc #'(lambda (room) + (slack-request-worker-push + (slack-room-create-info-request room team))) + (oref team channels)) + (slack-log "Slack Channel List Updated" team :level 'info)))) + (slack-room-list-update slack-channel-list-url + #'on-list-update + team + :sync nil)))) + +(defmethod slack-room-update-mark-url ((_room slack-channel)) + slack-channel-update-mark-url) + +(defun slack-create-channel () + (interactive) + (let ((team (slack-team-select))) + (cl-labels + ((on-create-channel (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-channel-create")))) + (slack-create-room slack-create-channel-url + team + #'on-create-channel)))) + +(defun slack-channel-rename () + (interactive) + (slack-room-rename slack-channel-rename-url + #'slack-channel-names)) + +(defun slack-channel-invite () + (interactive) + (slack-room-invite slack-channel-invite-url + #'slack-channel-names)) + +(defun slack-channel-leave (&optional team select) + (interactive) + (let* ((team (or team (slack-team-select))) + (channel (slack-current-room-or-select + #'(lambda () + (slack-channel-names + team + #'(lambda (channels) + (cl-remove-if-not #'slack-room-member-p + channels)))) + select))) + (slack-channel-request-leave channel team))) + +(defun slack-channel-request-leave (channel team) + (cl-labels + ((on-channel-leave (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-channel-leave") + (oset channel is-member nil) + (message "Left Channel: %s" + (slack-room-name channel team))))) + (slack-room-request-with-id slack-channel-leave-url + (oref channel id) + team + #'on-channel-leave))) + +(defun slack-channel-join (&optional team select) + (interactive) + (cl-labels + ((filter-channel (channels) + (cl-remove-if + #'(lambda (c) + (or (slack-room-member-p c) + (slack-room-archived-p c))) + channels))) + (let* ((team (or team (slack-team-select))) + (channel (slack-current-room-or-select + #'(lambda () + (slack-channel-names team + #'filter-channel)) + select))) + (slack-channel-request-join channel team)))) + +(defun slack-channel-request-join (channel team) + (cl-labels + ((on-channel-join (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-channel-join")))) + (slack-request + (slack-request-create + slack-channel-join-url + team + :params (list (cons "name" (slack-room-name channel team))) + :success #'on-channel-join)))) + +(defun slack-channel-create-from-info (id team) + (cl-labels + ((on-create-from-info + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-channel-create-from-info") + (let* ((c-data (plist-get data :channel))) + (if (plist-get c-data :is_channel) + (let ((channel (slack-room-create c-data team 'slack-channel))) + (with-slots (channels) team (push channel channels)) + (message "Channel: %s created" + (slack-room-display-name channel + team)))))))) + (slack-channel-fetch-info id team #'on-create-from-info))) + +(defun slack-channel-fetch-info (id team success) + (slack-request + (slack-request-create + slack-channel-info-url + team + :params (list (cons "channel" id)) + :success success))) + +(defun slack-channel-archive () + (interactive) + (let* ((team (slack-team-select)) + (channel (slack-current-room-or-select + #'(lambda () + (slack-channel-names + team + #'(lambda (channels) + (cl-remove-if #'slack-room-archived-p + channels))))))) + (cl-labels + ((on-channel-archive (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-channel-archive")))) + (slack-room-request-with-id slack-channel-archive-url + (oref channel id) + team + #'on-channel-archive)))) + +(defun slack-channel-unarchive () + (interactive) + (let* ((team (slack-team-select)) + (channel (slack-current-room-or-select + #'(lambda () + (slack-channel-names + team + #'(lambda (channels) + (cl-remove-if-not #'slack-room-archived-p + channels))))))) + (cl-labels + ((on-channel-unarchive (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-channel-unarchive")))) + (slack-room-request-with-id slack-channel-unarchive-url + (oref channel id) + team + #'on-channel-unarchive)))) + +(defmethod slack-room-subscribedp ((room slack-channel) team) + (with-slots (subscribed-channels) team + (let ((name (slack-room-name room team))) + (and name + (memq (intern name) subscribed-channels))))) + +(defmethod slack-room-get-info-url ((_room slack-channel)) + slack-channel-info-url) + +(defmethod slack-room-update-info ((room slack-channel) data team) + (let ((new-room (slack-room-create (plist-get data :channel) + team + 'slack-channel))) + + (slack-merge room new-room))) + +(defmethod slack-room-history-url ((_room slack-channel)) + slack-channel-history-url) + +(defmethod slack-room-replies-url ((_room slack-channel)) + "https://slack.com/api/channels.replies") + +(defmethod slack-room-hidden-p ((room slack-channel)) + (slack-room-archived-p room)) + +(defmethod slack-room-member-p ((this slack-channel)) + (oref this is-member)) + +(provide 'slack-channel) +;;; slack-channel.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-channel.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-channel.elc new file mode 100644 index 000000000000..01339737bd16 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-channel.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-conversations.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-conversations.el new file mode 100644 index 000000000000..f752d0c14783 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-conversations.el @@ -0,0 +1,278 @@ +;;; slack-conversations.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2018 + +;; Author: <yuya373@yuya373> +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: +(require 'slack-request) +(require 'slack-room) + +(defconst slack-conversations-archive-url + "https://slack.com/api/conversations.archive") +(defconst slack-conversations-invite-url + "https://slack.com/api/conversations.invite") +(defconst slack-conversations-join-url + "https://slack.com/api/conversations.join") +(defconst slack-conversations-leave-url + "https://slack.com/api/conversations.leave") +(defconst slack-conversations-rename-url + "https://slack.com/api/conversations.rename") +(defconst slack-conversations-set-purpose-url + "https://slack.com/api/conversations.setPurpose") +(defconst slack-conversations-set-topic-url + "https://slack.com/api/conversations.setTopic") +(defconst slack-conversations-members-url + "https://slack.com/api/conversations.members") +(defconst slack-conversations-kick-url + "https://slack.com/api/conversations.kick") + +(cl-defun slack-conversations-success-handler (team &key on-errors on-success) + (cl-function + (lambda (&key data &allow-other-keys) + (cl-labels + ((replace-underscore-with-space (s) + (replace-regexp-in-string "_" + " " + s)) + (log-error + (_) + (slack-if-let* + ((err (plist-get data :error)) + (message (format "%s" + (replace-underscore-with-space + err)))) + (slack-log message team :level 'error)) + (slack-if-let* + ((errors (plist-get data :errors)) + (has-handler (functionp on-errors))) + (funcall on-errors errors)))) + (slack-request-handle-error + (data "conversations" #'log-error) + (slack-if-let* ((warning (plist-get data :warning))) + (slack-log (format "%s" (replace-underscore-with-space + warning)) + team + :level 'warn) + (when (functionp on-success) + (funcall on-success data)))))))) + +(defun slack-conversations-archive (room team) + (let ((id (oref room id))) + (slack-request + (slack-request-create + slack-conversations-archive-url + team + :type "POST" + :params (list (cons "channel" id)) + :success (slack-conversations-success-handler team))))) + +(defun slack-conversations-invite (room team) + (let* ((channel (oref room id)) + (user-names (slack-user-names team)) + (users nil)) + (cl-labels + ((already-selected-p + (user-name) + (cl-find-if #'(lambda (e) + (string= e + (plist-get (cdr user-name) + :id))) + users)) + (filter-selected (user-names) + (cl-remove-if #'already-selected-p + user-names))) + (cl-loop for i from 1 upto 30 + as candidates = (filter-selected user-names) + as selected = (slack-select-from-list + (candidates "Select User: ")) + while selected + do (push (plist-get selected :id) users))) + (setq users (mapconcat #'identity users ",")) + + (cl-labels + ((errors-handler + (errors) + (let ((message + (mapconcat #'(lambda (err) + (let ((msg (plist-get err :error)) + (user (plist-get err :user))) + (format "%s%s" + (replace-regexp-in-string "_" " " msg) + (or (and user (format ": %s" user)) + "")))) + errors + ", "))) + (slack-log message team :level 'error)))) + (slack-request + (slack-request-create + slack-conversations-invite-url + team + :type "POST" + :params (list (cons "channel" channel) + (cons "users" users)) + :success (slack-conversations-success-handler team + :on-errors + #'errors-handler)))))) + +(defun slack-conversations-join (room team) + (let ((channel (oref room id))) + (slack-request + (slack-request-create + slack-conversations-join-url + team + :type "POST" + :params (list (cons "channel" channel)) + :success (slack-conversations-success-handler team))))) + +(defun slack-conversations-leave (room team) + (let ((channel (oref room id))) + (slack-request + (slack-request-create + slack-conversations-leave-url + team + :type "POST" + :params (list (cons "channel" channel)) + :success (slack-conversations-success-handler team))))) + +(defun slack-conversations-rename (room team) + (let ((channel (oref room id)) + (name (read-from-minibuffer "Name: "))) + (slack-request + (slack-request-create + slack-conversations-rename-url + team + :type "POST" + :params (list (cons "channel" channel) + (cons "name" name)) + :success (slack-conversations-success-handler team))))) + +(defun slack-conversations-set-purpose (room team) + (let ((channel (oref room id)) + (purpose (read-from-minibuffer "Purpose: "))) + (cl-labels + ((on-success (data) + (let* ((channel (plist-get data :channel)) + (purpose (plist-get channel :purpose))) + (oset room purpose purpose)))) + (slack-request + (slack-request-create + slack-conversations-set-purpose-url + team + :type "POST" + :params (list (cons "channel" channel) + (cons "purpose" purpose)) + :success (slack-conversations-success-handler team + :on-success + #'on-success)))))) + +(defun slack-conversations-set-topic (room team) + (let ((channel (oref room id)) + (topic (read-from-minibuffer "Topic: "))) + (cl-labels + ((on-success (data) + (let* ((channel (plist-get data :channel)) + (topic (plist-get channel :topic))) + (oset room topic topic)))) + (slack-request + (slack-request-create + slack-conversations-set-topic-url + team + :type "POST" + :params (list (cons "channel" channel) + (cons "topic" topic)) + :success (slack-conversations-success-handler team + :on-success + #'on-success)))))) + +(defun slack-conversations-members (room team &optional cursor after-success) + (let ((channel (oref room id))) + (cl-labels + ((build-users + (members) + (cl-remove-if-not #'(lambda (user-name) + (cl-find (plist-get (cdr user-name) + :id) + members + :test #'string=)) + (slack-user-names team))) + (on-success + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-conversations-membe") + (let* ((members (plist-get data :members)) + (meta (plist-get data :response_metadata)) + (next-cursor (plist-get meta :next_cursor))) + (when (functionp after-success) + (funcall after-success + (build-users members) + next-cursor)))))) + (slack-request + (slack-request-create + slack-conversations-members-url + team + :type "GET" + :sync t + :params (list (cons "channel" channel) + (and cursor (cons "cursor" cursor)) + ;; (cons "limit" "1") + ) + :success #'on-success))))) + +(defun slack-conversations-kick (room team) + (let ((channel (oref room id)) + (cursor nil) + (user nil) + (candidates nil)) + (cl-labels + ((on-member-success (members next-cursor) + (setq candidates members) + (setq cursor next-cursor)) + (select-member (candidates) + (funcall #'completing-read + "Select User: " candidates))) + (while (not user) + (slack-conversations-members room + team + cursor + #'on-member-success) + (let ((selected (cl-assoc (select-member (or (and (< 0 (length cursor)) + (append candidates + (cons "Next page" + 'next-page))) + candidates)) + candidates + :test #'string=))) + (when selected + (unless (eq 'next-page (cdr selected)) + (setq user (plist-get (cdr selected) :id)))))) + + (slack-request + (slack-request-create + slack-conversations-kick-url + team + :type "POST" + :params (list (cons "channel" channel) + (cons "user" user)) + :success (slack-conversations-success-handler team)))))) + +(provide 'slack-conversations) +;;; slack-conversations.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-conversations.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-conversations.elc new file mode 100644 index 000000000000..3ca9b1d339b5 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-conversations.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog-buffer.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog-buffer.el new file mode 100644 index 000000000000..c1d42cb4dca9 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog-buffer.el @@ -0,0 +1,377 @@ +;;; slack-dialog-buffer.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2018 ๅๅชไน + +;; Author: ๅๅชไน <yuyaminami@minamiyuuya-no-MacBook.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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: +(require 'eieio) +(require 'slack-buffer) +(require 'slack-dialog) + +(define-derived-mode slack-dialog-buffer-mode fundamental-mode "Slack Dialog Buffer" + (setq-local default-directory slack-default-directory) + (setq-local buffer-read-only t)) + +(defvar slack-dialog-submit-button-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "RET") #'slack-dialog-buffer-submit) + (define-key map [mouse-1] #'slack-dialog-buffer-submit) + map)) + +(defvar slack-dialog-cancel-button-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "RET") #'slack-dialog-buffer-cancel) + (define-key map [mouse-1] #'slack-dialog-buffer-cancel) + map)) + +(defvar slack-dialog-select-element-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "RET") #'slack-dialog-buffer-select) + (define-key map [mouse-1] #'slack-dialog-buffer-select) + map)) + +(defface slack-dialog-element-placeholder-face + '((t (:inherit font-lock-comment-face :slant normal + ;; :box (:line-width 1 :color "#fff") + ))) + "Used to dialog's element placeholder" + :group 'slack) + +(defface slack-dialog-element-error-face + '((t (:inherit font-lock-warning-face))) + "Used to dialog's element error message" + :group 'slack) + +(defface slack-dialog-element-hint-face + '((t (:inherit font-lock-comment-face :slant italic))) + "Used to dialog's element hint" + :group 'slack) + +(defface slack-dialog-element-label-face + '((t (:weight bold))) + "Used to dialog's element label" + :group 'slack) + +(defface slack-dialog-select-element-input-face + '((t (:box (:line-width 1 :style released-button)))) + "Used to dialog's select element input" + :group 'slack) + +(defface slack-dialog-title-face + '((t (:weight bold :height 1.2))) + "Used to dialog's title" + :group 'slack) + +(defface slack-dialog-submit-button-face + '((t (:box (:line-width 1 :style released-button) + :foreground "#2aa198"))) + "Used to dialog's submit button" + :group 'slack) + +(defface slack-dialog-cancel-button-face + '((t (:box (:line-width 1 :style released-button)))) + "Used to dialog's cancel button" + :group 'slack) + +(defclass slack-dialog-buffer (slack-buffer) + ((dialog-id :initarg :dialog-id :type string) + (dialog :initarg :dialog :type slack-dialog))) + +(defmethod slack-buffer-name :static ((_class slack-dialog-buffer) dialog-id dialog team) + (with-slots (title) dialog + (format "*Slack Dialog - %s [%s] : %s*" + title + dialog-id + (slack-team-name team)))) + +(defmethod slack-buffer-name ((this slack-dialog-buffer)) + (with-slots (dialog-id dialog team) this + (slack-buffer-name 'slack-dialog-buffer + dialog-id dialog team))) + +(defmethod slack-buffer-find :static ((class slack-dialog-buffer) + dialog-id dialog team) + (slack-buffer-find-4 class dialog-id dialog team)) + +(defmethod slack-buffer-insert-label ((this slack-dialog-element)) + (with-slots (label optional) this + (insert (propertize label + 'face 'slack-dialog-element-label-face)) + (when optional + (insert " (optional)")))) + +(defmethod slack-buffer-insert-hint ((this slack-dialog-text-element)) + (with-slots (hint) this + (when hint + (insert "\n") + (insert (propertize hint + 'face 'slack-dialog-element-hint-face)) + (insert "\n")))) + +(defvar slack-dialog-element-edit-button-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "RET") #'slack-dialog-buffer-open-edit-element-buffer) + (define-key map [mouse-1] #'slack-dialog-buffer-open-edit-element-buffer) + map)) + +(defmethod slack-buffer-insert-edit-button ((this slack-dialog-text-element)) + (insert (propertize " Edit " + 'face '(:box (:line-width 1 :style released-button)) + 'keymap slack-dialog-element-edit-button-map + 'slack-dialog-element this))) + +(defun slack-dialog-buffer-open-edit-element-buffer () + (interactive) + (slack-if-let* + ((element (get-text-property (point) 'slack-dialog-element)) + (buffer slack-current-buffer) + (team (oref buffer team)) + (edit-buffer (slack-create-dialog-element-edit-buffer + buffer element team))) + (slack-buffer-display edit-buffer))) + +(defmethod slack-buffer-insert-placeholder ((this slack-dialog-text-element)) + (with-slots (placeholder) this + (insert (propertize placeholder + 'face 'slack-dialog-element-placeholder-face)))) + +(defmethod slack-buffer-insert-errors ((this slack-dialog-element)) + (with-slots (errors) this + (mapc #'(lambda (err) + (insert (propertize (oref err error-message) + 'face 'slack-dialog-element-error-face)) + (insert "\n")) + errors))) + +(defmethod slack-buffer-insert ((this slack-dialog-text-element)) + (with-slots (value placeholder errors) this + (slack-buffer-insert-label this) + (insert " ") + (slack-buffer-insert-edit-button this) + (insert "\n") + (if value + (insert value) + (if placeholder + (slack-buffer-insert-placeholder this) + (insert "Click Edit"))) + (insert "\n") + (slack-buffer-insert-errors this) + (slack-buffer-insert-hint this))) + +(defmethod slack-buffer-insert ((this slack-dialog-textarea-element)) + (with-slots (value placeholder) this + (slack-buffer-insert-label this) + (insert " ") + (slack-buffer-insert-edit-button this) + (insert "\n") + (if value + (insert value) + (if placeholder + (slack-buffer-insert-placeholder this) + (insert "Click Edit"))) + (insert "\n") + (slack-buffer-insert-errors this) + (slack-buffer-insert-hint this))) + +(defun slack-dialog-buffer-select () + (interactive) + (slack-if-let* + ((buffer slack-current-buffer) + (team (oref buffer team)) + (dialog (oref buffer dialog)) + (dialog-id (oref buffer dialog-id)) + (element-name (get-text-property (point) 'slack-dialog-element-name)) + (dialog-element (cl-find-if #'(lambda (el) (string= element-name + (oref el name))) + (oref dialog elements))) + (selected (slack-dialog--execute dialog-element + dialog-id + team)) + (label (car selected)) + (value (cdr selected)) + (option (make-instance 'slack-dialog-select-option + :label label + :value value))) + (progn + (oset dialog-element selected-options (list option)) + (oset dialog-element value value) + (slack-dialog-buffer-redisplay buffer)))) + +(defmethod slack-buffer-insert-select-button ((this slack-dialog-select-element)) + (let ((label (slack-if-let* + ((selected (slack-dialog-selected-option this))) + (slack-selectable-text selected) + "Choose an option..."))) + + (insert (propertize (format " %s " label) + 'face 'slack-dialog-select-element-input-face + 'keymap slack-dialog-select-element-map + 'slack-dialog-element-name (oref this name))))) + +(defmethod slack-buffer-insert ((this slack-dialog-select-element)) + (slack-buffer-insert-label this) + (insert "\n") + (slack-buffer-insert-select-button this) + (insert "\n") + (slack-buffer-insert-errors this)) + +(defun slack-dialog-buffer-submit () + (interactive) + (slack-if-let* + ((buffer slack-current-buffer)) + (slack-dialog-buffer--submit buffer))) + +(defmethod slack-dialog-buffer--submit ((this slack-dialog-buffer)) + (with-slots (dialog dialog-id team) this + (with-slots (elements) dialog + (dolist (element elements) + (let ((value (slack-dialog-element-value element))) + (slack-dialog-element-validate element value))) + (let ((params (mapcar #'(lambda (element) + (cons (oref element name) + (slack-dialog-element-value element))) + elements))) + (cl-labels + ((create-dialog-element-error + (payload) + (make-instance #'slack-dialog-element-error + :name (plist-get payload :name) + :error-message (plist-get payload :error))) + (set-dialog-element-error + (dialog-error elements) + (slack-if-let* + ((element (cl-find-if #'(lambda (el) + (string= (oref el name) + (oref dialog-error name))) + elements)) + (new-errors (cons dialog-error + (cl-remove-if #'(lambda (e) + (string= (oref e name) + (oref dialog-error + name))) + (oref element errors))))) + (oset element errors new-errors))) + (after-success + (data) + (slack-if-let* ((err (plist-get data :error))) + (progn + (oset dialog error-message err) + (dolist (dialog-error (mapcar #'create-dialog-element-error + (plist-get data :dialog_errors))) + (set-dialog-element-error dialog-error elements)) + + (slack-dialog-buffer-redisplay this)) + (slack-dialog-buffer-kill-buffer this)))) + (slack-dialog-clear-errors dialog) + (slack-dialog--submit dialog dialog-id team params #'after-success)))))) + +(defun slack-dialog-buffer-cancel () + (interactive) + (slack-if-let* ((buffer slack-current-buffer)) + (with-slots (dialog dialog-id team) buffer + (slack-dialog-notify-cancel dialog dialog-id team) + (slack-dialog-buffer-kill-buffer buffer)))) + +(defmethod slack-dialog-buffer-kill-buffer ((this slack-dialog-buffer)) + (slack-if-let* ((buffer-name (slack-buffer-name this)) + (buf (get-buffer buffer-name)) + (win (get-buffer-window buf))) + (progn + (kill-buffer buf) + (when (< 1 (count-windows)) + (delete-window win))))) + +(defmethod slack-buffer-insert ((this slack-dialog-buffer)) + (with-slots (dialog) this + (with-slots (error-message title elements submit-label) dialog + (let ((inhibit-read-only t)) + (insert (propertize title + 'face 'slack-dialog-title-face)) + (when error-message + (insert "\n") + (insert (propertize error-message + 'face 'slack-dialog-element-error-face))) + (insert "\n\n") + (mapc #'(lambda (el) + (slack-buffer-insert el) + (insert "\n")) + elements) + (insert "\n") + (insert (propertize " Cancel " + 'face 'slack-dialog-cancel-button-face + 'keymap slack-dialog-cancel-button-map)) + (insert "\t") + (insert (propertize (format " %s " submit-label) + 'face 'slack-dialog-submit-button-face + 'keymap slack-dialog-submit-button-map)) + (goto-char (point-min)))))) + +(defmethod slack-buffer-init-buffer ((this slack-dialog-buffer)) + (let* ((buf (generate-new-buffer (slack-buffer-name this))) + (dialog (oref this dialog)) + (dialog-id (oref this dialog-id)) + (team (oref this team))) + (with-current-buffer buf + (slack-dialog-buffer-mode) + (slack-buffer-set-current-buffer this) + (slack-buffer-insert this)) + (slack-buffer-push-new-4 'slack-dialog-buffer + dialog-id dialog team))) + +(defun slack-create-dialog-buffer (dialog-id dialog team) + (slack-if-let* + ((buf (slack-buffer-find 'slack-dialog-buffer + dialog-id + dialog + team))) + buf + (make-instance 'slack-dialog-buffer + :dialog-id dialog-id + :dialog dialog + :team team))) + +(defmethod slack-dialog-buffer-save-element-value ((this slack-dialog-buffer) + name + value) + (with-slots (dialog) this + (with-slots (elements) dialog + (let ((element (cl-find-if #'(lambda (el) + (string= name + (oref el name))) + elements))) + (oset element value value) + (slack-dialog-buffer-redisplay this))))) + +(defmethod slack-dialog-buffer-redisplay ((this slack-dialog-buffer)) + (slack-if-let* ((bufname (slack-buffer-name this)) + (buf (get-buffer bufname))) + (with-current-buffer buf + (let ((inhibit-read-only t) + (cur-point (point))) + (delete-region (point-min) (point-max)) + (slack-buffer-insert this) + (when (and (< (point-min) cur-point) + (< cur-point (point-max))) + (goto-char cur-point)))))) + +(provide 'slack-dialog-buffer) +;;; slack-dialog-buffer.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog-buffer.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog-buffer.elc new file mode 100644 index 000000000000..2b254a6ad435 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog-buffer.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog-edit-element-buffer.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog-edit-element-buffer.el new file mode 100644 index 000000000000..53b23c388678 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog-edit-element-buffer.el @@ -0,0 +1,111 @@ +;;; slack-dialog-edit-element-buffer.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2018 ๅๅชไน + +;; Author: ๅๅชไน <yuyaminami@minamiyuuya-no-MacBook.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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: +(require 'eieio) +(require 'slack-dialog-buffer) + +(defclass slack-dialog-edit-element-buffer (slack-buffer) + ((dialog-buffer :initarg :dialog-buffer :type slack-dialog-buffer) + (element :initarg :element :type slack-dialog-element))) + +(define-derived-mode slack-dialog-edit-element-buffer-mode fundamental-mode "Slack Dialog Edit Element Buffer" + (setq-local default-directory slack-default-directory)) + +(setq slack-dialog-edit-element-buffer-mode-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "C-c C-c") + #'slack-dialog-edit-buffer-save-content) + (define-key map (kbd "C-c C-k") + #'slack-dialog-edit-buffer-abort) + map)) + +(defun slack-dialog-edit-buffer-save-content () + (interactive) + (let ((content (buffer-substring-no-properties (point-min) + (point-max))) + (buffer slack-current-buffer)) + (with-slots (element dialog-buffer) buffer + (slack-dialog-edit-buffer-abort) + (slack-dialog-buffer-save-element-value dialog-buffer + (oref element name) + content)))) + +(defun slack-dialog-edit-buffer-abort () + (interactive) + (let* ((buffer-name (slack-buffer-name slack-current-buffer)) + (buf (get-buffer buffer-name)) + (win (get-buffer-window buf))) + (kill-buffer buf) + (when (< 1 (count-windows)) + (delete-window win)))) + +(defmethod slack-buffer-name :static ((_class slack-dialog-edit-element-buffer) + dialog-buffer element team) + (with-slots (dialog dialog-id) dialog-buffer + (with-slots (name) element + (with-slots (title) dialog + (format "* Slack Dialog Edit Element - %s [%s] edit %s : %s" + title dialog-id name (slack-team-name team)))))) + +(defmethod slack-buffer-find :static ((class slack-dialog-edit-element-buffer) + dialog-buffer element team) + (slack-buffer-find-4 class dialog-buffer element team)) + +(defmethod slack-buffer-name ((this slack-dialog-edit-element-buffer)) + (with-slots (dialog-buffer element team) this + (slack-buffer-name 'slack-dialog-edit-element-buffer + dialog-buffer element team))) + +(defun slack-create-dialog-element-edit-buffer (dialog-buffer element team) + (slack-if-let* + ((buf (slack-buffer-find 'slack-dialog-edit-element-buffer + dialog-buffer + element + team))) + buf + (make-instance 'slack-dialog-edit-element-buffer + :dialog-buffer dialog-buffer + :element element + :team team))) + +(defmethod slack-buffer-init-buffer ((this slack-dialog-edit-element-buffer)) + (let* ((buf (generate-new-buffer (slack-buffer-name this))) + (element (oref this element))) + (with-current-buffer buf + (slack-dialog-edit-element-buffer-mode) + (slack-buffer-set-current-buffer this) + (goto-char (point-min)) + (with-slots (value label) element + (setq-local header-line-format + (format "%s: C-c to save content" label)) + (insert (or value "")))) + (slack-buffer-push-new-4 'slack-dialog-edit-element-buffer + (oref this dialog-buffer) + element + (oref this team)))) + + +(provide 'slack-dialog-edit-element-buffer) +;;; slack-dialog-edit-element-buffer.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog-edit-element-buffer.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog-edit-element-buffer.elc new file mode 100644 index 000000000000..dd06a1723d0a --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog-edit-element-buffer.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog.el new file mode 100644 index 000000000000..e62f2a46ec13 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog.el @@ -0,0 +1,343 @@ +;;; slack-dialog.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2018 + +;; Author: <yuya373@yuya373> +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: + +(require 'eieio) +(require 'slack-util) +(require 'slack-selectable) + +(defclass slack-dialog () + ((title :initarg :title :type string) + (callback-id :initarg :callback_id :type string) + (elements :initarg :elements :type list) + (state :initarg :state :type (or null string) :initform nil) + (submit-label :initarg :submit_label :type string :initform "Submit") + (notify-on-cancel :initarg :notify_on_cancel :type boolean :initform nil) + (error-message :initarg :error-message :type (or null string) :initform nil) + )) + +(defclass slack-dialog-element () + ((name :initarg :name :type string) + (label :initarg :label :type string) + (type :initarg :type :type string) + (optional :initarg :optional :type boolean :initform nil) + (placeholder :initarg :placeholder :type (or null string) :initform nil) + (value :initarg :value :type (or null string) :initform nil) + (errors :initarg :errors :type list :initform '()))) + +(defclass slack-dialog-element-error () + ((name :initarg :name :type string) + (error-message :initarg :error-message :type string))) + +(defclass slack-dialog-text-element (slack-dialog-element) + ((max-length :initarg :max_length :type number :initform 150) + (min-length :initarg :min_length :type number :initform 0) + (hint :initarg :hint :type (or null string) :initform nil) + ;; one of email, number, tel or url + (subtype :initarg :subtype :type (or null string) :initform nil))) + +(defclass slack-dialog-textarea-element (slack-dialog-text-element) + ((max-length :initarg :max_length :type number :initform 3000))) + +(defclass slack-dialog-select-element (slack-dialog-element slack-selectable) + ((min-query-length :initarg :min_query_length :type (or null number) :initform nil))) + +(defclass slack-dialog-select-option (slack-selectable-option) + ((label :initarg :label :type string))) + +(defclass slack-dialog-select-option-group (slack-selectable-option-group) + ((label :initarg :label :type string))) + +(defmethod slack-dialog-element-value ((this slack-dialog-element)) + (or (oref this value) "")) + +(defmethod slack-dialog-element-value ((this slack-dialog-select-element)) + (with-slots (data-source selected-options) this + (or (cond + ((string= data-source "external") + (and selected-options + (car selected-options) + (oref (car selected-options) value))) + (t (oref this value))) + ""))) + +(defmethod slack-equalp ((this slack-dialog-element) other) + (string= (oref this name) + (oref other name))) + +(defmethod slack-dialog-selected-option ((this slack-dialog-select-element)) + (with-slots (data-source value options selected-options) this + (if (string= data-source "static") + (cl-find-if #'(lambda (op) (string= (oref op value) + value)) + options) + (and selected-options (car selected-options))))) + +(defmethod slack-selectable-text ((this slack-dialog-select-option)) + (oref this label)) + +(defmethod slack-selectable-text ((this slack-dialog-select-option-group)) + (oref this label)) + +(defmethod slack-selectable-prompt ((this slack-dialog-select-element)) + (format "%s :" + (oref this label))) + +(defun slack-dialog-text-element-create (payload) + (apply #'make-instance 'slack-dialog-text-element + (slack-collect-slots 'slack-dialog-text-element payload))) + +(defun slack-dialog-textarea-element-create (payload) + (apply #'make-instance 'slack-dialog-textarea-element + (slack-collect-slots 'slack-dialog-textarea-element payload))) + +(defun slack-dialog-select-element-create (payload) + (let ((options + (mapcar #'(lambda (e) + (apply #'make-instance 'slack-dialog-select-option + (slack-collect-slots 'slack-dialog-select-option + e))) + (plist-get payload :options))) + (option-groups + (mapcar #'(lambda (e) + (apply #'make-instance + 'slack-dialog-select-option-group + (slack-collect-slots 'slack-dialog-select-option-group + e))) + (plist-get payload :option_groups)))) + (setq payload (plist-put payload :options options)) + (setq payload (plist-put payload :option_groups option-groups)) + (apply #'make-instance 'slack-dialog-select-element + (slack-collect-slots 'slack-dialog-select-element + payload)))) + +(defun slack-dialog-element-create (payload) + (let ((type (plist-get payload :type))) + (cond + ((string= type "select") + (slack-dialog-select-element-create payload)) + ((string= type "text") + (slack-dialog-text-element-create payload)) + ((string= type "textarea") + (slack-dialog-textarea-element-create payload)) + (t (error "Unknown dialog element type: %s" type))))) + +(defun slack-dialog-create (payload) + (let ((elements (mapcar #'slack-dialog-element-create + (plist-get payload :elements)))) + (setq payload (plist-put payload :elements elements)) + (apply #'make-instance 'slack-dialog + (slack-collect-slots 'slack-dialog payload)))) + +(defmethod slack-dialog-element-validate ((this slack-dialog-element) value) + (with-slots (optional label) this + (when (and (not optional) + (or (null value) + (< (length value) 1))) + (error "%s must not be empty" label)))) + +(defmethod slack-dialog-element-validate ((_this slack-dialog-select-element) _value) + (call-next-method)) + +(defmethod slack-dialog-element-validate ((this slack-dialog-text-element) value) + (call-next-method) + (with-slots (min-length max-length label) this + (when (< max-length (length value)) + (error "%s must be less than %s" label max-length)) + (when (< (length value) min-length) + (error "%s must be greater than %s" label min-length)))) + +(defmethod slack-dialog-execute ((this slack-dialog-text-element) _dialog-id team) + (with-slots (hint value placeholder label optional) this + (let* ((prompt (format "%s%s%s : " + label + (if hint (format " (%s)" hint) "") + (if optional " (optional)" ""))) + (value (read-from-minibuffer prompt value))) + (slack-dialog-element-validate this value) + value))) + +(defmethod slack-dialog-execute ((this slack-dialog-textarea-element) _dialog-id team) + (call-next-method)) + +(defmethod slack-dialog-select-element-get-suggestions ((this slack-dialog-select-element) + dialog-id team after-success) + (let* ((url "https://slack.com/api/dialog.selectSuggestion") + (min-query-length (oref this min-query-length)) + (prompt (format "Type hints to see options (minimum: %s) : " min-query-length)) + (params (list (cons "dialog_id" dialog-id) + (cons "name" (oref this name)) + (cons "value" (read-from-minibuffer prompt))))) + (cl-labels + ((on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-dialog-select-fetch-suggestion") + (funcall after-success data)))) + (slack-request + (slack-request-create + url + team + :type "POST" + :params params + :sync t + :success #'on-success))))) + +(defmethod slack-dialog-execute ((this slack-dialog-select-element) dialog-id team) + (slack-if-let* ((selected (slack-dialog--execute this dialog-id team))) + (cdr selected))) + +(defmethod slack-dialog--execute ((this slack-dialog-select-element) dialog-id team) + (with-slots (data-source) this + (cond + ((string= data-source "external") + (let ((result-option nil)) + (cl-labels + ((log-error (err) + (slack-log (format "Error: %s" err) team :level 'error)) + (select (options) + (slack-if-let* + ((selected (completing-read "Choose an Option..." + (mapcar #'(lambda (option) + (plist-get option :label)) + options) + nil t))) + (cl-find-if #'(lambda (option) (string= selected + (plist-get option :label))) + options))) + (after-success (data) + (slack-request-handle-error + (data "slack-dialog-execute" + #'log-error) + (let ((option-groups (plist-get data :option_groups)) + (options (plist-get data :options))) + (when option-groups + (slack-if-let* ((selected-option-group (select option-groups))) + (setq options (plist-get selected-option-group :options)))) + (when options + (slack-if-let* ((selected (select options))) + (setq result-option selected))))))) + (slack-dialog-select-element-get-suggestions this + dialog-id + team + #'after-success) + (if result-option + (cons (plist-get result-option :label) + (plist-get result-option :value)))))) + ((string= data-source "conversations") + (slack-if-let* ((rooms (append (oref team channels) + (oref team groups) + (oref team ims))) + (room (slack-room-select rooms team))) + (cons (slack-room-name room team) + (oref room id)))) + ((string= data-source "channels") + (slack-if-let* ((channels (oref team channels)) + (channel (slack-room-select channels team))) + (cons (slack-room-name channel team) + (oref channel id)))) + ((string= data-source "users") + (slack-if-let* ((id (plist-get (slack--user-select team) :id))) + (cons (slack-user-name id team) + id))) + ((string= "static" data-source) + (slack-if-let* ((selected (slack-selectable-select-from-static-data-source this))) + (cons (oref selected label) + (oref selected value)))) + (t (error "Unknown element's data-source: %s" data-source)) + ))) + +(defmethod slack-dialog--submit ((_this slack-dialog) + dialog-id team submission + &optional after-success) + (let ((url "https://slack.com/api/dialog.submit") + (params (list (cons "submission" (json-encode-alist submission)) + (cons "dialog_id" dialog-id)))) + (cl-labels + ((on-success (&key data &allow-other-keys) + (when (functionp after-success) + (funcall after-success data)))) + (slack-request + (slack-request-create + url + team + :type "POST" + :params params + :success #'on-success))))) + +(defmethod slack-dialog-submit ((this slack-dialog) dialog-id team) + (with-slots (elements) this + (let ((submission (mapcar #'(lambda (element) + (let ((value (slack-dialog-execute element dialog-id team))) + (cons (oref element name) value))) + elements))) + (slack-dialog--submit this dialog-id team submission)))) + +(defun slack-dialog-get (id team) + (let ((url "https://slack.com/api/dialog.get") + (params (list (cons "dialog_id" id)))) + (cl-labels + ((on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-dialog-get") + (slack-if-let* + ((payload (plist-get data :dialog)) + (dialog (slack-dialog-create payload))) + ;; (slack-dialog-submit dialog id team) + (slack-buffer-display + (slack-create-dialog-buffer id + dialog + team)) + )))) + (slack-request + (slack-request-create + url + team + :type "POST" + :params params + :success #'on-success))))) + +(defmethod slack-dialog-notify-cancel ((this slack-dialog) dialog-id team) + (slack-if-let* ((url "https://slack.com/api/dialog.notifyCancel") + (params (list (cons "dialog_id" dialog-id))) + (notify-cancelp (oref this notify-on-cancel))) + (cl-labels + ((on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-dialog-notify-cancel")))) + (slack-request + (slack-request-create + url + team + :type "POST" + :params params + :success #'on-success))))) + +(defmethod slack-dialog-clear-errors ((this slack-dialog)) + (oset this error-message nil) + (dolist (element (oref this elements)) + (oset element errors nil))) + +(provide 'slack-dialog) +;;; slack-dialog.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog.elc new file mode 100644 index 000000000000..25bf207a1af9 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-dialog.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-emoji.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-emoji.el new file mode 100644 index 000000000000..baec1b03b86f --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-emoji.el @@ -0,0 +1,93 @@ +;;; slack-emoji.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 ๅๅชไน + +;; Author: ๅๅชไน <yuyaminami@minamiyuuya-no-MacBook.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 'slack-request) + +(defconst slack-emoji-list "https://slack.com/api/emoji.list") + +(defun slack-emoji-watch-download-complete (team paths) + (if (eq (length (cl-remove-if #'identity (mapcar #'file-exists-p paths))) + 0) + (when (timerp (oref team emoji-download-watch-timer)) + (cancel-timer (oref team emoji-download-watch-timer)) + (oset team emoji-download-watch-timer nil) + (emojify-create-emojify-emojis t)))) + +(defun slack-request-emoji (team) + (if (require 'emojify nil t) + (cl-labels + ((handle-alias (name emojis) + (let* ((raw-url (plist-get emojis name)) + (alias (if (string-prefix-p "alias:" raw-url) + (intern (format ":%s" (cadr (split-string raw-url ":"))))))) + (or (and alias (or (plist-get emojis alias) + (let ((emoji (emojify-get-emoji (format "%s:" alias)))) + (if emoji + (concat (emojify-image-dir) "/" (gethash "image" emoji)))))) + raw-url))) + (push-new-emoji (emoji) + (cl-pushnew emoji emojify-user-emojis + :test #'string= + :key #'car)) + (on-success + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-request-emoji") + (emojify-create-emojify-emojis) + (let* ((emojis (plist-get data :emoji)) + (names (cl-remove-if + #'(lambda (key) (not (plist-member emojis key))) + emojis)) + (paths + (mapcar + #'(lambda (name) + (let* ((url (handle-alias name emojis)) + (path (if (file-exists-p url) url + (slack-image-path url))) + (emoji (cons (format "%s:" name) + (list (cons "name" (substring (symbol-name name) 1)) + (cons "image" path) + (cons "style" "github"))))) + (if (file-exists-p path) + (push-new-emoji emoji) + (slack-url-copy-file + url + path + :success #'(lambda () (push-new-emoji emoji)))) + + path)) + names))) + + (oset team + emoji-download-watch-timer + (run-with-idle-timer 5 t #'slack-emoji-watch-download-complete team paths)))))) + (slack-request + (slack-request-create + slack-emoji-list + team + :success #'on-success))))) + +(provide 'slack-emoji) +;;; slack-emoji.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-emoji.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-emoji.elc new file mode 100644 index 000000000000..1330302ab41c --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-emoji.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-file-info-buffer.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-file-info-buffer.el new file mode 100644 index 000000000000..da0f62ec6eba --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-file-info-buffer.el @@ -0,0 +1,146 @@ +;;; slack-file-info-buffer.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 + +;; Author: <yuya373@yuya373> +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: + +(require 'eieio) +(require 'slack-util) +(require 'slack-buffer) +(require 'slack-message) + +(define-derived-mode slack-file-info-buffer-mode slack-buffer-mode "Slack File Info" + (add-hook 'lui-post-output-hook 'slack-display-image t t)) + +(defclass slack-file-info-buffer (slack-buffer) + ((file :initarg :file :type slack-file))) + +(defmethod slack-buffer-name :static ((class slack-file-info-buffer) file team) + (format "*Slack - %s File: %s" + (oref team name) + (or (oref file title) + (oref file name) + (oref file id)))) + +(defun slack-create-file-info-buffer (team file) + (slack-if-let* ((buffer (slack-buffer-find 'slack-file-info-buffer + file + team))) + (progn + (oset buffer file file) + buffer) + (slack-file-info-buffer :team team :file file))) + +(defmethod slack-buffer-init-buffer :after ((this slack-file-info-buffer)) + (with-slots (file team) this + (let ((class (eieio-object-class-name this))) + (slack-buffer-push-new-3 class file team)))) + +(defmethod slack-buffer-name ((this slack-file-info-buffer)) + (with-slots (file team) this + (slack-buffer-name (eieio-object-class-name this) + file + team))) + +(defmethod slack-buffer-buffer ((this slack-file-info-buffer)) + (slack-if-let* ((buf (get-buffer (slack-buffer-name this)))) + (progn + (with-current-buffer buf + (let ((inhibit-read-only t)) + (slack-buffer-insert this))) + buf) + (slack-buffer-init-buffer this))) + +(defmethod slack-buffer-init-buffer ((this slack-file-info-buffer)) + (let ((buf (call-next-method))) + (with-current-buffer buf + (slack-file-info-buffer-mode) + (slack-buffer-set-current-buffer this) + (slack-buffer-insert this)) + buf)) + +(defmethod slack-buffer-file-to-string ((this slack-file-info-buffer)) + (with-slots (file team) this + (let* ((header (format "%s %s\n" + (slack-message-put-header-property (oref file title)) + (if (oref file is-starred) ":star:" ""))) + (body (slack-message-body-to-string file team)) + (thumb (or (and (slack-file-image-p file) + (slack-message-large-image-to-string file)) + (slack-message-image-to-string file))) + (comments (mapconcat #'(lambda (comment) + (slack-message-to-string comment team)) + (oref file comments) + "\n"))) + (propertize (slack-format-message header + body + thumb + "\n" + comments) + 'file-id (oref file id))))) + +(defmethod slack-buffer-insert ((this slack-file-info-buffer)) + (delete-region (point-min) lui-output-marker) + (with-slots (file team) this + (let ((lui-time-stamp-position nil)) + (lui-insert-with-text-properties + (slack-buffer-file-to-string this) + ;; saved-text-properties not working?? + 'file-id (oref file id) + 'ts (slack-ts file))))) + +(defmethod slack-buffer-add-reaction-to-message + ((this slack-file-info-buffer) reaction _ts) + (with-slots (file team) this + (slack-file-add-reaction (oref file id) reaction team))) + +(defmethod slack-buffer-add-star ((this slack-file-info-buffer) _ts) + (let ((url slack-message-stars-add-url)) + (with-slots (file team) this + (slack-message-star-api-request url + (list (slack-message-star-api-params file)) + team)))) + +(defmethod slack-buffer-remove-star ((this slack-file-info-buffer) _ts) + (let ((url slack-message-stars-remove-url)) + (with-slots (file team) this + (slack-message-star-api-request url + (list (slack-message-star-api-params + file)) + team)))) + +(defmethod slack-buffer--replace ((this slack-file-info-buffer) _ts) + (slack-if-let* ((buffer (get-buffer (slack-buffer-name this)))) + (with-current-buffer buffer + (let ((inhibit-read-only t)) + (slack-buffer-insert this))))) + +(defmethod slack-buffer-update ((this slack-file-info-buffer)) + (with-slots (file team) this + (let ((buffer (get-buffer (slack-buffer-name this)))) + (with-current-buffer buffer + (let ((inhibit-read-only t)) + (slack-buffer-insert this)))))) + +(provide 'slack-file-info-buffer) +;;; slack-file-info-buffer.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-file-info-buffer.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-file-info-buffer.elc new file mode 100644 index 000000000000..5344c55cc2d1 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-file-info-buffer.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-file-list-buffer.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-file-list-buffer.el new file mode 100644 index 000000000000..527cdc919917 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-file-list-buffer.el @@ -0,0 +1,79 @@ +;;; slack-file-list-buffer.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 ๅๅชไน + +;; Author: ๅๅชไน <yuyaminami@minamiyuuya-no-MacBook.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 'slack-util) +(require 'slack-room-buffer) + +(define-derived-mode slack-file-list-buffer-mode slack-buffer-mode "Slack File List Buffer") + +(defclass slack-file-list-buffer (slack-message-buffer) ()) + +(defmethod slack-buffer-name ((_this slack-file-list-buffer)) + (format "%s" (call-next-method))) + +(defmethod slack-buffer-major-mode ((this slack-file-list-buffer)) + 'slack-file-list-buffer-mode) + +(defmethod slack-create-message-buffer ((room slack-file-room) team) + (slack-if-let* ((buffer (slack-buffer-find 'slack-file-list-buffer + room + team))) + buffer + (slack-file-list-buffer :room room :team team))) + +(cl-defmethod slack-buffer-update ((this slack-file-list-buffer) message &key replace) + (with-slots (room team) this + (let ((buffer (get-buffer (slack-buffer-name this)))) + (if replace (slack-buffer-replace this message) + (with-current-buffer buffer + (slack-buffer-insert this message)))))) + +(defmethod slack-buffer-insert ((this slack-file-list-buffer) message &optional not-tracked-p) + (let ((lui-time-stamp-time (slack-message-time-stamp message)) + (ts (slack-ts message)) + (team (oref this team))) + (lui-insert-with-text-properties + (slack-message-to-string message ts team) + 'not-tracked-p not-tracked-p + 'ts ts + 'slack-last-ts lui-time-stamp-last) + (lui-insert "" t) + )) + +(defmethod slack-buffer-replace ((this slack-file-list-buffer) + message) + (with-slots (team) this + (with-current-buffer (slack-buffer-buffer this) + (lui-replace (slack-message-to-string message + (slack-ts message) + team) + (lambda () + (equal (get-text-property (point) 'ts) + (slack-ts message))))))) + +(provide 'slack-file-list-buffer) +;;; slack-file-list-buffer.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-file-list-buffer.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-file-list-buffer.elc new file mode 100644 index 000000000000..ecc2ec89d475 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-file-list-buffer.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-file.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-file.el new file mode 100644 index 000000000000..f6ac4242e87b --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-file.el @@ -0,0 +1,550 @@ +;;; slack-file.el --- handle files -*- lexical-binding: t; -*- + +;; Copyright (C) 2016 ๅๅชไน + +;; 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 'slack-util) +(require 'slack-room) +(require 'slack-request) + +(defconst slack-file-history-url "https://slack.com/api/files.list") +(defconst slack-file-list-url "https://slack.com/api/files.list") +(defconst slack-file-upload-url "https://slack.com/api/files.upload") +(defconst slack-file-delete-url "https://slack.com/api/files.delete") + +(defclass slack-file () + ((id :initarg :id) + (created :initarg :created) + (name :initarg :name) + (size :initarg :size) + (public :initarg :public) + (filetype :initarg :filetype) + (user :initarg :user) + (preview :initarg :preview) + (permalink :initarg :permalink) + (channels :initarg :channels :type list) + (groups :initarg :groups :type list) + (ims :initarg :ims :type list) + (username :initarg :username) + (page :initarg :page :initform 1) + (pages :initarg :pages :initform nil) + (thumb-64 :initarg :thumb_64 :initform nil) + (thumb-80 :initarg :thumb_80 :initform nil) + (thumb-360 :initarg :thumb_360 :initform nil) + (thumb-360-w :initarg :thumb_360_w :initform nil) + (thumb-360-h :initarg :thumb_360_h :initform nil) + (thumb-160 :initarg :thumb_160 :initform nil) + (thumb-pdf :initarg :thumb_pdf :initform nil) + (thumb-pdf-w :initarg :thumb_pdf_w :initform nil) + (thumb-pdf-h :initarg :thumb_pdf_h :initform nil) + (original-w :initarg :original_w :initform nil) + (original-h :initarg :original_h :initform nil) + (is-starred :initarg :is_starred :initform nil) + (mimetype :initarg :mimetype :type string :initform "") + (title :initarg :title :type (or null string) :initform nil) + (pretty-type :initarg :pretty_type :type (or null string) :initform nil) + (is-public :initarg :is_public :initform nil) + (url :initarg :url :initform "" :type string) + (url-download :initarg :url_download :initform "" :type string) + (url-private :initarg :url_private :initform "" :type string) + (url-private-download :initarg :url_private_download :initform "" :type string) + (timestamp :initarg :timestamp :type number) + (comments :initarg :comments :type list :initform '()) + )) + +(defclass slack-file-email (slack-file) + ((from :initarg :from :type (or null list) :initform nil) + (to :initarg :to :type (or null list) :initform nil) + ;; TODO verify type + (cc :initarg :cc :type (or null list) :initform nil) + (subject :initarg :subject :type (or null string)) + (plain-text :initarg :plain_text :type string) + (preview-plain-text :initarg :preview_plain_text :type string) + (is-expanded :initform nil :type boolean))) + +(defclass slack-file-email-from () + ((address :initarg :address :type string) + (name :initarg :name :type string) + (original :initarg :original :type string))) + +(defclass slack-file-email-to (slack-file-email-from) ()) +(defclass slack-file-email-cc (slack-file-email-from) ()) + +(defclass slack-file-comment () + ((id :initarg :id :type string) + (created :initarg :created :type number) + (timestamp :initarg :timestamp :type number) + (user :initarg :user :type string) + (is-intro :initarg :is_intro) + (comment :initarg :comment :type string))) + +(defmethod slack-merge ((old slack-reaction) new) + (with-slots (count users) old + (setq count (oref new count)) + (setq users (cl-remove-duplicates (append users (oref new users)) + :test #'string=)))) + +(defmethod slack-merge ((old string) _new) old) +(defmethod slack-equalp ((old string) new) (string= old new)) + +(defmethod slack-merge ((old slack-file) new) + (cl-labels + ((slack-merge-string-list + (new old) + (cl-remove-duplicates (append new old) :test #'string=))) + + (slack-merge-list (oref old channels) (oref new channels)) + (slack-merge-list (oref old groups) (oref new groups)) + (slack-merge-list (oref old ims) (oref new ims)) + )) + +(defclass slack-file-room (slack-room) ()) + +(defun slack-file-find (id team) + (let ((files (oref (slack-file-room-obj team) messages))) + (cl-find-if #'(lambda (file) (string= (oref file id) id)) + files))) + +(defun slack-file-room-obj (team) + (with-slots (file-room) team + (if file-room + file-room + (setq file-room (slack-file-room "file-room" + :name "Files" + :id "F" + :created (format-time-string "%s") + :latest nil + :unread_count 0 + :unread_count_display 0 + :messages '()))))) + +(defun slack-file-create-email-from (payload &optional type) + (and payload + (make-instance (or (and (eq type 'to) 'slack-file-email-to) + (and (eq type 'cc) 'slack-file-email-cc) + 'slack-file-email-from) + :original (plist-get payload :original) + :name (plist-get payload :name) + :address (plist-get payload :address)))) + +(defun slack-file-create (payload) + (setq payload (append payload nil)) + (plist-put payload :channels (append (plist-get payload :channels) nil)) + (plist-put payload :groups (append (plist-get payload :groups) nil)) + (plist-put payload :ims (append (plist-get payload :ims) nil)) + (plist-put payload :pinned_to (append (plist-get payload :pinned_to) nil)) + (plist-put payload :channel "F") + (let* ((file (if (string= "email" (plist-get payload :filetype)) + (progn + (plist-put payload :from + (mapcar #'slack-file-create-email-from + (plist-get payload :from))) + (plist-put payload :to + (mapcar #'(lambda (e) + (slack-file-create-email-from e 'to)) + (plist-get payload :to))) + (plist-put payload :cc + (mapcar #'(lambda (e) + (slack-file-create-email-from e 'cc)) + (plist-get payload :cc))) + (apply #'slack-file-email "file-email" + (slack-collect-slots 'slack-file-email + payload))) + + (apply #'slack-file "file" + (slack-collect-slots 'slack-file payload)))) + ) + file)) + +(defmethod slack-message-equal ((f slack-file) other) + (string= (oref f id) (oref other id))) + +(defmethod slack-equalp ((old slack-file) new) + (string= (oref old id) (oref new id))) + +(defmethod slack-file-pushnew ((f slack-file) team) + (let ((room (slack-file-room-obj team))) + (slack-merge-list (oref room messages) (list f)) + ;; (oset room messages (slack-room-sort-messages (oref room messages))) + ;; (slack-room-update-latest room (car (last (oref room messages)))) + )) + +(defconst slack-file-info-url "https://slack.com/api/files.info") + +(defun slack-file-update () + (interactive) + (slack-if-let* ((buf slack-current-buffer)) + (with-slots (file team) buf + (slack-if-let* ((page (oref file page))) + (slack-file-request-info + file page team + #'(lambda (file team) + (slack-redisplay file team))))))) + +(defun slack-file-comment-create (payload) + (apply 'make-instance 'slack-file-comment + (slack-collect-slots 'slack-file-comment payload))) + +(defun slack-file-request-info (file-id page team &optional after-success) + (cl-labels + ((on-file-info (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-file-info") + (let* ((paging (plist-get data :paging)) + (file (slack-file-create (plist-get data :file))) + (comments (mapcar #'slack-file-comment-create + (plist-get data :comments)))) + (oset file comments comments) + (slack-file-pushnew file team) + (if after-success + (funcall after-success file team)))))) + (slack-request + (slack-request-create + slack-file-info-url + team + :params (list (cons "file" file-id) + (cons "page" (number-to-string page))) + :success #'on-file-info)))) + +(defmethod slack-file-gdoc-p ((this slack-file)) + (string= (oref this filetype) "gdoc")) + +(defmethod slack-file-gdoc-to-string ((this slack-file)) + (with-slots (pretty-type name title url-private permalink) this + (let ((title (propertize (format "<%s|%s>" permalink (or title name)) + 'face '(:weight bold))) + (description (format "<%s|%s>" url-private pretty-type))) + (slack-format-message title description)))) + +(defmethod slack-message-body-to-string ((file slack-file) team) + (cond + ((slack-file-gdoc-p file) (slack-file-gdoc-to-string file)) + (t (with-slots (name title size filetype permalink) file + (slack-message-put-text-property + (format "name: %s\nsize: %s\ntype: %s\n%s\n" + (or title name) size filetype permalink)))))) + +(defmethod slack-team-display-image-inlinep ((_file slack-file) team) + (slack-team-display-file-image-inlinep team)) + +(defmethod slack-message-image-to-string ((file slack-file)) + (slack-image-string (slack-file-thumb-image-spec file))) + +(defmethod slack-file-image-p ((this slack-file)) + (string= (car (split-string (oref this mimetype) "/")) + "image")) + +(defmethod slack-message-large-image-to-string ((file slack-file)) + (slack-image-string (slack-file-image-spec file))) + +(defmethod slack-message-to-string ((this slack-file-email) ts team) + (let ((body (slack-file-summary this ts team)) + (thumb (slack-image-string (slack-file-thumb-image-spec this)))) + (slack-format-message body thumb))) + +(defmethod slack-message-to-string ((this slack-file) ts team) + (let ((body (slack-file-summary this ts team)) + (thumb (slack-image-string (slack-file-thumb-image-spec this)))) + (slack-format-message body thumb))) + +(defmethod slack-message-to-string ((this slack-file-comment) team) + (with-slots (user comment) this + (let ((name (slack-user-name user team)) + (status (slack-user-status user team))) + (format "%s\n%s\n" + (propertize (format "%s %s" name status) + 'face 'slack-message-output-header) + (slack-message-unescape-string comment team))))) + +(defun slack-file-list () + (interactive) + (let* ((team (slack-team-select)) + (room (slack-file-room-obj team))) + (slack-room-display room team))) + +(cl-defmethod slack-room-history-request ((room slack-file-room) team &key oldest after-success async) + (cl-labels + ((on-file-list + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-file-list") + (let ((files (cl-loop for e in (plist-get data :files) + collect (slack-file-create e)))) + (if oldest + (slack-room-set-prev-messages room files) + (slack-room-set-messages room files))) + (if after-success + (funcall after-success))))) + (slack-request + (slack-request-create + slack-file-list-url + team + :params (list (if oldest + (cons "ts_to" oldest))) + :success #'on-file-list)))) + +(defun slack-file-select-sharing-channels (current-room-name team) + (cl-labels + ((select-channels + (channels acc) + (let ((selected (apply slack-completing-read-function + (if acc + (list "Select another channel (or leave empty): " + (cons "" channels) nil t) + (list "Select channel: " channels nil t current-room-name))))) + (if (< 0 (length selected)) + (select-channels (cl-remove-if (lambda (x) (equal selected (car-safe x))) channels) + (cons selected acc)) + acc))) + (channel-id (selected channels) + (oref (cdr (cl-assoc selected channels :test #'string=)) + id))) + (let* ((channels (slack-room-names + (append (oref team ims) + (oref team channels) + (oref team groups)) + team)) + (target-channels (select-channels channels '()))) + (mapcar #'(lambda (selected) (channel-id selected channels)) + (cl-delete-if #'null target-channels))))) + +(defun slack-file-select-upload-file-as-buffer () + (find-file-noselect + (car (find-file-read-args + "Select File: " + (confirm-nonexistent-file-or-buffer))) + t t)) + +(defun slack-file-upload () + (interactive) + (slack-if-let* + ((slack-buffer slack-current-buffer) + (team (oref slack-buffer team)) + (buf (slack-file-select-upload-file-as-buffer)) + (filename (read-from-minibuffer "Filename: " + (file-name-nondirectory + (buffer-file-name buf)))) + (filetype (read-from-minibuffer "Filetype: " + (file-name-extension + (buffer-file-name buf)))) + (initial-comment (read-from-minibuffer "Message: "))) + (cl-labels + ((on-file-upload (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-file-upload")))) + + (slack-request + (slack-request-create + slack-file-upload-url + team + :type "POST" + :params (append (slack-file-upload-params slack-buffer) + (list + (cons "filename" filename) + (cons "filetype" filetype) + (if initial-comment + (cons "initial_comment" initial-comment)))) + :files (list (cons "file" buf)) + :headers (list (cons "Content-Type" "multipart/form-data")) + :success #'on-file-upload))) + (error "Call from message buffer or thread buffer"))) + +(defun slack-file-delete () + (interactive) + (cl-labels + ((on-file-delete (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-file-delete")))) + (let* ((team (slack-team-select)) + (files (oref (slack-file-room-obj team) messages)) + (your-files (cl-remove-if #'(lambda (f) + (not (string= (oref f user) + (oref team self-id)))) + files)) + (candidates (mapcar #'(lambda (f) + (cons (concat + (slack-message-time-to-string (slack-ts f)) + " " + (oref f (or title name))) + f)) + your-files)) + (selected (funcall slack-completing-read-function "Select File: " candidates)) + (deleting-file (cdr (cl-assoc selected candidates :test #'string=)))) + (slack-request + (slack-request-create + slack-file-delete-url + team + :params (list (cons "file" (oref deleting-file id))) + :success #'on-file-delete))))) + +(defmethod slack-file-id ((file slack-file)) + (oref file id)) + +(defmethod slack-file-channel ((_file slack-file)) + nil) + +(defmethod slack-file-thumb-image-spec ((file slack-file)) + (with-slots (thumb-360 thumb-360-w thumb-360-h thumb-160 thumb-80 thumb-64 thumb-pdf thumb-pdf-w thumb-pdf-h) file + (or (and thumb-360 (list thumb-360 thumb-360-w thumb-360-h)) + (and thumb-160 (list thumb-160 nil nil)) + (and thumb-80 (list thumb-80 nil nil)) + (and thumb-64 (list thumb-64 nil nil)) + (and thumb-pdf (list thumb-pdf thumb-pdf-w thumb-pdf-h)) + (list nil nil nil)))) + +(defmethod slack-file-image-spec ((this slack-file)) + (with-slots (is-public url-download url-private-download) this + (list url-private-download + nil + nil + nil + (floor (* 0.9 (frame-pixel-width)))))) + +(defmethod slack-file-channel-ids ((file slack-file)) + (append (oref file channels) + (oref file ims) + (oref file groups))) + +(defun slack-file-link-info (file-id text) + (propertize text + 'file file-id + 'face '(:underline t :weight bold) + 'keymap (let ((map (make-sparse-keymap))) + (define-key map (kbd "RET") + #'slack-file-display) + map))) + +(defmethod slack-file-summary ((file slack-file) _ts team) + (with-slots (pretty-type mimetype permalink name title) file + (format "uploaded this %s: %s <%s|open in browser>" + (or pretty-type mimetype) + (slack-file-link-info (oref file id) + (slack-message-unescape-string (or title name) + team)) + permalink))) + +(defmethod slack-file-summary ((this slack-file-email) ts team) + (with-slots (preview-plain-text plain-text is-expanded) this + (let* ((has-more (< (length preview-plain-text) + (length plain-text))) + (body (slack-message-unescape-string + (or (and is-expanded plain-text) + (or (and has-more (format "%sโฆ" preview-plain-text)) + preview-plain-text)) + team))) + (format "%s\n\n%s\n\n%s" + (call-next-method) + (propertize body + 'slack-defer-face #'slack-put-preview-overlay) + (propertize (or (and is-expanded "Collapse โ") + "+ Click to expand inline") + 'face '(:underline t) + 'keymap (let ((map (make-sparse-keymap))) + (define-key map (kbd "RET") + #'(lambda () + (interactive) + (slack-buffer-toggle-email-expand + slack-current-buffer + ts (oref this id)))) + map)))))) + +(defmacro slack-with-file (id team &rest body) + (declare (indent 2) (debug t)) + `(cl-loop for file in (oref (slack-file-room-obj ,team) messages) + do (when (string= (oref file id) ,id) + ,@body))) + +(defmethod slack-room-buffer-name ((this slack-file) _team) + (with-slots (name) this + (format "*Slack File - %s*" name))) + +(define-derived-mode slack-file-info-mode lui-mode "Slack File Info" + "" + (setq-local default-directory slack-default-directory) + ) + +(defun slack-file-display () + (interactive) + (slack-if-let* ((id (get-text-property (point) 'file)) + (buf slack-current-buffer)) + (slack-buffer-display-file buf id))) + +(defmethod slack-message-star-added ((this slack-file)) + (oset this is-starred t)) + +(defmethod slack-message-star-removed ((this slack-file)) + (oset this is-starred nil)) + +(defmethod slack-message-star-api-params ((this slack-file)) + (cons "file" (oref this id))) + +(defun slack-file-process-star-api (url team file-id) + (slack-with-file file-id team + (slack-message-star-api-request url + (list (slack-message-star-api-params file)) + team))) + +(defmethod slack-message-body-to-string ((this slack-file-email) _team) + (let ((from (format "From: %s" (mapconcat #'(lambda (e) (oref e original)) + (oref this from) + ", "))) + (to (format "To: %s" (mapconcat #'(lambda (e) (oref e original)) + (oref this to) + ", "))) + (cc (format "CC: %s" (mapconcat #'(lambda (e) (oref e original)) + (oref this cc) + ", "))) + (subject (format "Subject: %s" (oref this subject))) + (body (propertize (format "\n%s" (oref this plain-text)) + 'slack-defer-face #'slack-put-email-body-overlay)) + (date (format "Date: %s" (slack-message-time-to-string (oref this created))))) + (mapconcat #'identity + (list from to cc subject date body) + "\n"))) + +(defun slack-redisplay (file team) + ;; (slack-if-let* ((buffer (slack-buffer-find 'slack-file-info-buffer file team))) + ;; (slack-buffer--replace buffer nil)) + (slack-if-let* ((buffer (slack-buffer-find 'slack-file-list-buffer + (slack-file-room-obj team) + team))) + (slack-buffer-replace buffer file))) + +(defmethod slack-message-update ((this slack-file) team &rest _args) + (slack-if-let* ((buffer (slack-buffer-find 'slack-file-info-buffer + this + team))) + (progn + (oset buffer file this) + (slack-buffer-update buffer)))) + +(defmethod slack-ts ((this slack-file)) + (number-to-string (oref this timestamp))) + +(defmethod slack-thread-message-p ((this slack-file)) + nil) + +(provide 'slack-file) +;;; slack-file.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-file.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-file.elc new file mode 100644 index 000000000000..927bb346ee9c --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-file.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-group.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-group.el new file mode 100644 index 000000000000..f26538bf9e5f --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-group.el @@ -0,0 +1,287 @@ +;;; slack-group.el --- slack private group interface -*- lexical-binding: t; -*- + +;; Copyright (C) 2015 Yuya Minami + +;; Author: Yuya Minami +;; 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 'slack-room) +(require 'slack-util) +(require 'slack-buffer) +(require 'slack-request) + +(defconst slack-group-history-url "https://slack.com/api/groups.history") +(defconst slack--group-open-url "https://slack.com/api/groups.open") +(defconst slack-group-buffer-name "*Slack - Private Group*") +(defconst slack-group-list-url "https://slack.com/api/groups.list") +(defconst slack-group-update-mark-url "https://slack.com/api/groups.mark") +(defconst slack-create-group-url "https://slack.com/api/groups.create") +(defconst slack-group-rename-url "https://slack.com/api/groups.rename") +(defconst slack-group-invite-url "https://slack.com/api/groups.invite") +(defconst slack-group-leave-url "https://slack.com/api/groups.leave") +(defconst slack-group-archive-url "https://slack.com/api/groups.archive") +(defconst slack-group-unarchive-url "https://slack.com/api/groups.unarchive") +(defconst slack-mpim-close-url "https://slack.com/api/mpim.close") +(defconst slack-mpim-open-url "https://slack.com/api/mpim.open") +(defconst slack-group-info-url "https://slack.com/api/groups.info") + +(defvar slack-buffer-function) + +(defclass slack-group (slack-room) + ((is-group :initarg :is_group :initform nil) + (creator :initarg :creator :initform "") + (is-archived :initarg :is_archived :initform nil) + (is-mpim :initarg :is_mpim :initform nil) + (topic :initarg :topic :initform nil) + (purpose :initarg :purpose :initform nil))) + +(defmethod slack-merge ((this slack-group) other) + (call-next-method) + (with-slots (is-group creator is-archived is-mpim members topic purpose) this + (setq is-group (oref other is-group)) + (setq creator (oref other creator)) + (setq is-archived (oref other is-archived)) + (setq is-mpim (oref other is-mpim)) + (setq members (oref other members)) + (setq topic (oref other topic)) + (setq purpose (oref other purpose)))) + +(defun slack-group-names (team &optional filter) + (with-slots (groups) team + (slack-room-names groups team filter))) + +(defmethod slack-room-subscribedp ((room slack-group) team) + (with-slots (subscribed-channels) team + (let ((name (slack-room-name room team))) + (and name + (memq (intern name) subscribed-channels))))) + +(defmethod slack-room-buffer-name ((room slack-group) team) + (concat slack-group-buffer-name + " : " + (slack-room-display-name room team))) + +(defun slack-group-select () + (interactive) + (let* ((team (slack-team-select)) + (room (slack-room-select + (cl-loop for team in (list team) + for groups = (oref team groups) + nconc groups) + team))) + (slack-room-display room team))) + +(defun slack-group-list-update (&optional team after-success) + (interactive) + (let ((team (or team (slack-team-select)))) + (cl-labels ((on-list-update + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-group-list-update") + (slack-merge-list (oref team groups) + (mapcar #'(lambda (g) + (slack-room-create + g team 'slack-group)) + (plist-get data :groups))) + (if after-success + (funcall after-success team)) + (mapc #'(lambda (room) + (slack-room-info-request room team)) + (oref team groups)) + (slack-log "Slack Group List Updated" team :level 'info)))) + (slack-room-list-update slack-group-list-url + #'on-list-update + team + :sync nil)))) + + +(defmethod slack-room-update-mark-url ((_room slack-group)) + slack-group-update-mark-url) + +(defun slack-create-group () + (interactive) + (let ((team (slack-team-select))) + (cl-labels + ((on-create-group (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-create-group")))) + (slack-create-room slack-create-group-url + team + #'on-create-group)))) + +(defun slack-group-rename () + (interactive) + (slack-room-rename slack-group-rename-url + #'slack-group-names)) + +(defun slack-group-invite () + (interactive) + (slack-room-invite slack-group-invite-url + #'slack-group-names)) + +(defun slack-group-leave () + (interactive) + (let* ((team (slack-team-select)) + (group (slack-current-room-or-select + #'(lambda () + (slack-group-names team))))) + (cl-labels + ((on-group-leave + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-group-leave") + (with-slots (groups) team + (setq groups + (cl-delete-if #'(lambda (g) + (slack-room-equal-p group g)) + groups))) + (message "Left Group: %s" + (slack-room-display-name group team))))) + (slack-room-request-with-id slack-group-leave-url + (oref group id) + team + #'on-group-leave)))) + +(defmethod slack-room-archived-p ((room slack-group)) + (oref room is-archived)) + +(defun slack-group-archive () + (interactive) + (let* ((team (slack-team-select)) + (group (slack-current-room-or-select + #'(lambda () + (slack-group-names + team + #'(lambda (groups) + (cl-remove-if #'slack-room-archived-p + groups))))))) + (cl-labels + ((on-group-archive (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-group-archive")))) + (slack-room-request-with-id slack-group-archive-url + (oref group id) + team + #'on-group-archive)))) + +(defun slack-group-unarchive () + (interactive) + (let* ((team (slack-team-select)) + (group (slack-current-room-or-select + #'(lambda () + (slack-group-names + team + #'(lambda (groups) + (cl-remove-if-not #'slack-room-archived-p + groups))))))) + (cl-labels + ((on-group-unarchive (&key _data &allow-other-keys) + (data "slack-group-unarchive"))) + (slack-room-request-with-id slack-group-unarchive-url + (oref group id) + team + #'on-group-unarchive)))) + + +(defun slack-group-members-s (group team) + (with-slots (members) group + (mapconcat #'(lambda (user) + (slack-user-name user + team)) + members ", "))) + +(defun slack-group-mpim-open () + (interactive) + (let* ((team (slack-team-select)) + (users (slack-user-names team))) + (cl-labels + ((select-users (users acc) + (let ((selected (funcall slack-completing-read-function "Select User: " + users nil t))) + (if (< 0 (length selected)) + (select-users users + (push (cdr (cl-assoc selected users :test #'string=)) acc)) + acc))) + (on-success + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-group-mpim-open")))) + (slack-request + (slack-request-create + slack-mpim-open-url + team + :type "POST" + :params (list (cons "users" (mapconcat (lambda (u) (plist-get u :id)) (select-users users '()) ","))) + :success #'on-success))))) + +(defun slack-group-mpim-close () + (interactive) + (let* ((team (slack-team-select))) + (slack-select-from-list + ((slack-group-names team #'(lambda (groups) + (cl-remove-if-not #'slack-mpim-p + groups))) + "Select MPIM: ") + (cl-labels + ((on-success + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-group-mpim-close") + (let ((group (slack-room-find (oref selected id) team))) + (with-slots (groups) team + (setq groups + (cl-delete-if #'(lambda (g) + (slack-room-equal-p group g)) + groups))) + (if (plist-get data :already_closed) + (message "Direct Message Channel with %s Already Closed" + (slack-group-members-s group team))))))) + (slack-request + (slack-request-create + slack-mpim-close-url + team + :type "POST" + :params (list (cons "channel" (oref selected id))) + :success #'on-success)))))) + + +(defmethod slack-mpim-p ((room slack-group)) + (oref room is-mpim)) + +(defmethod slack-room-get-info-url ((_room slack-group)) + slack-group-info-url) + +(defmethod slack-room-update-info ((room slack-group) data team) + (let ((new-room (slack-room-create (plist-get data :group) + team + 'slack-group))) + (slack-merge room new-room))) + +(defmethod slack-room-history-url ((_room slack-group)) + slack-group-history-url) + +(defmethod slack-room-replies-url ((_room slack-group)) + "https://slack.com/api/groups.replies") + +(provide 'slack-group) +;;; slack-group.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-group.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-group.elc new file mode 100644 index 000000000000..c07a081f913b --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-group.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-im.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-im.el new file mode 100644 index 000000000000..ba224483e03c --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-im.el @@ -0,0 +1,249 @@ +;;; slack-im.el ---slack direct message 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 'slack-util) +(require 'slack-room) +(require 'slack-buffer) +(require 'slack-user) +(require 'slack-request) + +(defvar slack-buffer-function) + +(defconst slack-im-history-url "https://slack.com/api/im.history") +(defconst slack-im-buffer-name "*Slack - Direct Messages*") +(defconst slack-user-list-url "https://slack.com/api/users.list") +(defconst slack-im-list-url "https://slack.com/api/im.list") +(defconst slack-im-close-url "https://slack.com/api/im.close") +(defconst slack-im-open-url "https://slack.com/api/im.open") +(defconst slack-im-update-mark-url "https://slack.com/api/im.mark") + +(defclass slack-im (slack-room) + ((user :initarg :user :initform "") + (is-open :initarg :is_open :initform t) + (is-user-deleted :initarg :is_user_deleted :initform nil))) + +(defmethod slack-merge ((this slack-im) other) + (call-next-method) + (with-slots (user is-open) this + (setq user (oref other user)) + (setq is-open (oref other is-open)))) + +(defmethod slack-room-open-p ((room slack-im)) + (oref room is-open) + (not (oref room is-user-deleted))) + +(defmethod slack-im-user-presence ((room slack-im) team) + (slack-user-presence-to-string (slack-user-find room team))) + +(defmethod slack-im-user-dnd-status ((room slack-im) team) + (slack-user-dnd-status-to-string (slack-user-find room + team))) + +(defmethod slack-room-name ((room slack-im) team) + (with-slots (user) room + (slack-user-name user team))) + +(defmethod slack-room-display-name ((room slack-im) team) + "To Display emoji in minibuffer configure `emojify-inhibit-in-buffer-functions'" + (let* ((status (slack-user-status (oref room user) team)) + (room-name (or (and status + (format "%s %s" + (slack-room-name room team) + status)) + (slack-room-name room team)))) + (if slack-display-team-name + (format "%s - %s" + (slack-team-name team) + room-name) + room-name))) + +(defun slack-im-user-name (im team) + (with-slots (user) im + (slack-user-name user team))) + +(defun slack-im-names (team) + (with-slots (ims) team + (slack-room-names ims + team + #'(lambda (ims) + (cl-remove-if #'(lambda (im) (not (oref im is-open))) + ims))))) + +(defmethod slack-room-buffer-name ((room slack-im) team) + (concat slack-im-buffer-name + " : " + (slack-room-display-name room team))) + +(defun slack-im-select () + (interactive) + (let* ((team (slack-team-select)) + (candidates (cl-loop for team in (list team) + for ims = (cl-remove-if #'(lambda (im) + (not (oref im is-open))) + (oref team ims)) + nconc ims)) + (room (slack-room-select candidates team))) + (slack-room-display room team))) + +(defun slack-user-equal-p (a b) + (string= (plist-get a :id) (plist-get b :id))) + +(defun slack-user-pushnew (user team) + (with-slots (users) team + (cl-pushnew user users :test #'slack-user-equal-p))) + +(defun slack-im-update-room-list (users team &optional after-success) + (cl-labels ((on-update-room-list + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-im-update-room-list") + (mapc #'(lambda (u) (slack-user-pushnew u team)) + (append users nil)) + (slack-merge-list (oref team ims) + (mapcar #'(lambda (d) + (slack-room-create d team 'slack-im)) + (plist-get data :ims))) + (if after-success + (funcall after-success team)) + (slack-request-dnd-team-info team) + (mapc #'(lambda (room) + (slack-room-info-request room team)) + (oref team ims)) + (slack-log "Slack Im List Updated" team :level 'info)))) + (slack-room-list-update slack-im-list-url + #'on-update-room-list + team + :sync nil))) + +(defun slack-im-list-update (&optional team after-success) + (interactive) + (let ((team (or team (slack-team-select)))) + (cl-labels + ((on-list-update + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-im-list-update") + (let* ((members (append (plist-get data :members) nil))) + (slack-im-update-room-list members team after-success))))) + (slack-request + (slack-request-create + slack-user-list-url + team + :success #'on-list-update))))) + +(defmethod slack-room-update-mark-url ((_room slack-im)) + slack-im-update-mark-url) + +(defun slack-im-close () + (interactive) + (let* ((team (slack-team-select)) + (alist (cl-remove-if #'(lambda (im-names) + (not (oref (cdr im-names) is-open))) + (slack-im-names team)))) + (slack-select-from-list + (alist "Select User: ") + (cl-labels + ((on-success + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-im-close") + (if (plist-get data :already_closed) + (let ((im (slack-room-find (oref selected id) team))) + (oset im is-open nil) + (message "Direct Message Channel with %s Already Closed" + (slack-user-name (oref im user) team))))))) + (slack-request + (slack-request-create + slack-im-close-url + team + :type "POST" + :params (list (cons "channel" (oref selected id))) + :success #'on-success)))))) + +(defun slack-im-open (&optional user after-success) + (interactive) + (let* ((team (slack-team-select)) + (user (or user (slack-select-from-list + ((slack-user-name-alist + team + :filter #'(lambda (users) (cl-remove-if #'slack-user-hidden-p users))) + "Select User: "))))) + (cl-labels + ((on-success + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-im-open") + (if (plist-get data :already_open) + (let ((im (slack-room-find (plist-get (plist-get data :channel) :id) team))) + (oset im is-open t) + (message "Direct Message Channel with %s Already Open" + (slack-user-name (oref im user) team)))) + (when (functionp after-success) + (funcall after-success))))) + (slack-request + (slack-request-create + slack-im-open-url + team + :type "POST" + :params (list (cons "user" (plist-get user :id))) + :success #'on-success))))) + +(defmethod slack-room-label-prefix ((room slack-im) team) + (format "%s " + (or + (slack-im-user-dnd-status room team) + (slack-im-user-presence room team)))) + +(defmethod slack-room-get-info-url ((_room slack-im)) + slack-im-open-url) + +(defmethod slack-room-update-info ((room slack-im) data team) + (let ((new-room (slack-room-create (plist-get data :channel) + team + 'slack-im))) + + (slack-merge room new-room))) + +(defmethod slack-room-info-request-params ((room slack-im)) + (list (cons "user" (oref room user)) + (cons "return_im" "true"))) + +(defmethod slack-room-get-members ((room slack-im)) + (list (oref room user))) + +(defun slack-im-find-by-user-id (user-id team) + (cl-find-if #'(lambda (im) (string= user-id (oref im user))) + (oref team ims))) + +(defmethod slack-room-history-url ((_room slack-im)) + slack-im-history-url) + +(defmethod slack-room-replies-url ((_room slack-im)) + "https://slack.com/api/im.replies") + +(provide 'slack-im) +;;; slack-im.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-im.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-im.elc new file mode 100644 index 000000000000..3bba70fbf39a --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-im.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-buffer.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-buffer.el new file mode 100644 index 000000000000..3ed9fc14f9a4 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-buffer.el @@ -0,0 +1,429 @@ +;;; slack-message-buffer.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 + +;; Author: <yuya373@yuya373> +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: + +(require 'eieio) +(require 'slack-room) +(require 'slack-util) +(require 'slack-room-buffer) +(require 'slack-buffer) +(require 'slack-request) +(require 'slack-action) + +(defface slack-new-message-marker-face + '((t (:foreground "#d33682" + :weight bold + :height 0.8))) + "Face used to New Message Marker." + :group 'slack) + +(define-derived-mode slack-message-buffer-mode slack-mode "Slack Message Buffer" + (add-hook 'lui-pre-output-hook 'slack-buffer-buttonize-link nil t) + (add-hook 'lui-pre-output-hook 'slack-add-face-lazy nil t) + (add-hook 'lui-pre-output-hook 'slack-search-code-block nil t) + (add-hook 'lui-post-output-hook 'slack-display-image t t) + (add-hook 'lui-pre-output-hook 'slack-display-inline-action t t) + ;; TODO move to `slack-room-buffer' ? + (cursor-sensor-mode) + (setq-local lui-max-buffer-size nil) + ) + +(defclass slack-message-buffer (slack-room-buffer) + ((oldest :initform nil :type (or null string)) + (latest :initform nil :type (or null string)) + (marker-overlay :initform nil) + (update-mark-timer :initform '(nil . nil)) ;; (timestamp . timer) + )) + +(defmethod slack-buffer-last-read ((this slack-message-buffer)) + (with-slots (room) this + (oref room last-read))) + +(cl-defmethod slack-buffer-update-mark ((this slack-message-buffer) &key (force nil)) + (with-slots (room update-mark-timer team) this + (let* ((ts (slack-get-ts)) + (timer-timeout-sec (or (and force 0) 5)) + (prev-mark (or (car update-mark-timer) + (slack-buffer-last-read this))) + (prev-timer (cdr update-mark-timer))) + (when (or force (or (string< prev-mark ts) + (string= prev-mark ts))) + (slack-log (format "%s: update mark to %s" + (slack-room-name room team) + ts) + (oref this team)) + (when (timerp prev-timer) + (cancel-timer prev-timer)) + (cl-labels + ((update-mark () + (slack-buffer-update-mark-request this ts))) + (setq update-mark-timer + (cons ts (run-at-time timer-timeout-sec nil #'update-mark)))))))) + +(defmethod slack-buffer-update-mark-request ((this slack-message-buffer) ts &optional after-success) + (with-slots (room team) this + (when (slack-room-member-p room) + (cl-labels ((on-update-mark (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-buffer-update-mark-request") + (oset room last-read ts) + (slack-buffer-update-marker-overlay this) + (when (functionp after-success) + (funcall after-success))))) + (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))))))) + +(defmethod slack-buffer-send-message ((this slack-message-buffer) message) + (with-slots (room team) this + (slack-message-send-internal message (oref room id) team))) + +(defmethod slack-buffer-latest-ts ((this slack-message-buffer)) + (with-slots (room) this + (slack-if-let* ((latest (oref room latest))) + (slack-ts latest)))) + +(defmethod slack-buffer-buffer ((this slack-message-buffer)) + (let ((buffer-already-exists-p (get-buffer (slack-buffer-name this))) + (buffer (call-next-method)) + (last-read (slack-buffer-last-read this))) + (with-current-buffer buffer + (if (slack-team-mark-as-read-immediatelyp (oref this team)) + (progn + (unless buffer-already-exists-p + (goto-char (marker-position lui-input-marker))) + (and (slack-buffer-latest-ts this) + (slack-buffer-update-mark-request this + (slack-buffer-latest-ts this)))) + (unless (string= "0" last-read) + (unless buffer-already-exists-p + (slack-buffer-goto last-read)) + (slack-buffer-update-marker-overlay this)))) + + buffer)) + +(defmethod slack-buffer-display-unread-threads ((this slack-message-buffer)) + (with-slots (room team) this + (let* ((threads (mapcar #'(lambda (m) (oref m thread)) + (cl-remove-if + #'(lambda (m) + (or (not (slack-message-thread-parentp m)) + (not (< 0 (oref (oref m thread) unread-count))))) + (oref room messages)))) + (alist (mapcar #'(lambda (thread) + (cons (slack-thread-title thread team) thread)) + (cl-sort threads + #'string> + :key #'(lambda (thread) (oref thread thread-ts))))) + (selected (slack-select-from-list (alist "Select Thread: ")))) + (slack-thread-show-messages selected room team)))) + +(defmethod slack-buffer-start-thread ((this slack-message-buffer) ts) + (with-slots (room team) this + (let* ((message (slack-room-find-message room ts)) + (buf (slack-create-thread-message-buffer room team ts))) + (when (slack-reply-broadcast-message-p message) + (error "Can't start thread from broadcasted message")) + (slack-buffer-display buf)))) + +(defmethod slack-buffer-major-mode ((this slack-message-buffer)) + 'slack-message-buffer-mode) + +(defmethod slack-buffer-init-buffer ((this slack-message-buffer)) + (let ((buf (call-next-method))) + (with-current-buffer buf + (funcall (slack-buffer-major-mode this)) + (slack-buffer-set-current-buffer this) + (goto-char (point-min)) + + (slack-buffer-insert-load-more this) + + (with-slots (room team latest) this + (let* ((messages (slack-room-sorted-messages room)) + (latest-message (car (last messages))) + (oldest-message (car messages))) + (cl-loop for m in messages + do (if (and (or (null latest) + (string< latest (slack-ts m))) + (or (not (slack-thread-message-p m)) + (slack-reply-broadcast-message-p m))) + (slack-buffer-insert this m t))) + (when latest-message + (slack-buffer-update-lastest this (slack-ts latest-message))) + (when oldest-message + (slack-buffer-update-oldest this oldest-message)))) + ) + (with-slots (room team) this + (let* ((class (eieio-object-class-name this))) + (slack-buffer-push-new-3 class room team))) + buf)) + + +(cl-defmethod slack-buffer-update ((this slack-message-buffer) message &key replace) + (with-slots (room team) this + (let ((buffer (get-buffer (slack-buffer-name this)))) + (when (and (slack-team-mark-as-read-immediatelyp team) + (slack-buffer-in-current-frame buffer)) + (slack-buffer-update-mark-request this (slack-ts message))) + + (if replace (slack-buffer-replace this message) + (slack-buffer-update-lastest this (slack-ts message)) + (with-current-buffer buffer + (slack-buffer-insert this message)))))) + +(defmethod slack-buffer-display-message-compose-buffer ((this slack-message-buffer)) + (with-slots (room team) this + (let ((buf (slack-create-room-message-compose-buffer room team))) + (slack-buffer-display buf)))) + +(defmethod slack-buffer-update-lastest ((this slack-message-buffer) latest) + (with-slots ((prev-latest latest)) this + (if (or (null prev-latest) + (string< prev-latest latest)) + (setq prev-latest latest)))) + +(defmethod slack-buffer-display-thread ((this slack-message-buffer) ts) + (with-slots (room team) this + (let ((thread (slack-room-find-thread room ts))) + (if thread (slack-thread-show-messages thread room team) + (slack-thread-start))))) + +(defmethod slack-buffer-display-edit-message-buffer ((this slack-message-buffer) ts) + (with-slots (room team) this + (let ((buf (slack-create-edit-message-buffer room team ts))) + (slack-buffer-display buf)))) + +(defmethod slack-create-message-buffer ((room slack-room) team) + (slack-if-let* ((buffer (slack-buffer-find 'slack-message-buffer + room + team))) + buffer + (slack-message-buffer :room room :team team))) + + +(defmethod slack-buffer-share-message ((this slack-message-buffer) ts) + (with-slots (room team) this + (let ((buf (slack-create-message-share-buffer room team ts))) + (slack-buffer-display buf)))) + +(defmethod slack-buffer-add-reaction-to-message + ((this slack-message-buffer) reaction ts) + (with-slots (room team) this + (slack-message-reaction-add reaction ts room team))) + +(defmethod slack-buffer-remove-reaction-from-message + ((this slack-message-buffer) ts) + (with-slots (room team) this + (let* ((message (slack-room-find-message room ts)) + (reactions (slack-message-reactions message)) + (reaction (slack-message-reaction-select reactions))) + (slack-message-reaction-remove reaction ts room team)))) + +(defmethod slack-buffer-pins-remove ((this slack-message-buffer) ts) + (with-slots (room team) this + (slack-message-pins-request slack-message-pins-remove-url + room team ts))) + +(defmethod slack-buffer-pins-add ((this slack-message-buffer) ts) + (with-slots (room team) this + (slack-message-pins-request slack-message-pins-add-url + room team ts))) +(defmethod slack-buffer-remove-star ((this slack-message-buffer) ts) + (with-slots (room team) this + (slack-if-let* ((message (slack-room-find-message room ts))) + (slack-message-star-api-request slack-message-stars-remove-url + (list (cons "channel" (oref room id)) + (slack-message-star-api-params message)) + team)))) + +(defmethod slack-buffer-add-star ((this slack-message-buffer) ts) + (with-slots (room team) this + (slack-if-let* ((message (slack-room-find-message room ts))) + (slack-message-star-api-request slack-message-stars-add-url + (list (cons "channel" (oref room id)) + (slack-message-star-api-params message)) + team)))) + +(defmethod slack-buffer-update-oldest ((this slack-message-buffer) message) + (when (and message (or (null (oref this oldest)) + (string< (slack-ts message) (oref this oldest)))) + (oset this oldest (slack-ts message)))) + +(defmethod slack-buffer-load-missing-messages ((this slack-message-buffer)) + (with-slots (room team) this + (cl-labels + ((request-messages (latest) + (slack-room-history-request room team + :latest latest + :count 100 + :after-success #'after-success)) + (after-success (has-more) + (let* ((messages (slack-room-sorted-messages room)) + (oldest-message (car messages)) + (latest-message (car (last messages)))) + (if has-more + (request-messages (slack-ts latest-message)) + (progn + (with-current-buffer (slack-buffer-buffer this) + (let ((inhibit-read-only t)) + (slack-buffer-delete-overlay this) + (delete-region (point-min) + (marker-position lui-output-marker))) + (slack-buffer-prepare-marker-for-history this) + (slack-buffer-insert-load-more this) + (cl-loop for m in messages + do (slack-buffer-insert this m t)) + (slack-buffer-goto (slack-buffer-last-read this)) + (slack-buffer-update-marker-overlay this)) + (when oldest-message + (slack-buffer-update-oldest this + oldest-message))))))) + (oset room messages nil) + (request-messages nil)))) + +(defmethod slack-buffer-load-more ((this slack-message-buffer)) + (with-slots (room team oldest) this + (let ((current-ts (let ((change (next-single-property-change (point) 'ts))) + (when change + (get-text-property change 'ts)))) + (cur-point (point))) + (cl-labels + ((update-buffer + (messages) + (with-current-buffer (slack-buffer-buffer this) + (slack-buffer-widen + (let ((inhibit-read-only t)) + (goto-char (point-min)) + + (slack-if-let* ((loading-message-end + (slack-buffer-loading-message-end-point this))) + (progn + (slack-buffer-delete-overlay this) + (delete-region (point-min) loading-message-end)) + (message "loading-message-end not found, oldest: %s" oldest)) + + (set-marker lui-output-marker (point-min)) + (if (and messages (< 0 (length messages))) + (slack-buffer-insert-load-more this) + (let ((lui-time-stamp-position nil)) + (lui-insert "(no more messages)\n"))) + + (cl-loop for m in messages + do (slack-buffer-insert this m t)) + (lui-recover-output-marker) + (slack-buffer-update-marker-overlay this) + )) + (if current-ts + (slack-buffer-goto current-ts) + (goto-char cur-point)))) + (after-success (&rest _ignore) + (let ((messages (cl-remove-if #'(lambda (e) + (or (string< oldest e) + (string= oldest e))) + (slack-room-sorted-messages room) + :key #'slack-ts))) + (update-buffer messages) + (slack-buffer-update-oldest this (car messages))))) + (slack-room-history-request room team + :oldest oldest + :after-success #'after-success))))) + +(defmethod slack-buffer-display-pins-list ((this slack-message-buffer)) + (with-slots (room team) this + (cl-labels + ((on-pins-list (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-room-pins-list") + (let* ((buf (slack-create-pinned-items-buffer + room team (plist-get data :items)))) + (slack-buffer-display buf))))) + (slack-request + (slack-request-create + slack-room-pins-list-url + team + :params (list (cons "channel" (oref room id))) + :success #'on-pins-list))))) + +(defmethod slack-buffer-display-user-profile ((this slack-message-buffer)) + (with-slots (room team) this + (let* ((members (cl-remove-if + #'(lambda (e) + (or (slack-user-self-p e team) + (slack-user-hidden-p + (slack-user--find e team)))) + (slack-room-get-members room))) + (user-alist (mapcar #'(lambda (u) (cons (slack-user-name u team) u)) + members)) + (user-id (if (eq 1 (length members)) + (car members) + (slack-select-from-list (user-alist "Select User: "))))) + (let ((buf (slack-create-user-profile-buffer team user-id))) + (slack-buffer-display buf))))) + +(defmethod slack-buffer-delete-overlay ((this slack-message-buffer)) + (when (oref this marker-overlay) + (delete-overlay (oref this marker-overlay)))) + +(defmethod slack-buffer-update-marker-overlay ((this slack-message-buffer)) + (let ((buf (get-buffer (slack-buffer-name this)))) + (and buf (with-current-buffer buf + (let* ((last-read (slack-buffer-last-read this)) + (beg (slack-buffer-ts-eq (point-min) (point-max) last-read)) + (end (and beg (next-single-property-change beg 'ts)))) + (when (and beg end) + (if (oref this marker-overlay) + (move-overlay (oref this marker-overlay) + beg end) + (progn + (oset this marker-overlay (make-overlay beg end)) + (let ((after-string + (propertize "New Message" + 'face + 'slack-new-message-marker-face))) + (overlay-put (oref this marker-overlay) + 'after-string + (format "\n%s" after-string))))))))))) + +(defmethod slack-buffer-replace ((this slack-message-buffer) message) + (call-next-method) + (slack-buffer-update-marker-overlay this)) + +(defmethod slack-file-upload-params ((this slack-message-buffer)) + (with-slots (room team) this + (list (cons "channels" + (mapconcat #'identity + (slack-file-select-sharing-channels + (slack-room-label room team) + team) + ","))))) + +(provide 'slack-message-buffer) +;;; slack-message-buffer.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-buffer.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-buffer.elc new file mode 100644 index 000000000000..41803497b5c0 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-buffer.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-compose-buffer.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-compose-buffer.el new file mode 100644 index 000000000000..7bf581086194 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-compose-buffer.el @@ -0,0 +1,51 @@ +;;; slack-message-compose-buffer.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 + +;; Author: <yuya373@yuya373> +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: + +(require 'eieio) +(require 'slack-buffer) + +(define-derived-mode slack-message-compose-buffer-mode + slack-edit-message-mode + "Slack Compose Message") + +(defclass slack-message-compose-buffer (slack-buffer) ()) + +(defmethod slack-buffer-send-message ((this slack-message-compose-buffer) _message) + (let ((buffer (slack-buffer-buffer this))) + (with-current-buffer buffer + (kill-buffer) + (if (> (count-windows) 1) (delete-window))))) + +(defmethod slack-buffer-init-buffer ((this slack-message-compose-buffer)) + (let ((buf (call-next-method))) + (with-current-buffer buf + (slack-message-compose-buffer-mode) + (slack-buffer-set-current-buffer this)) + buf)) + + +(provide 'slack-message-compose-buffer) +;;; slack-message-compose-buffer.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-compose-buffer.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-compose-buffer.elc new file mode 100644 index 000000000000..4b5fe10abfda --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-compose-buffer.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-edit-buffer.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-edit-buffer.el new file mode 100644 index 000000000000..50dc4bf47496 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-edit-buffer.el @@ -0,0 +1,94 @@ +;;; slack-message-edit-buffer.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 + +;; Author: <yuya373@yuya373> +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: + +(require 'eieio) +(require 'slack-util) +(require 'slack-message-compose-buffer) + +(define-derived-mode slack-message-edit-buffer-mode + slack-edit-message-mode + "Slack Edit Message") + +(defclass slack-message-edit-buffer (slack-message-compose-buffer) + ((room :initarg :room :type slack-room) + (ts :initarg :ts :type string))) + +(defun slack-buffer-find-4 (class a b team) + (slack-if-let* ((buf (cl-find-if #'(lambda (buf) + (string= (buffer-name buf) + (slack-buffer-name class a b team))) + (slot-value team class)))) + (with-current-buffer buf slack-current-buffer))) + +(defun slack-create-edit-message-buffer (room team ts) + (slack-if-let* ((buffer (slack-buffer-find 'slack-message-edit-buffer + room ts team))) + buffer + (slack-message-edit-buffer :room room :team team :ts ts))) + +(defmethod slack-buffer-find :static + ((class slack-message-edit-buffer) room ts team) + (slack-buffer-find-4 class room ts team)) + +(defmethod slack-buffer-name :static + ((class slack-message-edit-buffer) room ts team) + (format "*Slack - %s : %s Edit Message %s" + (oref team name) + (slack-room-name room team) + ts)) + +(defmethod slack-buffer-name ((this slack-message-edit-buffer)) + (with-slots (room team ts) this + (slack-buffer-name (eieio-object-class-name this) + room ts team))) + +(defmethod slack-buffer-init-buffer ((this slack-message-edit-buffer)) + (with-slots (room team ts) this + (let* ((buf (call-next-method)) + (message (slack-room-find-message room ts))) + (with-current-buffer buf + (slack-message-edit-buffer-mode) + (slack-buffer-set-current-buffer this) + (insert (slack-message-unescape-string + (slack-message-get-text message) + team))) + (with-slots (room ts team) this + (slack-buffer-push-new-4 (eieio-object-class-name this) + room + ts + team)) + buf))) + +(defmethod slack-buffer-send-message ((this slack-message-edit-buffer) message) + (with-slots (room team ts) this + (slack-if-let* ((m (slack-room-find-message room ts))) + (progn + (slack-message--edit (oref room id) team ts message) + (call-next-method))))) + + +(provide 'slack-message-edit-buffer) +;;; slack-message-edit-buffer.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-edit-buffer.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-edit-buffer.elc new file mode 100644 index 000000000000..473fa3cd1ea9 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-edit-buffer.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-editor.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-editor.el new file mode 100644 index 000000000000..1c592cf65784 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-editor.el @@ -0,0 +1,130 @@ +;;; slack-message-editor.el --- edit message 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 'slack-util) +(require 'slack-room) +(require 'slack-message-sender) + +(defconst slack-message-edit-url "https://slack.com/api/chat.update") +(defconst slack-message-edit-buffer-name "*Slack - Edit message*") +(defconst slack-message-write-buffer-name "*Slack - Write message*") +(defconst slack-message-share-buffer-name "*Slack - Share message*") +(defconst slack-share-url "https://slack.com/api/chat.shareMessage") +(defvar slack-buffer-function) +(defvar slack-target-ts) +(make-local-variable 'slack-target-ts) +(defvar slack-message-edit-buffer-type) +(make-local-variable 'slack-message-edit-buffer-type) + +(defvar slack-edit-message-mode-map + (let ((keymap (make-sparse-keymap))) + (define-key keymap (kbd "C-s C-m") #'slack-message-embed-mention) + (define-key keymap (kbd "C-s C-c") #'slack-message-embed-channel) + (define-key keymap (kbd "C-c C-k") #'slack-message-cancel-edit) + (define-key keymap (kbd "C-c C-c") #'slack-message-send-from-buffer) + keymap)) + +(define-derived-mode slack-edit-message-mode fundamental-mode "Slack Edit Msg" + "" + (slack-buffer-enable-emojify)) + +(defun slack-message-share () + (interactive) + (slack-if-let* ((buf slack-current-buffer)) + (slack-buffer-share-message buf (slack-get-ts)))) + +(defun slack-message-share--send (team room ts msg) + (let* ((slack-room-list (or (and (object-of-class-p room 'slack-channel) + (slack-message-room-list team)) + (list (cons (slack-room-display-name room team) + room)))) + (share-channel-id (oref (slack-select-from-list + (slack-room-list + "Select Channel: " + :initial + (slack-room-name room team))) + id))) + (cl-labels + ((on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-message-share")))) + (slack-request + (slack-request-create + slack-share-url + team + :type "POST" + :params (list (cons "channel" (oref room id)) + (cons "timestamp" ts) + (cons "text" (slack-message-prepare-links + (slack-escape-message msg) + team)) + (cons "share_channel" share-channel-id)) + :success #'on-success))))) + +(defun slack-message-write-another-buffer () + (interactive) + (slack-if-let* ((buf slack-current-buffer)) + (slack-buffer-display-message-compose-buffer buf))) + +(defmethod slack-message-get-user-id ((m slack-user-message)) + (oref m user)) + +(defun slack-message-edit () + (interactive) + (slack-if-let* ((buf slack-current-buffer)) + (slack-buffer-display-edit-message-buffer buf (slack-get-ts)))) + + +(defun slack-message-cancel-edit () + (interactive) + (let ((buffer (slack-buffer-buffer slack-current-buffer))) + (with-current-buffer buffer + (erase-buffer) + (if (> (count-windows) 1) (delete-window))))) + +(defun slack-message-send-from-buffer () + (interactive) + (slack-if-let* ((buf slack-current-buffer) + (text (buffer-substring-no-properties (point-min) (point-max)))) + (slack-buffer-send-message buf text))) + +(defun slack-message--edit (channel team ts text) + (cl-labels ((on-edit (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-message--edit")))) + (slack-request + (slack-request-create + slack-message-edit-url + team + :type "POST" + :params (list (cons "channel" channel) + (cons "ts" ts) + (cons "text" (slack-message-prepare-links + (slack-escape-message text) + team))) + :success #'on-edit)))) + +(provide 'slack-message-editor) +;;; slack-message-editor.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-editor.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-editor.elc new file mode 100644 index 000000000000..674de8184985 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-editor.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-formatter.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-formatter.el new file mode 100644 index 000000000000..190c3a498ae6 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-formatter.el @@ -0,0 +1,337 @@ +;;; slack-message-formatter.el --- format message text -*- lexical-binding: t; -*- + +;; Copyright (C) 2015 yuya.minami + +;; Author: yuya.minami <yuya.minami@yuyaminami-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 'slack-user) +(require 'slack-room) + +(defface slack-profile-image-face + '((t (:background "#fff"))) + "Face used to profile image." + :group 'slack) + +(defface slack-message-output-text + '((t (:weight normal :height 0.9))) + "Face used to text message." + :group 'slack) + +(defface slack-message-output-header + '((t (:foreground "#FFA000" + :weight bold + :height 1.0 + :underline t))) + "Face used to text message." + :group 'slack) + +(defface slack-message-output-reaction + '((t (:box (:line-width 1 :style released-button)))) + "Face used to reactions." + :group 'slack) + +(defface slack-message-deleted-face + '((t (:strike-through t))) + "Face used to deleted message." + :group 'slack) + +(defface slack-attachment-header + '((t (:weight bold))) + "Face used to shared message header." + :group 'slack) + +(defface slack-attachment-footer + '((t (:height 0.8))) + "Face used to shared message footer." + :group 'slack) + +(defface slack-attachment-pad + '((t (:weight ultra-bold))) + "Face used to shared message pad." + :group 'slack) + +(defface slack-attachment-field-title + '((t (:weight bold :height 1.0))) + "Face used to attachment field title." + :group 'slack) + +(defcustom slack-date-formats + '((date_num . "%Y-%m-%d") + (date . "%B %d,%Y") + (date_short . "%b %d,%Y") + (date_long . "%A %B %d,%Y") + (date_pretty . "%B %d,%Y") + (date_short_pretty . "%b %d,%Y") + (date_long_pretty . "%A %B %d,%Y") + (time . "%H:%M") + (time_secs . "%H:%M:%S")) + "Date formats for Slack's date token. +this format string passed to `format-time-string' function. +see \"Formatting dates\" section in https://api.slack.com/docs/message-formatting" + :group 'slack) + +(defun slack-message-put-header-property (header) + (if header + (propertize header 'face 'slack-message-output-header))) + +(defun slack-message-put-text-property (text) + (if text + (propertize text 'face 'slack-message-output-text))) + +(defun slack-message-put-hard (text) + (if text + (propertize text 'hard t))) + +(defun slack-message-put-deleted-property (text) + (if text + (propertize text 'face 'slack-message-deleted-face))) + +(defun slack-message-time-to-string (ts) + (when ts + (when (stringp ts) + (setf ts (string-to-number ts))) + (format-time-string "%Y-%m-%d %H:%M:%S" + (seconds-to-time ts)))) + +(defmethod slack-message-header ((m slack-message) team) + (slack-message-sender-name m team)) + +(defmethod slack-message-starred-p ((m slack-message)) + (oref m is-starred)) + +(defmethod slack-message-starred-str ((m slack-message)) + (if (slack-message-starred-p m) + ":star:" + "")) + +(defun slack-format-message (&rest args) + (let ((messages args)) + (mapconcat #'identity + (cl-remove-if #'(lambda (e) (< (length e) 1)) messages) + "\n"))) + +(defmethod slack-message-profile-image ((m slack-message) team) + (slack-user-image (slack-user-find m team) team)) + +(defmethod slack-message-header-with-image ((m slack-message) header team) + (let ((image (slack-message-profile-image m team))) + (if image + (format "%s %s" (propertize "image" + 'display image + 'face 'slack-profile-image-face) + header) + header))) + +(defun slack-message-header-to-string (m team) + (let ((header (format "%s %s" + (slack-message-put-header-property + (slack-message-header m team)) + (slack-message-starred-str m)))) + (if (slack-team-display-profile-imagep team) + (slack-message-header-with-image m header team) + header))) + +(defmethod slack-message-body-to-string ((m slack-message) team) + (let ((raw-body (slack-message-body m team))) + (if (oref m deleted-at) + (slack-message-put-deleted-property raw-body) + (slack-message-put-text-property raw-body)))) + + +(defun slack-format-reactions (reactions team) + (concat "\n" + (mapconcat #'(lambda (r) (slack-reaction-to-string r team)) + reactions + " "))) + +(defmethod slack-message-reaction-to-string ((m slack-message) team) + (let ((reactions (slack-message-reactions m))) + (when reactions + (slack-format-reactions reactions team)))) + +(defmethod slack-message-to-string ((m slack-message) team) + (let ((text (if (slot-boundp m 'text) (oref m text)))) + (let* ((header (slack-message-header-to-string m team)) + (attachment-body (slack-message-attachment-body m team)) + (body (slack-message-body-to-string m team)) + (files (mapconcat #'(lambda (file) + (slack-message-to-string file + (slack-ts m) + team)) + (oref m files) "\n")) + (reactions (slack-message-reaction-to-string m team)) + (thread (slack-thread-to-string m team))) + (slack-format-message header body + (if (< 0 (length files)) + (format "\n%s" files) + files) + attachment-body reactions thread)))) + +(defmethod slack-message-body ((m slack-message) team) + (with-slots (text) m + (slack-message-unescape-string text team))) + +(defmethod slack-message-body ((m slack-reply-broadcast-message) team) + (format "Replied to a thread: \n%s" + (slack-message-unescape-string (oref m text) team))) + +(defmethod slack-message-body-to-string ((m slack-file-comment-message) team) + (with-slots (file comment deleted-at) m + (let ((commented-user (slack-user-name (plist-get comment :user) + team)) + (comment-body (plist-get comment :comment)) + (file-id (plist-get file :id)) + (file-user (slack-user-name (plist-get file :user) + team)) + (file-title (plist-get file :title)) + (text-propertize (or + (and deleted-at + #'slack-message-put-deleted-property) + #'slack-message-put-text-property))) + (format "%s %s: %s" + (funcall text-propertize + (format "@%s commented on @%s's file" + commented-user + file-user)) + (slack-file-link-info file-id file-title) + (funcall text-propertize + comment-body))))) + +(defmethod slack-team-display-image-inlinep ((_m slack-message) team) + (slack-team-display-attachment-image-inlinep team)) + +(defmethod slack-message-attachment-body ((m slack-message) team) + (with-slots (attachments) m + (let ((body (mapconcat #'(lambda (attachment) + (slack-message-to-string attachment team)) + attachments "\n\t-\n"))) + (if (< 0 (length body)) + (slack-message-unescape-string (format "\n%s" body) team))))) + +(defmethod slack-message-to-alert ((m slack-message) team) + (with-slots (text attachments files) m + (let ((alert-text + (cond + ((and text (< 0 (length text))) text) + ((and attachments (< 0 (length attachments))) + (mapconcat #'slack-attachment-to-alert attachments " ")) + ((and files (< 0 (length files))) + (mapconcat #'(lambda (file) (oref file title)) files " "))))) + (slack-message-unescape-string alert-text team)))) + +(defun slack-message-unescape-string (text team) + (when text + (let* ((and-unescpaed + (replace-regexp-in-string "&" "&" text)) + (lt-unescaped + (replace-regexp-in-string "<" "<" and-unescpaed)) + (gt-unescaped + (replace-regexp-in-string ">" ">" lt-unescaped))) + (slack-message-unescape-date-format + (slack-message-unescape-command + (slack-message-unescape-user-id + (slack-message-unescape-channel gt-unescaped team) + team)))))) + +(defun slack-message-unescape-user-id (text team) + (let ((user-regexp "<@\\(U.*?\\)>")) + (cl-labels ((unescape-user-id + (text) + (concat "@" (or + (slack-message-replace-user-name text) + (let ((user (slack-user--find (match-string 1 text) team))) + (plist-get user :name)) + (match-string 1 text))))) + (replace-regexp-in-string user-regexp + #'unescape-user-id + text t t)))) + +(defun slack-message-replace-user-name (text) + (let ((user-name-regexp "<@U.*?|\\(.*?\\)>")) + (cl-labels ((replace-user-id-with-name (text) + (match-string 1 text))) + (if (string-match-p user-name-regexp text) + (replace-regexp-in-string user-name-regexp + #'replace-user-id-with-name + text nil t))))) + +(defun slack-message-unescape-date-format (text) + (let ((date-regexp "<!date^\\([[:digit:]]*\\)^\\(.*?\\)\\(\\^.*\\)?|\\(.*\\)>") + (time-format-regexp "{\\(.*?\\)}")) + (cl-labels + ((unescape-date-string + (text) + (let* ((time (match-string 1 text)) + (format-string (match-string 2 text)) + (link (match-string 3 text)) + (fallback (match-string 4 text))) + (replace-regexp-in-string time-format-regexp + #'(lambda (text) + (unescape-datetime-format time + link + text + fallback)) + format-string))) + (unescape-datetime-format + (unix-time link text fallback) + (let* ((match (match-string 1 text)) + (template (cl-assoc (intern match) slack-date-formats))) + (if template + (slack-linkfy + (format-time-string (cdr template) + (float-time (string-to-number unix-time))) + (and link (substring link 1 (length link)))) + fallback)))) + (replace-regexp-in-string date-regexp + #'unescape-date-string + text nil t)))) + +(defun slack-message-unescape-command (text) + (let ((command-regexp "<!\\(.*?\\)>")) + (cl-labels ((unescape-command + (text) + (let ((match (match-string 1 text))) + (if (string-prefix-p "date" match) + (format "<!%s>" match) + (concat "@" match))))) + (replace-regexp-in-string command-regexp + #'unescape-command + text nil t)))) + +(defun slack-message-unescape-channel (text team) + (let ((channel-regexp "<#\\(C.*?\\)\\(|.*?\\)?>")) + (cl-labels ((unescape-channel + (text) + (let ((name (match-string 2 text)) + (id (match-string 1 text))) + (concat "#" (or (and name (substring name 1)) + (slack-if-let* ((room (slack-room-find id team))) + (oref room name) + id)))))) + (replace-regexp-in-string channel-regexp + #'unescape-channel + text t)))) + +(provide 'slack-message-formatter) +;;; slack-message-formatter.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-formatter.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-formatter.elc new file mode 100644 index 000000000000..e72f84b1cbe3 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-formatter.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-notification.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-notification.el new file mode 100644 index 000000000000..35d8f6c67165 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-notification.el @@ -0,0 +1,145 @@ +;;; slack-message-notification.el --- message notification -*- lexical-binding: t; -*- + +;; Copyright (C) 2015 yuya.minami + +;; Author: yuya.minami <yuya.minami@yuyaminami-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 'slack-room) +(require 'slack-message) +(require 'slack-message-formatter) +(require 'slack-buffer) +(require 'slack-im) +(require 'alert) + +(defvar alert-default-style) + +(defcustom slack-message-custom-notifier nil + "Custom notification function.\ntake 3 Arguments.\n(lambda (MESSAGE ROOM TEAM) ...)." + :group 'slack) + +(defcustom slack-message-im-notification-title-format-function + #'(lambda (team-name room-name thread-messagep) + (format "%s - %s" team-name (if thread-messagep + (format "Thread in %s" room-name) + room-name))) + "Function to format notification title for IM message.\ntake 3 Arguments.\n(lambda (TEAM-NAME ROOM-NAME THREAD-MESSAGEP) ...)." + :type 'function + :group 'slack) + +(defcustom slack-message-notification-title-format-function + #'(lambda (team-name room-name thread-messagep) + (format "%s - %s" team-name (if thread-messagep + (format "Thread in #%s" room-name) + (format "#%s" room-name)))) + "Function to format notification title for non-IM message.\ntake 3 Arguments.\n(lambda (TEAM-NAME ROOM-NAME THREAD-MESSAGEP) ...)." + :type 'function + :group 'slack) + +(defcustom slack-alert-icon nil + "String passed as the :icon argument to `alert'." + :type '(choice file (const :tag "Stock alert icon" nil)) + :group 'slack) + +(defvar slack-modeline nil) + +(defcustom slack-modeline-formatter #'slack-default-modeline-formatter + "Format modeline with Arg '((team-name . unread-count))." + :group 'slack) + +(defun slack-message-notify (message room team) + (if slack-message-custom-notifier + (funcall slack-message-custom-notifier message room team) + (slack-message-notify-alert message room team))) + +(defun slack-message-notify-alert (message room team) + (if (and (not (slack-message-minep message team)) + (or (slack-im-p room) + (and (slack-group-p room) (slack-mpim-p room)) + (slack-room-subscribedp room team) + (string-match (format "@%s" (plist-get (oref team self) :name)) + (or (slack-message-body message team) "")))) + (let ((team-name (oref team name)) + (room-name (slack-room-name room team)) + (text (with-temp-buffer + (goto-char (point-min)) + (insert (slack-message-to-alert message team)) + (slack-buffer-buttonize-link) + (buffer-substring-no-properties (point-min) + (point-max)))) + (user-name (slack-message-sender-name message team))) + (if (and (eq alert-default-style 'notifier) + (slack-im-p room) + (or (eq (aref text 0) ?\[) + (eq (aref text 0) ?\{) + (eq (aref text 0) ?\<) + (eq (aref text 0) ?\())) + (setq text (concat "\\" text))) + (alert (if (slack-im-p room) text (format "%s: %s" user-name text)) + :icon slack-alert-icon + :title (if (slack-im-p room) + (funcall slack-message-im-notification-title-format-function + team-name room-name (slack-thread-messagep message)) + (funcall slack-message-notification-title-format-function + team-name room-name (slack-thread-messagep message))) + :category 'slack)))) + +(defmethod slack-message-sender-equalp ((_m slack-message) _sender-id) + nil) + +(defmethod slack-message-minep ((m slack-message) team) + (if team + (with-slots (self-id) team + (slack-message-sender-equalp m self-id)) + (slack-message-sender-equalp m (oref team self-id)))) + +(defun slack-default-modeline-formatter (alist) + "Arg is alist of '((team-name . unread-count))" + (if (= 1 (length alist)) + (format "[ %s: %s ]" (caar alist) (cdar alist)) + (mapconcat #'(lambda (e) (format "[ %s: %s ]" (car e) (cdr e))) + alist " "))) + +(defun slack-enable-modeline () + (add-to-list 'global-mode-string '(:eval slack-modeline) t)) + +(defun slack-update-modeline () + (let ((teams (cl-remove-if-not #'slack-team-modeline-enabledp slack-teams))) + (when (< 0 (length teams)) + (setq slack-modeline + (funcall slack-modeline-formatter + (mapcar #'(lambda (e) (cons (or (oref e modeline-name) (slack-team-name e)) + (slack-team-get-unread-messages e))) + teams))) + (force-mode-line-update)))) + +(defun slack-message-test-notification () + "Debug notification. +Execute this function when cursor is on some message." + (interactive) + (let ((ts (slack-get-ts))) + (with-slots (room team) slack-current-buffer + (let ((message (slack-room-find-message room ts))) + (slack-message-notify message room team))))) + +(provide 'slack-message-notification) +;;; slack-message-notification.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-notification.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-notification.elc new file mode 100644 index 000000000000..8bd41165ab67 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-notification.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-reaction.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-reaction.el new file mode 100644 index 000000000000..5014723c7cc3 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-reaction.el @@ -0,0 +1,146 @@ +;;; slack-message-reaction.el --- adding, removing reaction from message -*- lexical-binding: t; -*- + +;; Copyright (C) 2015 yuya.minami + +;; Author: yuya.minami <yuya.minami@yuyaminami-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 'slack-util) +(require 'slack-message) +(require 'slack-reaction) +(require 'slack-room) +(require 'slack-file) +(require 'slack-request) + +(defconst slack-message-reaction-add-url "https://slack.com/api/reactions.add") +(defconst slack-message-reaction-remove-url "https://slack.com/api/reactions.remove") +(defcustom slack-invalid-emojis '("^:flag_" "tone[[:digit:]]:$" "-" "^[^:].*[^:]$" "\\Ca") + "Invalid emoji regex. Slack server treated some emojis as Invalid." + :group 'slack) + +(defun slack-get-file-id () + (get-text-property 0 'file-id (thing-at-point 'line))) + +(defun slack-file-add-reaction (file-id reaction team) + (slack-message-reaction-add-request (list (cons "name" reaction) + (cons "file" file-id)) + team)) + +(defun slack-message--add-reaction (buf reaction) + (slack-buffer-add-reaction-to-message buf reaction (slack-get-ts))) + +(defun slack-message-add-reaction () + (interactive) + (slack-if-let* ((buf slack-current-buffer) + (reaction (slack-message-reaction-input))) + (slack-message--add-reaction buf reaction))) + +(defun slack-file-remove-reaction (file-id team) + (slack-with-file file-id team + (let ((reaction (slack-message-reaction-select + (slack-message-reactions file)))) + (slack-message-reaction-remove-request + (list (cons "file" file-id) + (cons "name" reaction)) + team)))) + +(defun slack-message-remove-reaction () + (interactive) + (slack-buffer-remove-reaction-from-message slack-current-buffer + (slack-get-ts))) + +(defun slack-message-show-reaction-users () + (interactive) + (slack-if-let* ((buf slack-current-buffer)) + (with-slots (team) buf + (slack-if-let* ((reaction (ignore-errors + (get-text-property (point) + 'reaction)))) + (let ((user-names (slack-reaction-user-names reaction + team))) + (message "reacted users: %s" + (mapconcat #'identity user-names ", "))) + (message "Can't get reaction:"))))) + +(defun slack-message-reaction-select (reactions) + (let ((list (mapcar #'(lambda (r) + (cons (oref r name) + (oref r name))) + reactions))) + (slack-select-from-list + (list "Select Reaction: ") + selected))) + +(defun slack-select-emoji () + (if (fboundp 'emojify-completing-read) + (emojify-completing-read "Select Emoji: ") + (read-from-minibuffer "Emoji: "))) + +(defun slack-message-reaction-input () + (let ((reaction (slack-select-emoji))) + (if (and (string-prefix-p ":" reaction) + (string-suffix-p ":" reaction)) + (substring reaction 1 -1) + reaction))) + +(defun slack-message-reaction-add (reaction ts room team) + (slack-if-let* ((message (slack-room-find-message room ts))) + (let ((params (list (cons "channel" (oref room id)) + (slack-message-get-param-for-reaction message) + (cons "name" reaction)))) + (slack-message-reaction-add-request params team)))) + +(defun slack-message-reaction-add-request (params team) + (cl-labels ((on-reaction-add + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-message-reaction-add-request")))) + (slack-request + (slack-request-create + slack-message-reaction-add-url + team + :type "POST" + :params params + :success #'on-reaction-add)))) + +(defun slack-message-reaction-remove (reaction ts room team) + (slack-if-let* ((message (slack-room-find-message room ts))) + (let ((params (list (cons "channel" (oref room id)) + (slack-message-get-param-for-reaction message) + (cons "name" reaction)))) + (slack-message-reaction-remove-request params team)))) + +(defun slack-message-reaction-remove-request (params team) + (cl-labels ((on-reaction-remove + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-message-reaction-remove-request")))) + (slack-request + (slack-request-create + slack-message-reaction-remove-url + team + :type "POST" + :params params + :success #'on-reaction-remove)))) + +(provide 'slack-message-reaction) +;;; slack-message-reaction.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-reaction.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-reaction.elc new file mode 100644 index 000000000000..a023e9c24731 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-reaction.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-sender.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-sender.el new file mode 100644 index 000000000000..dbd2c1ad53e0 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-sender.el @@ -0,0 +1,177 @@ +;;; slack-message-sender.el --- slack message concern message sending -*- lexical-binding: t; -*- + +;; Copyright (C) 2015 yuya.minami + +;; Author: yuya.minami <yuya.minami@yuyaminami-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 'json) +(require 'slack-util) +(require 'slack-websocket) +(require 'slack-room) +(require 'slack-im) +(require 'slack-group) +(require 'slack-message) +(require 'slack-channel) +(require 'slack-slash-commands) + +(defvar slack-message-minibuffer-local-map nil) +(defvar slack-buffer-function) + +(defun slack-message-send () + (interactive) + (slack-message--send (slack-message-read-from-minibuffer))) + +(defun slack-message-inc-id (team) + (with-slots (message-id) team + (if (eq message-id (1- most-positive-fixnum)) + (setq message-id 1) + (cl-incf message-id)))) + +(defun slack-escape-message (message) + "Escape '<,' '>' & '&' in MESSAGE." + (replace-regexp-in-string + ">" ">" + (replace-regexp-in-string + "<" "<" + (replace-regexp-in-string "&" "&" message)))) + +(defun slack-link-users (message team) + "Add links to all references to valid users in MESSAGE." + (replace-regexp-in-string + "@\\<\\([A-Za-z0-9._\-]+\\)\\>" + #'(lambda (text) + (let* ((username (match-string 1 text)) + (id (slack-user-get-id username team))) + (if id + (format "<@%s|%s>" id username) + (cond + ((string= username "here") "<!here|here>") + ((cl-find username '("channel" "group") :test #'string=) "<!channel>") + ((string= username "everyone") "<!everyone>") + (t text))))) + message t)) + +(defun slack-link-channels (message team) + "Add links to all references to valid channels in MESSAGE." + (let ((channel-ids + (mapcar #'(lambda (x) + (let ((channel (cdr x))) + (cons (slack-room-name channel team) + (slot-value channel 'id)))) + (slack-channel-names team)))) + (replace-regexp-in-string + "#\\<\\([A-Za-z0-9_\-]+\\)\\>" + #'(lambda (text) + (let* ((channel (match-string 1 text)) + (id (cdr (assoc channel channel-ids)))) + (if id + (format "<#%s|%s>" id channel) + text))) + message t))) + +(defun slack-message-prepare-links (message team) + (slack-link-channels (slack-link-users message team) team)) + +(defun slack-message--send (message) + (slack-if-let* ((buf slack-current-buffer) + (team (oref buf team)) + (room (oref buf room))) + (if (string-prefix-p "/" message) + (slack-if-let* ((command-and-arg (slack-slash-commands-parse message team))) + (slack-command-run (car command-and-arg) + team + (oref room id) + :text (cdr command-and-arg)) + (error "Unknown slash command: %s" + (car (split-string message)))) + (slack-buffer-send-message buf message)))) + +(defun slack-message-send-internal (message channel-id team) + (slack-message-inc-id team) + (with-slots (message-id sent-message self-id) team + (let* ((m (list :id message-id + :channel channel-id + :type "message" + :user self-id + :text (slack-message-prepare-links + (slack-escape-message message) + team))) + (obj (slack-message-create m team))) + (slack-ws-send m team) + (puthash message-id obj sent-message)))) + +(defun slack-message-read-room (team) + (let* ((list (slack-message-room-list team)) + (choices (mapcar #'car list)) + (room-name (slack-message-read-room-list "Select Room: " choices)) + (room (cdr (cl-assoc room-name list :test #'string=)))) + room)) + +(defun slack-message-read-room-list (prompt choices) + (let ((completion-ignore-case t)) + (funcall slack-completing-read-function (format "%s" prompt) + choices nil t nil nil choices))) + +(defun slack-message-room-list (team) + (append (slack-group-names team) + (slack-im-names team) + (slack-channel-names team))) + +(defun slack-message-read-from-minibuffer () + (let ((prompt "Message: ")) + (slack-message-setup-minibuffer-keymap) + (read-from-minibuffer + prompt + nil + slack-message-minibuffer-local-map))) + +(defun slack-message-setup-minibuffer-keymap () + (unless slack-message-minibuffer-local-map + (setq slack-message-minibuffer-local-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "RET") 'newline) + (set-keymap-parent map minibuffer-local-map) + map)))) + +(defun slack-message-embed-channel () + (interactive) + (slack-if-let* ((buf slack-current-buffer)) + (with-slots (team) buf + (slack-select-from-list + ((slack-channel-names team) "Select Channel: ") + (insert (concat "#" (slack-room-name selected team))))))) + +(defun slack-message-embed-mention () + (interactive) + (slack-if-let* ((buf slack-current-buffer)) + (with-slots (team) buf + (let* ((pre-defined (list (list "here" :name "here") + (list "channel" :name "channel"))) + (alist (append pre-defined (slack-user-names team)))) + (slack-select-from-list + (alist "Select User: ") + (insert (concat "@" (plist-get selected :name)))))))) + +(provide 'slack-message-sender) +;;; slack-message-sender.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-sender.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-sender.elc new file mode 100644 index 000000000000..1c75c5cf5e9f --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-sender.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-share-buffer.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-share-buffer.el new file mode 100644 index 000000000000..2e999b29d3ac --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-share-buffer.el @@ -0,0 +1,75 @@ +;;; slack-message-share-buffer.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 + +;; Author: <yuya373@yuya373> +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: + +(require 'eieio) +(require 'slack-util) +(require 'slack-room-buffer) + +(define-derived-mode slack-message-share-buffer-mode + slack-message-compose-buffer-mode + "Slack Share Message") + +(defclass slack-message-share-buffer (slack-message-compose-buffer) + ((ts :initarg :ts :type string) + (room :initarg :room :type slack-room))) + +(defun slack-create-message-share-buffer (room team ts) + (slack-if-let* ((buf (slack-buffer-find 'slack-message-share-buffer + room ts team))) + buf + (slack-message-share-buffer :room room :team team :ts ts))) + +(defmethod slack-buffer-find :static ((class slack-message-share-buffer) room ts team) + (slack-buffer-find-4 class room ts team)) + +(defmethod slack-buffer-name :static ((class slack-message-share-buffer) room ts team) + (format "*Slack - %s : %s Share Message - %s" + (oref team name) + (slack-room-name room team) + ts)) + +(defmethod slack-buffer-name ((this slack-message-share-buffer)) + (with-slots (room ts team) this + (slack-buffer-name 'slack-message-share-buffer + room ts team))) + +(defmethod slack-buffer-init-buffer ((this slack-message-share-buffer)) + (let* ((buf (call-next-method))) + (with-current-buffer buf + (slack-message-share-buffer-mode) + (slack-buffer-set-current-buffer this)) + (with-slots (room ts team) this + (slack-buffer-push-new-4 'slack-message-share-buffer + room ts team)) + buf)) + +(defmethod slack-buffer-send-message ((this slack-message-share-buffer) message) + (with-slots (room team ts) this + (slack-message-share--send team room ts message) + (call-next-method))) + +(provide 'slack-message-share-buffer) +;;; slack-message-share-buffer.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-share-buffer.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-share-buffer.elc new file mode 100644 index 000000000000..c3e433223e89 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message-share-buffer.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message.el new file mode 100644 index 000000000000..11360f47c44b --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message.el @@ -0,0 +1,454 @@ +;;; slack-message.el --- slack-message -*- lexical-binding: t; -*- + +;; Copyright (C) 2015 yuya.minami + +;; Author: yuya.minami <yuya.minami@yuyaminami-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 'subr-x) +(require 'slack-util) +(require 'slack-reaction) +(require 'slack-request) +(require 'slack-attachment) + +(defcustom slack-message-custom-delete-notifier nil + "Custom notification function for deleted message.\ntake 3 Arguments.\n(lambda (MESSAGE ROOM TEAM) ...)." + :group 'slack) + +(defconst slack-message-pins-add-url "https://slack.com/api/pins.add") +(defconst slack-message-pins-remove-url "https://slack.com/api/pins.remove") +(defconst slack-message-stars-add-url "https://slack.com/api/stars.add") +(defconst slack-message-stars-remove-url "https://slack.com/api/stars.remove") + +(defclass slack-message () + ((type :initarg :type :type string) + (subtype :initarg :subtype) + (channel :initarg :channel :initform nil) + (ts :initarg :ts :type string :initform "") + (text :initarg :text :type (or null string) :initform nil) + (item-type :initarg :item_type) + (attachments :initarg :attachments :type (or null list) :initform nil) + (reactions :initarg :reactions :type (or null list)) + (is-starred :initarg :is_starred :type boolean :initform nil) + (pinned-to :initarg :pinned_to :type (or null list)) + (deleted-at :initarg :deleted-at :initform nil) + (thread :initarg :thread :initform nil) + (thread-ts :initarg :thread_ts :initform nil) + (hide :initarg :hide :initform nil) + (files :initarg :files :initform '()) + (edited :initarg :edited :initform nil) + (is-ephemeral :initarg :is_ephemeral :initform nil))) + +(defclass slack-message-edited () + ((user :initarg :user :type string) + (ts :initarg :ts :type string))) + +(defclass slack-reply (slack-message) + ((user :initarg :user :initform nil) + (reply-to :initarg :reply_to :type integer) + (id :initarg :id :type integer))) + +(defclass slack-user-message (slack-message) + ((user :initarg :user :type string) + (id :initarg :id) + (inviter :initarg :inviter))) + +(defclass slack-reply-broadcast-message (slack-user-message) + ((broadcast-thread-ts :initarg :broadcast_thread_ts :initform nil))) + +(defclass slack-bot-message (slack-message) + ((bot-id :initarg :bot_id :type string) + (username :initarg :username :type string :initform "") + (icons :initarg :icons))) + +(defclass slack-file-comment-message (slack-message) + ((file :initarg :file :initform nil) + (comment :initarg :comment :initform nil))) + +(defmethod slack-message-sender-name ((m slack-file-comment-message) team) + (with-slots (comment) m + (slack-user-name (plist-get comment :user) team))) + +(defmethod slack-message-sender-id ((m slack-file-comment-message)) + (with-slots (comment) m + (plist-get comment :user))) + +(defgeneric slack-message-sender-name (slack-message team)) +(defgeneric slack-message-to-string (slack-message)) +(defgeneric slack-message-to-alert (slack-message)) +(defmethod slack-message-bot-id ((_this slack-message)) nil) + +(defgeneric slack-room-buffer-name (room team)) + +(defun slack-room-find (id team) + (if (and id team) + (cl-labels ((find-room (room) + (string= id (oref room id)))) + (cond + ((string-prefix-p "F" id) (slack-file-room-obj team)) + ((string-prefix-p "C" id) (cl-find-if #'find-room + (oref team channels))) + ((string-prefix-p "G" id) (cl-find-if #'find-room + (oref team groups))) + ((string-prefix-p "D" id) (cl-find-if #'find-room + (oref team ims))) + ((string-prefix-p "Q" id) (cl-find-if #'find-room + (oref team search-results))))))) + +(defun slack-reaction-create (payload) + (apply #'slack-reaction "reaction" + (slack-collect-slots 'slack-reaction payload))) + +(defmethod slack-message-set-attachments ((m slack-message) payload) + (let ((attachments (append (plist-get payload :attachments) nil))) + (if (< 0 (length attachments)) + (oset m attachments + (mapcar #'slack-attachment-create attachments)))) + m) + +(defmethod slack-message-set-file ((m slack-message) payload team) + (let ((files (mapcar #'(lambda (file) (slack-file-create file)) + (plist-get payload :files)))) + (oset m files files) + m)) + +(defmethod slack-message-set-thread ((m slack-message) team payload) + (when (slack-message-thread-parentp m) + (oset m thread (slack-thread-create m team payload)))) + +(defun slack-reply-broadcast-message-create (payload) + (let ((parent (cl-first (plist-get payload :attachments)))) + (plist-put payload :broadcast_thread_ts (plist-get parent :ts)) + (apply #'slack-reply-broadcast-message "reply-broadcast" + (slack-collect-slots 'slack-reply-broadcast-message payload)))) + +(cl-defun slack-message-create (payload team &key room) + (when payload + (plist-put payload :reactions (append (plist-get payload :reactions) nil)) + (plist-put payload :attachments (append (plist-get payload :attachments) nil)) + (plist-put payload :pinned_to (append (plist-get payload :pinned_to) nil)) + (if room + (plist-put payload :channel (oref room id))) + (cl-labels + ((create-message + (payload) + (let ((subtype (plist-get payload :subtype))) + (cond + ((plist-member payload :reply_to) + (apply #'slack-reply "reply" + (slack-collect-slots 'slack-reply payload))) + ((or (and subtype (or (string-equal "reply_broadcast" subtype) + (string= "thread_broadcast" subtype))) + (plist-get payload :reply_broadcast)) + (slack-reply-broadcast-message-create payload)) + ((and (plist-member payload :user) (plist-get payload :user)) + (apply #'slack-user-message "user-msg" + (slack-collect-slots 'slack-user-message payload))) + ((and subtype (string= "bot_message" subtype)) + (apply #'slack-bot-message "bot-msg" + (slack-collect-slots 'slack-bot-message payload))) + ((and subtype (string= "file_comment" subtype)) + (apply #'slack-file-comment-message "file_comment" + (slack-collect-slots 'slack-file-comment-message payload))) + (t (progn + (slack-log (format "Unknown Message Type: %s" payload) + team :level 'warn) + (apply #'slack-message "unknown message" + (slack-collect-slots 'slack-message payload)))))))) + + (let ((message (create-message payload))) + (when message + (slack-message-set-edited message payload) + (slack-message-set-attachments message payload) + (oset message reactions + (mapcar #'slack-reaction-create (plist-get payload :reactions))) + (slack-message-set-file message payload team) + (slack-message-set-thread message team payload) + message))))) + +(defmethod slack-message-set-edited ((this slack-message) payload) + (if (plist-get payload :edited) + (oset this edited (apply #'make-instance slack-message-edited + (slack-collect-slots 'slack-message-edited + (plist-get payload :edited)))))) + +(defmethod slack-message-edited-at ((this slack-message)) + (with-slots (edited) this + (when edited + (oref edited ts)))) + +(defmethod slack-message-equal ((m slack-message) n) + (string= (slack-ts m) (slack-ts n))) + +(defmethod slack-message-get-thread ((parent slack-message) team) + (let ((thread (oref parent thread))) + (unless thread + (oset parent thread (slack-thread-create parent team))) + (oref parent thread))) + +(defmethod slack-message-sender-name ((m slack-message) team) + (slack-user-name (oref m user) team)) + +(defmethod slack-message-sender-id ((m slack-message)) + (oref m user)) + +(defun slack-message-pins-add () + (interactive) + (slack-if-let* ((buf slack-current-buffer)) + (slack-buffer-pins-add buf (slack-get-ts)))) + +(defun slack-message-pins-remove () + (interactive) + (slack-if-let* ((buf slack-current-buffer)) + (slack-buffer-pins-remove buf (slack-get-ts)))) + +(defun slack-message-pins-request (url room team ts) + (cl-labels ((on-pins-add + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-message-pins-request")))) + (slack-request + (slack-request-create + url + team + :params (list (cons "channel" (oref room id)) + (cons "timestamp" ts)) + :success #'on-pins-add + )))) + +(defmethod slack-ts ((this slack-message)) + (oref this ts)) + +(defun slack-ts-to-time (ts) + (seconds-to-time (string-to-number ts))) + +(defun slack-message-time-stamp (message) + (slack-ts-to-time (slack-ts message))) + +(defmethod slack-user-find ((m slack-message) team) + (slack-user--find (slack-message-sender-id m) team)) + +(defun slack-message-copy-link () + (interactive) + (slack-buffer-copy-link slack-current-buffer (slack-get-ts))) + +(defmethod slack-message-star-added ((m slack-message)) + (oset m is-starred t)) + +(defmethod slack-message-star-removed ((m slack-message)) + (oset m is-starred nil)) + +(defun slack-message-star-api-request (url params team) + (cl-labels + ((on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data url)))) + (slack-request + (slack-request-create + url + team + :params params + :success #'on-success)))) + +(defun slack-message-remove-star () + (interactive) + (slack-buffer-remove-star slack-current-buffer (slack-get-ts))) + +(defun slack-message-add-star () + (interactive) + (slack-buffer-add-star slack-current-buffer (slack-get-ts))) + +(defmethod slack-message-star-api-params ((m slack-message)) + (cons "timestamp" (slack-ts m))) + +(defmethod slack-reaction-delete ((this slack-message) reaction) + (with-slots (reactions) this + (setq reactions (slack-reaction--delete reactions reaction)))) + +(defmethod slack-reaction-push ((this slack-message) reaction) + (push reaction (oref this reactions))) + +(defmethod slack-reaction-find ((m slack-message) reaction) + (slack-reaction--find (oref m reactions) reaction)) + +(defmethod slack-message-reactions ((this slack-message)) + (oref this reactions)) + +(defmethod slack-message-get-param-for-reaction ((m slack-message)) + (cons "timestamp" (slack-ts m))) + +(defmethod slack-message-append-reaction ((m slack-message) reaction &optional _type _file-id) + (slack-if-let* ((old-reaction (slack-reaction-find m reaction))) + (slack-reaction-join old-reaction reaction) + (slack-reaction-push m reaction))) + +(defmethod slack-message-pop-reaction ((m slack-message) reaction &optional _type _file-id) + (slack-message--pop-reaction m reaction)) + +(defun slack-message--pop-reaction (message reaction) + (let* ((old-reaction (slack-reaction-find message reaction)) + (decl-p (< 1 (oref old-reaction count)))) + (if decl-p + (with-slots (count users) old-reaction + (cl-decf count) + (setq users (cl-remove-if + #'(lambda (old-user) + (cl-find old-user + (oref reaction users) + :test #'string=)) + users))) + (slack-reaction-delete message reaction)))) + +(defmethod slack-message-get-text ((m slack-message)) + (oref m text)) + +(defmethod slack-thread-message-update-buffer ((message slack-message) + room team replace) + (slack-if-let* ((parent (slack-room-find-thread-parent room message))) + (progn + (slack-room-update-buffer room team parent t) + (if (slack-reply-broadcast-message-p message) + (slack-room-update-buffer room team message replace)) + (slack-if-let* ((thread (slack-message-get-thread parent team))) + (progn + (slack-if-let* ((buf (slack-buffer-find 'slack-thread-message-buffer + room + (oref thread thread-ts) + team))) + (slack-buffer-update buf message :replace replace))))))) + +(defmethod slack-message-update ((message slack-message) team &optional replace no-notify) + (slack-if-let* + ((room (slack-room-find (oref message channel) team)) + (ts (slack-ts message)) + (no-same-message (if replace t + (not (slack-room-find-message room ts))))) + + (progn + (slack-room-push-message room message) + (slack-room-update-latest room message) + (if (slack-thread-message-p message) + (slack-thread-message-update-buffer message room team replace) + (slack-room-update-buffer room team message replace) + (slack-room-inc-unread-count room)) + + (unless no-notify + (slack-message-notify message room team)) + (slack-update-modeline)))) + +(defun slack-message-delete () + (interactive) + (slack-if-let* ((buf slack-current-buffer)) + (slack-buffer-delete-message buf (slack-get-ts)))) + +(defmethod slack-message-deleted ((message slack-message) room team) + (if (slack-thread-message-p message) + (slack-if-let* ((parent (slack-room-find-thread-parent room message)) + (thread (slack-message-get-thread parent team))) + (progn + (slack-thread-delete-message thread message) + (slack-if-let* ((buffer (slack-buffer-find 'slack-thread-message-buffer + room + (oref thread thread-ts) + team))) + (slack-buffer-message-delete buffer (slack-ts message))) + (slack-message-update parent team t))) + (slack-if-let* ((buf (slack-buffer-find 'slack-message-buffer + room + team))) + (slack-buffer-message-delete buf (slack-ts message)))) + + (if slack-message-custom-delete-notifier + (funcall slack-message-custom-delete-notifier message room team) + (alert "message deleted" + :icon slack-alert-icon + :title (format "\\[%s] from %s" + (slack-room-display-name room team) + (slack-message-sender-name message team)) + :category 'slack))) + +(defmethod slack-message-changed--copy ((this slack-message) other) + (let ((changed nil)) + (with-slots (text attachments edited) this + (unless (string= text (oref other text)) + (setq text (oref other text)) + (setq changed t)) + (setq attachments (oref other attachments)) + (setq edited (oref other edited))) + changed)) + +(defmethod slack-thread-message-p ((this slack-message)) + (and (oref this thread-ts) + (not (string= (slack-ts this) (oref this thread-ts))))) + +(defmethod slack-thread-message-p ((this slack-reply-broadcast-message)) + (call-next-method)) + +(defmethod slack-message-thread-parentp ((m slack-message)) + (let* ((thread (oref m thread)) + (thread-ts (or (and thread (oref thread thread-ts)) + (oref m thread-ts)))) + (and thread-ts (string= (slack-ts m) thread-ts)))) + +(defun slack-message-update-mark () + "Update Channel's last-read marker to this message." + (interactive) + (slack-if-let* ((buffer slack-current-buffer)) + (slack-buffer-update-mark buffer :force t))) + +(defmethod slack-message--inspect ((this slack-message) room team) + (format "RAW: %s\nROOM: %s\nMESSAGE: %s\nATTACHMENTS: %s - %s\nFILES: %s - %s" + (oref this text) + (oref room id) + (eieio-object-class this) + (length (oref this attachments)) + (mapcar (lambda (e) (format "\n(TITLE: %s\nPRETEXT: %s\nTEXT: %s)" + (slack-message-unescape-channel + (oref e title) + team) + (oref e pretext) + (oref e text))) + (oref this attachments)) + (length (oref this files)) + (mapcar (lambda (e) (format "(TITLE: %s)" + (oref e title))) + (oref this files)))) + +(defmethod slack-message--inspect ((this slack-file-comment-message) room team) + (let ((super (call-next-method))) + (with-slots (file comment) this + (format "%s\nFILE:%s\nCOMMENT:%s" + super + file comment)))) + +(defun slack-message-inspect () + (interactive) + (slack-if-let* ((ts (slack-get-ts)) + (buffer slack-current-buffer)) + (with-slots (room team) buffer + (slack-if-let* ((message (slack-room-find-message room ts)) + (text (slack-message--inspect message room team))) + (message "%s" text))))) + +(provide 'slack-message) +;;; slack-message.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message.elc new file mode 100644 index 000000000000..ef0d8a57365e --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-message.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-pinned-item.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-pinned-item.el new file mode 100644 index 000000000000..dfb9a11a4e4c --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-pinned-item.el @@ -0,0 +1,43 @@ +;;; slack-pinned-item.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 + +;; Author: <yuya373@yuya373> +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: + +(require 'eieio) + +(defclass slack-pinned-item () + ((message :initarg :message))) + +(defun slack-pinned-item-create (message) + (slack-pinned-item :message message)) + +(defmethod slack-ts ((this slack-pinned-item)) + (slack-ts (oref this message))) + +(defmethod slack-message-to-string ((this slack-pinned-item) team) + (with-slots (message) this + (slack-message-to-string message team))) + +(provide 'slack-pinned-item) +;;; slack-pinned-item.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-pinned-item.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-pinned-item.elc new file mode 100644 index 000000000000..af92bb6a9713 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-pinned-item.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-pinned-items-buffer.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-pinned-items-buffer.el new file mode 100644 index 000000000000..536195a1553a --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-pinned-items-buffer.el @@ -0,0 +1,102 @@ +;;; slack-pinned-items-buffer.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 + +;; Author: <yuya373@yuya373> +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: + +(require 'eieio) +(require 'slack-util) +(require 'slack-room-buffer) + +(define-derived-mode slack-pinned-items-buffer-mode slack-buffer-mode "Slack Pinned Items") + +(defclass slack-pinned-items-buffer (slack-room-buffer) + ((items :initarg :items :type list))) + +(defmethod slack-buffer-name :static ((class slack-pinned-items-buffer) room team) + (format "%s %s" (call-next-method) "Pinned Items")) + +(defmethod slack-buffer-name ((this slack-pinned-items-buffer)) + (with-slots (room team) this + (slack-buffer-name 'slack-pinned-items-buffer + room team))) + +(defmethod slack-buffer-buffer ((this slack-pinned-items-buffer)) + (slack-if-let* ((buf (get-buffer (slack-buffer-name this)))) + (progn + (slack-pinned-items-buffer-insert-items this) + buf) + (slack-buffer-init-buffer this))) + +(defmethod slack-pinned-items-buffer-insert-items ((this slack-pinned-items-buffer)) + (let* ((buf (get-buffer (slack-buffer-name this))) + (header-face '(:underline t :weight bold)) + (buf-header (propertize "Pinned Items\n" 'face header-face))) + (with-current-buffer buf + (let ((inhibit-read-only t)) + (delete-region (point-min) lui-output-marker)) + (let ((lui-time-stamp-position nil)) + (lui-insert buf-header t)) + (with-slots (team items) this + (if (< 0 (length items)) + (cl-loop for m in items + do (slack-buffer-insert this m t)) + (let ((inhibit-read-only t)) + (insert "No Pinned Items"))))))) + +(defmethod slack-buffer-init-buffer ((this slack-pinned-items-buffer)) + (let* ((buf (call-next-method))) + (with-current-buffer buf + (slack-pinned-items-buffer-mode) + (slack-buffer-set-current-buffer this)) + (slack-pinned-items-buffer-insert-items this) + (with-slots (room team) this + (slack-buffer-push-new-3 'slack-pinned-items-buffer room team)) + buf)) + +(defun slack-create-pinned-items-buffer (room team items) + + (cl-labels + ((create-item + (item) + (let ((type (plist-get item :type))) + (slack-pinned-item-create + (cond + ((string= type "message") + (slack-message-create (plist-get item :message) + team :room room)) + ((string= type "file") + (or (slack-file-find (plist-get (plist-get item :file) :id) team) + (slack-file-create (plist-get item :file))))))))) + (slack-if-let* ((buf (slack-buffer-find 'slack-pinned-items-buffer room team))) + (progn + (oset buf items (mapcar #'create-item items)) + buf) + (slack-pinned-items-buffer :room room + :team team + :items (mapcar #'create-item items))))) + + + +(provide 'slack-pinned-items-buffer) +;;; slack-pinned-items-buffer.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-pinned-items-buffer.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-pinned-items-buffer.elc new file mode 100644 index 000000000000..06b81d65fd60 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-pinned-items-buffer.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-pkg.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-pkg.el new file mode 100644 index 000000000000..acb78f329c89 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-pkg.el @@ -0,0 +1,11 @@ +(define-package "slack" "20180913.651" "Slack client for Emacs" + '((websocket "1.8") + (request "0.2.0") + (oauth2 "0.10") + (circe "2.2") + (alert "1.2") + (emojify "0.2")) + :url "https://github.com/yuya373/emacs-slack") +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-reaction.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-reaction.el new file mode 100644 index 000000000000..d0cff1a80370 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-reaction.el @@ -0,0 +1,117 @@ +;;; slack-reaction.el --- deal with reactions -*- lexical-binding: t; -*- + +;; Copyright (C) 2015 yuya.minami + +;; Author: yuya.minami <yuya.minami@yuyaminami-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) + +(defclass slack-reaction () + ((name :initarg :name :type string) + (count :initarg :count :type integer) + (users :initarg :users :initform ()))) + +(defmethod slack-reaction-join ((r slack-reaction) other) + (if (string= (oref r name) (oref other name)) + (progn + (cl-incf (oref r count)) + (oset r users (append (oref other users) (oref r users))) + r))) + +(defmethod slack-reaction-user-names ((r slack-reaction) team) + (with-slots (users) r + (mapcar #'(lambda (u) (slack-user-name u team)) + users))) + +(defmethod slack-equalp ((r slack-reaction) other) + (slack-reaction-equalp r other)) + +(defmethod slack-reaction-equalp ((r slack-reaction) other) + (string= (oref r name) (oref other name))) + +(defmethod slack-reaction-help-text ((r slack-reaction) team) + (let ((user-names (slack-reaction-user-names r team))) + (format "%s reacted with :%s:" + (mapconcat #'identity user-names ", ") + (oref r name)))) + +(defvar slack-reaction-keymap + (let ((keymap (make-sparse-keymap))) + (define-key keymap (kbd "RET") #'slack-reaction-toggle) + (define-key keymap [mouse-1] #'slack-reaction-toggle) + keymap)) + +(defun slack-reaction-toggle () + (interactive) + (slack-if-let* ((buffer slack-current-buffer) + (reaction (get-text-property (point) 'reaction)) + (reaction-name (oref reaction name)) + (reaction-users (oref reaction users)) + (team (oref buffer team)) + (self-id (oref team self-id))) + (if (cl-find-if #'(lambda (id) (string= id self-id)) reaction-users) + (slack-message-reaction-remove reaction-name + (slack-get-ts) + (oref buffer room) + team) + (slack-message--add-reaction buffer reaction-name)))) + +(defun slack-reaction-help-echo (_window _string pos) + (slack-if-let* ((buffer slack-current-buffer) + (reaction (get-text-property pos 'reaction)) + (team (oref buffer team))) + (slack-reaction-help-text reaction team))) + +(defmethod slack-reaction-to-string ((r slack-reaction) team) + (propertize (format " :%s: %d " (oref r name) (oref r count)) + 'face 'slack-message-output-reaction + 'mouse-face 'highlight + 'keymap slack-reaction-keymap + 'reaction r + 'help-echo #'slack-reaction-help-echo)) + +(defun slack-reaction-echo-description () + (slack-if-let* ((buffer slack-current-buffer) + (reaction (get-text-property (point) 'reaction)) + (team (oref buffer team))) + (message (slack-reaction-help-text reaction team)))) + +(defun slack-reaction-notify (payload team room) + (let* ((user-id (plist-get payload :user)) + (reaction (plist-get payload :reaction)) + (msg (slack-user-message "msg" + :text (format "added reaction %s" reaction) + :user user-id))) + (slack-message-notify msg room team))) + +(defun slack-reaction--find (reactions reaction) + (cl-find-if #'(lambda (e) (slack-reaction-equalp e reaction)) + reactions)) + +(defun slack-reaction--delete (reactions reaction) + (cl-delete-if #'(lambda (e) (slack-reaction-equalp e reaction)) + reactions)) + +(provide 'slack-reaction) +;;; slack-reaction.el ends here + diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-reaction.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-reaction.elc new file mode 100644 index 000000000000..220b289a5bee --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-reaction.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-reminder.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-reminder.el new file mode 100644 index 000000000000..8d2ab413ddab --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-reminder.el @@ -0,0 +1,237 @@ +;;; slack-reminder.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2016 ๅๅชไน + +;; Author: ๅๅชไน <yuyaminami@minamiyuuya-no-MacBook.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 'slack-room) +(require 'slack-team) +(require 'slack-request) + +(defconst slack-reminder-list-url "https://slack.com/api/reminders.list") +(defconst slack-reminder-delete-url "https://slack.com/api/reminders.delete") +(defconst slack-reminder-complete-url "https://slack.com/api/reminders.complete") +(defconst slack-reminder-info-url "https://slack.com/api/reminders.info") + +(defclass slack-reminder-base () + ((id :initarg :id :type string) + (creator :initarg :creator :type string) + (user :initarg :user :type string) + (text :initarg :text :type string))) + +(defclass slack-recurring-reminder (slack-reminder-base) + ()) + +(defclass slack-reminder (slack-reminder-base) + ((time :initarg :time :type integer) + (complete-ts :initarg :complete_ts :type integer))) + +(defmethod slack-reminder-user ((r slack-reminder-base) team) + (slack-user-find r team)) + +(defmethod slack-reminder-creator ((r slack-reminder-base) team) + (slack-user--find (oref r creator) team)) + +(defmethod slack-reminder-completedp ((r slack-reminder)) + (not (eq 0 (oref r complete-ts)))) + +(defmethod slack-reminder-completedp ((_r slack-recurring-reminder)) + nil) + +(defun slack-reminder-create (payload) + (let ((klass (if (eq :json-false (plist-get payload :recurring)) + 'slack-reminder + 'slack-recurring-reminder))) + (apply #'make-instance klass + (slack-collect-slots klass payload)))) + +(defmethod slack-reminder-to-body ((r slack-reminder)) + (with-slots (text time complete-ts) r + (let ((time-str (format "Remind At: %s" + (slack-message-time-to-string + (number-to-string time)))) + (completed (format "Completed: %s" + (if (eq complete-ts 0) + "Not Yet" + (slack-message-time-to-string + (number-to-string complete-ts)))))) + (format "%s\n%s\n\n%s" time-str completed text)))) + +(defmethod slack-reminder-to-body ((r slack-recurring-reminder)) + (oref r text)) + +(defmethod slack-reminder-to-string ((r slack-reminder-base) team) + (with-slots (creator user) r + (let* ((header (slack-message-put-header-property + (format "From: %s To: %s" + (slack-user-name creator team) + (slack-user-name user team)))) + (body (slack-reminder-to-body r))) + (format "%s\n%s\n\n" header body)))) + +(defmethod slack-create-reminder-buffer ((team slack-team)) + (let* ((buf-name "*Slack - Reminders*") + (buf (get-buffer-create buf-name))) + (with-current-buffer buf + (setq buffer-read-only nil) + (erase-buffer) + (goto-char (point-min)) + (with-slots (reminders) team + (cl-loop for reminder in reminders + do (insert (slack-reminder-to-string reminder team)))) + (setq buffer-read-only t)) + buf)) + +(defmethod slack-reminder-sort-key ((r slack-reminder)) + (oref r time)) + +(defmethod slack-reminder-sort-key ((r slack-recurring-reminder)) + 0) + +(defun slack-reminder-sort (team) + (with-slots (reminders) team + (setq reminders + (cl-sort reminders #'< + :key #'(lambda (r) (slack-reminder-sort-key r)))))) + +(defun slack-reminder-list () + (interactive) + (let ((team (slack-team-select))) + (cl-labels + ((on-reminder-list + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-reminder-list") + (oset team reminders + (cl-loop + for payload in (slack-decode + (append (plist-get data :reminders) + nil)) + collect (slack-reminder-create payload))) + (slack-reminder-sort team) + (if (< 0 (length (oref team reminders))) + (funcall + slack-buffer-function + (slack-create-reminder-buffer team)) + (message "No Reminders!"))))) + (slack-request + (slack-request-create + slack-reminder-list-url + team + :success #'on-reminder-list))))) + +(defmethod slack-reminders-alist ((team slack-team) &optional filter) + (cl-labels ((text (r) + (with-slots (creator user text) r + (format "Creator: %s Target: %s Content: %s" + (slack-user-name creator team) + (slack-user-name user team) + text)))) + (with-slots (reminders) team + (mapcar #'(lambda (r) (cons (text r) r)) + (if filter + (cl-remove-if-not #'(lambda (r) (funcall filter r)) + reminders) + reminders))))) + +(defmethod slack-team-delete-reminder ((team slack-team) r) + (with-slots (reminders) team + (setq reminders + (cl-remove-if #'(lambda (e) + (string= (oref e id) (oref r id))) + reminders)))) + +(defun slack-reminder-select (team &optional filter) + (slack-select-from-list + ((slack-reminders-alist team filter) "Select: "))) + +(defun slack-reminder-delete () + (interactive) + (let* ((team (slack-team-select)) + (reminder (slack-reminder-select team))) + (cl-labels + ((on-reminder-delete (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-reminder-delete") + (slack-team-delete-reminder team reminder) + (message "Reminder Deleted!")))) + (slack-request + (slack-request-create + slack-reminder-delete-url + team + :params (list (cons "reminder" (oref reminder id))) + :success #'on-reminder-delete))))) + +(defmethod slack-reminder-info ((r slack-reminder-base) team callback) + (cl-labels + ((on-reminder-info (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-reminder-info") + (let ((reminder (slack-reminder-create + (plist-get (slack-decode data) + :reminder)))) + (funcall callback reminder))))) + (slack-request + (slack-request-create + slack-reminder-info-url + team + :params (list (cons "reminder" (oref r id))) + :success #'on-reminder-info)))) + +(defmethod slack-reminder-refresh ((r slack-reminder-base) team) + (slack-reminder-info + r team + #'(lambda (reminder) + (with-slots (reminders) team + (setq reminders + (cl-remove-if #'(lambda (e) (string= (oref e id) + (oref reminder id))) + reminders)) + (push reminder reminders)) + (message "Reminder Updated!")))) + +(defun slack-reminder-complete () + (interactive) + (let* ((team (slack-team-select)) + (reminder (slack-reminder-select + team + #'(lambda (r) + (not (slack-reminder-completedp r)))))) + (cl-labels + ((on-reminder-complete (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-reminder-complete") + (slack-reminder-refresh reminder team)))) + (slack-request + (slack-request-create + slack-reminder-complete-url + team + :params (list (cons "reminder" (oref reminder id))) + :success #'on-reminder-complete))))) + +(defmethod slack-user-find ((r slack-reminder-base) team) + (slack-user--find (oref r user) team)) + +(provide 'slack-reminder) +;;; slack-reminder.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-reminder.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-reminder.elc new file mode 100644 index 000000000000..19a16c9e6cc1 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-reminder.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-reply.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-reply.el new file mode 100644 index 000000000000..8a6489e88bb4 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-reply.el @@ -0,0 +1,49 @@ +;;; slack-reply.el ---handle reply from slack -*- lexical-binding: t; -*- + +;; Copyright (C) 2015 yuya.minami + +;; Author: yuya.minami <yuya.minami@yuyaminami-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 'slack-message) + +(defmethod slack-message-handle-reply ((m slack-reply) team) + (with-slots (reply-to) m + (let ((sent-msg (slack-message-find-sent m team))) + (if sent-msg + (progn + (oset sent-msg ts (slack-ts m)) + (slack-message-update sent-msg team)))))) + +(defmethod slack-message-find-sent ((m slack-reply) team) + (with-slots (reply-to) m + (with-slots (sent-message) team + (let ((found (gethash reply-to sent-message))) + (remhash reply-to sent-message) + found)))) + +(defmethod slack-message-sender-equalp ((m slack-reply) sender-id) + (string= (oref m user) sender-id)) + + +(provide 'slack-reply) +;;; slack-reply.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-reply.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-reply.elc new file mode 100644 index 000000000000..d5c798fa0792 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-reply.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-request-worker.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-request-worker.el new file mode 100644 index 000000000000..13068f94800c --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-request-worker.el @@ -0,0 +1,143 @@ +;;; slack-request-worker.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2018 ๅๅชไน + +;; Author: ๅๅชไน <yuyaminami@minamiyuuya-no-MacBook.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 'slack-util) +(require 'slack-request) +(require 'slack-team) + +(defcustom slack-request-worker-max-request-limit 30 + "Max request count perform simultaneously." + :group 'slack) + +(defvar slack-request-worker-instance nil) + +(defclass slack-request-worker () + ((queue :initform '() :type list) + (timer :initform nil) + (current-request-count :initform 0 :type integer) + )) + +(defun slack-request-worker-create () + "Create `slack-request-worker' instance." + (make-instance 'slack-request-worker)) + +(defmethod slack-request-worker-push ((this slack-request-worker) req) + (let ((l '())) + (cl-pushnew req (oref this queue) + :test #'slack-equalp))) + +(defun slack-request-worker-set-timer () + (cl-labels + ((on-timeout () + (slack-request-worker-execute) + (when (timerp slack-request-worker-instance) + (cancel-timer slack-request-worker-instance)) + (slack-request-worker-set-timer))) + (oset slack-request-worker-instance timer + (run-at-time 1 nil #'on-timeout)))) + +(defun slack-request-worker-execute () + "Pop request from queue until `slack-request-worker-max-request-limit', and execute." + (when slack-request-worker-instance + (let ((do '()) + (skip '()) + (current (time-to-seconds)) + (limit (- slack-request-worker-max-request-limit + (oref slack-request-worker-instance + current-request-count)))) + + (cl-loop for req in (reverse (oref slack-request-worker-instance queue)) + do (if (and (< (oref req execute-at) current) + (< (length do) limit)) + (push req do) + (push req skip))) + + ;; (message "[WORKER] QUEUE: %s, LIMIT: %s, CURRENT: %s, DO: %s, SKIP: %s" + ;; (length (oref slack-request-worker-instance queue)) + ;; slack-request-worker-max-request-limit + ;; (oref slack-request-worker-instance current-request-count) + ;; (length do) + ;; (length skip)) + + (oset slack-request-worker-instance queue skip) + + (cl-labels + ((decl-request-count + () + (cl-decf (oref slack-request-worker-instance + current-request-count)))) + (cl-loop for req in do + do (progn + (cl-incf (oref slack-request-worker-instance + current-request-count)) + (slack-request req + :on-success #'decl-request-count + :on-error #'decl-request-count + ))))))) + +(defmethod slack-request-worker-push ((req slack-request-request)) + (unless slack-request-worker-instance + (setq slack-request-worker-instance + (slack-request-worker-create))) + (slack-request-worker-push slack-request-worker-instance req) + (unless (oref slack-request-worker-instance timer) + (slack-request-worker-set-timer))) + +(defun slack-request-worker-quit () + "Cancel timer and remove `slack-request-worker-instance'." + (when (and slack-request-worker-instance + (timerp (oref slack-request-worker-instance timer))) + (cancel-timer (oref slack-request-worker-instance timer))) + (setq slack-request-worker-instance nil)) + +(defmethod slack-request-worker-remove-request ((team slack-team)) + "Remove request from TEAM in queue." + (when slack-request-worker-instance + (let ((to-remove '()) + (new-queue '()) + (all (oref slack-request-worker-instance queue))) + + (dolist (req all) + (if (string= (oref (oref req team) id) + (oref team id)) + (push req to-remove) + (push req new-queue))) + + (dolist (req to-remove) + (when (and (oref req response) + (not (request-response-done-p (oref req response)))) + (request-abort (oref req response)))) + + (oset slack-request-worker-instance queue new-queue) + (slack-log (format "Remove Request from Worker, ALL: %s, REMOVED: %s, NEW-QUEUE: %s" + (length all) + (length to-remove) + (length new-queue)) + team :level 'debug)))) + +(provide 'slack-request-worker) +;;; slack-request-worker.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-request-worker.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-request-worker.elc new file mode 100644 index 000000000000..069a00cf3aaf --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-request-worker.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-request.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-request.el new file mode 100644 index 000000000000..43c97face3c1 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-request.el @@ -0,0 +1,162 @@ +;;; slack-request.el ---slack request function -*- 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 'json) +(require 'request) +(require 'slack-util) + +(defcustom slack-request-timeout 10 + "Request Timeout in seconds." + :group 'slack) + +(defun slack-parse () + (let ((json-object-type 'plist) + (json-array-type 'list)) + (json-read))) + +(defun slack-request-parse-payload (payload) + (let ((json-object-type 'plist) + (json-array-type 'list)) + (condition-case err-var + (json-read-from-string payload) + (json-end-of-file nil)))) + +(defclass slack-request-request () + ((response :initform nil) + (url :initarg :url) + (team :initarg :team) + (type :initarg :type :initform "GET") + (success :initarg :success) + (error :initarg :error :initform nil) + (params :initarg :params :initform nil) + (data :initarg :data :initform nil) + (parser :initarg :parser :initform #'slack-parse) + (sync :initarg :sync :initform nil) + (files :initarg :files :initform nil) + (headers :initarg :headers :initform nil) + (timeout :initarg :timeout :initform `,slack-request-timeout) + (execute-at :initform 0.0 :type float))) + +(cl-defun slack-request-create + (url team &key type success error params data parser sync files headers timeout) + (let ((args (list + :url url :team team :type type + :success success :error error + :params params :data data :parser parser + :sync sync :files files :headers headers + :timeout timeout)) + (ret nil)) + (mapc #'(lambda (maybe-key) + (let ((value (plist-get args maybe-key))) + (when value + (setq ret (plist-put ret maybe-key value))))) + args) + (apply #'make-instance 'slack-request-request ret))) + +(defmethod slack-equalp ((this slack-request-request) other) + (and (string= (oref (oref this team) id) + (oref (oref other team) id)) + (string= "GET" (oref this type)) + (string= "GET" (oref other type)) + (string= (oref this url) + (oref other url)) + (equalp (oref this params) + (oref other params)))) + +(defmethod slack-request-retry-request ((req slack-request-request) retry-after team) + (oset req execute-at (+ retry-after (time-to-seconds))) + (slack-request-worker-push req)) + +(cl-defmethod slack-request ((req slack-request-request) + &key (on-success nil) (on-error nil)) + (let ((team (oref req team))) + (with-slots (url type success error params data parser sync files headers timeout) req + (cl-labels + ((on-success (&key data &allow-other-keys) + (funcall success :data data) + (slack-log + (format "Request Finished. URL: %s, PARAMS: %s" + url + params) + team :level 'trace) + (when (functionp on-success) + (funcall on-success))) + (on-error (&key error-thrown symbol-status response data) + (slack-if-let* ((retry-after (request-response-header response "retry-after")) + (retry-after-sec (string-to-number retry-after))) + (progn + (slack-request-retry-request req retry-after-sec team) + (slack-log (format "Retrying Request After: %s second, URL: %s, PARAMS: %s" + retry-after-sec + url + params) + team)) + (slack-log (format "Request Failed. URL: %s, PARAMS: %s, ERROR-THROWN: %s, SYMBOL-STATUS: %s, DATA: %s" + url + params + error-thrown + symbol-status + data) + team + :level 'error) + (when (functionp error) + (funcall error + :error-thrown error-thrown + :symbol-status symbol-status + :response response + :data data)) + (when (functionp on-error) + (funcall on-error))))) + (oset req response + (request + url + :type type + :sync sync + :params (cons (cons "token" (oref team token)) + params) + :data data + :files files + :headers headers + :parser parser + :success #'on-success + :error #'on-error + :timeout timeout)))))) + + +(cl-defmacro slack-request-handle-error ((data req-name &optional handler) &body body) + "Bind error to e if present in DATA." + `(if (eq (plist-get ,data :ok) :json-false) + (if ,handler + (funcall ,handler (plist-get ,data :error)) + (message "Failed to request %s: %s" + ,req-name + (plist-get ,data :error))) + (progn + ,@body))) + +(provide 'slack-request) +;;; slack-request.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-request.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-request.elc new file mode 100644 index 000000000000..9779eb774677 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-request.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room-buffer.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room-buffer.el new file mode 100644 index 000000000000..6b477ccb9db4 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room-buffer.el @@ -0,0 +1,170 @@ +;;; slack-room-buffer.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 + +;; Author: <yuya373@yuya373> +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: + +(require 'eieio) +(require 'slack-util) +(require 'slack-buffer) +(require 'slack-request) + +(defconst slack-message-delete-url "https://slack.com/api/chat.delete") +(defconst slack-get-permalink-url "https://slack.com/api/chat.getPermalink") + +(defclass slack-room-buffer (slack-buffer) + ((room :initarg :room :type slack-room))) + +(defmethod slack-buffer-name :static ((class slack-room-buffer) room team) + (slack-if-let* ((room-name (slack-room-name room team))) + (format "*Slack - %s : %s" + (oref team name) + room-name))) + +(defmethod slack-buffer-name ((this slack-room-buffer)) + (with-slots (room team) this + (slack-buffer-name (eieio-object-class-name this) room team))) + +(defmethod slack-buffer-delete-message ((this slack-room-buffer) ts) + (with-slots (room team) this + (slack-if-let* ((message (slack-room-find-message room ts))) + (cl-labels + ((on-delete + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-message-delete")))) + (if (yes-or-no-p "Are you sure you want to delete this message?") + (slack-request + (slack-request-create + slack-message-delete-url + team + :type "POST" + :params (list (cons "ts" (slack-ts message)) + (cons "channel" (oref room id))) + :success #'on-delete)) + (message "Canceled")))))) + +(defmethod slack-buffer-message-delete ((this slack-room-buffer) ts) + (let ((buffer (slack-buffer-buffer this))) + (with-current-buffer buffer + (lui-delete #'(lambda () (equal (get-text-property (point) 'ts) + ts)))))) + +(defmethod slack-buffer-copy-link ((this slack-room-buffer) ts) + (with-slots (room team) this + (slack-if-let* ((message (slack-room-find-message room ts)) + (template "https://%s.slack.com/archives/%s/p%s%s")) + (cl-labels + ((on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-get-permalink") + (let ((permalink (plist-get data :permalink))) + (kill-new permalink) + (message "Link Copied to Clipboard"))))) + (slack-request + (slack-request-create + slack-get-permalink-url + team + :type "POST" + :params (list (cons "channel" (oref room id)) + (cons "message_ts" ts)) + :success #'on-success)))))) + +(defmethod slack-buffer--replace ((this slack-room-buffer) ts) + (with-slots (room) this + (slack-if-let* ((message (slack-room-find-message room ts))) + (slack-buffer-replace this message)))) + +(defmethod slack-buffer-toggle-email-expand ((this slack-room-buffer) ts file-id) + (with-slots (room) this + (slack-if-let* ((message (slack-room-find-message room ts)) + (file (cl-find-if + #'(lambda (e) (string= (oref e id) + file-id)) + (oref message files)))) + (progn + (oset file is-expanded (not (oref file is-expanded))) + (slack-buffer-update this message :replace t))))) + +;; POST +(defconst slack-actions-list-url "https://slack.com/api/apps.actions.list") +;; POST +;; params (action_id, type, app_id, channel, message_ts) +(defconst slack-actions-run-url "https://slack.com/api/apps.actions.run") + +(defmethod slack-buffer-execute-message-action ((this slack-room-buffer) ts) + (with-slots (team room) this + (cl-labels + ((select + (app-actions) + (let ((choices (mapcan + #'(lambda (app) + (mapcar #'(lambda (action) + (cons (format "%s - %s" + (plist-get action :name) + (plist-get app :app_name)) + (cons app action))) + (plist-get app :actions))) + app-actions))) + (cdr (cl-assoc (funcall slack-completing-read-function + "Select Action: " choices) + choices :test #'string=)))) + (on-success-run (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-buffer-execute-message-action" + #'(lambda (err) (slack-log (format "%s" err) + team + :level 'error))))) + (on-success-list + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-buffer-execute-message-action") + (slack-if-let* + ((app-actions (plist-get data :app_actions)) + (selected (select app-actions)) + (params (list (cons "message_ts" ts) + (cons "channel" (oref room id)) + (cons "type" (plist-get (cdr selected) + :type)) + (cons "action_id" (plist-get (cdr selected) + :action_id)) + (cons "app_id" (plist-get (car selected) + :app_id)) + (cons "client_token" + (slack-team-client-token team))))) + (slack-request + (slack-request-create + slack-actions-run-url + team + :type "POST" + :params params + :success #'on-success-run)))))) + (slack-request + (slack-request-create + slack-actions-list-url + team + :type "POST" + :success #'on-success-list))))) + +(provide 'slack-room-buffer) +;;; slack-room-buffer.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room-buffer.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room-buffer.elc new file mode 100644 index 000000000000..3f3fd8639ad2 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room-buffer.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room-info-buffer.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room-info-buffer.el new file mode 100644 index 000000000000..f7043c032217 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room-info-buffer.el @@ -0,0 +1,173 @@ +;;; slack-room-info-buffer.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2018 ๅๅชไน + +;; Author: ๅๅชไน <yuyaminami@minamiyuuya-no-MacBook.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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: +(require 'eieio) +(require 'slack-room) +(require 'slack-group) +(require 'slack-room-buffer) + +(defclass slack-room-info-buffer (slack-room-buffer) ()) + +(define-derived-mode slack-room-info-buffer-mode fundamental-mode + "Slack Room Info" + (setq-local default-directory slack-default-directory) + (setq-local buffer-read-only t)) + +(defmethod slack-buffer-name :static ((class slack-room-info-buffer) room team) + (slack-if-let* ((room-name (slack-room-name room team))) + (format "*Slack Room Info - %s : %s" + (slack-team-name team) + room-name))) + +(defmethod slack-buffer-name ((this slack-room-info-buffer)) + (with-slots (room team) this + (slack-buffer-name (eieio-object-class-name this) room team))) + +(defmethod slack-buffer-init-buffer ((this slack-room-info-buffer)) + (let* ((bufname (slack-buffer-name this)) + (buf (generate-new-buffer bufname))) + (with-current-buffer buf + (slack-room-info-buffer-mode) + (slack-buffer-set-current-buffer this) + (slack-buffer-insert this) + (goto-char (point-min))) + (with-slots (room team) this + (let ((class (eieio-object-class-name this))) + (slack-buffer-push-new-3 class room team))) + buf)) + +(defface slack-room-info-title-face + '((t (:weight bold :height 1.5))) + "Used to room info title." + :group 'slack) + +(defface slack-room-info-title-room-name-face + '((t (:inherit slack-room-info-title-face :foreground "#FFA000"))) + "Used to room info title." + :group 'slack) + +(defface slack-room-info-section-title-face + '((t (:weight bold :height 1.2))) + "Used to room info section title." + :group 'slack) + +(defface slack-room-info-section-label-face + '((t (:weight bold))) + "Used to room info section title." + :group 'slack) + +(defmethod slack-buffer-insert ((this slack-room-info-buffer)) + (with-slots (room team) this + (let ((inhibit-read-only t)) + (insert (propertize "About " + 'face 'slack-room-info-title-face)) + (insert (propertize (slack-room-name room team) + 'face 'slack-room-info-title-room-name-face)) + (insert "\n") + (insert "\n") + (insert (propertize "Channel Details" + 'face 'slack-room-info-section-title-face)) + (insert "\n") + + (slack-buffer-insert-purpose room) + (slack-buffer-insert-topic room) + (slack-buffer-insert-created room team) + ))) + +(defmethod slack-buffer-insert-created ((room slack-room) _team) + (with-slots (created) room + (when created + (insert (propertize "Created" + 'face 'slack-room-info-section-label-face)) + (insert ": ") + (insert (slack-message-time-to-string + (number-to-string created)))))) + +(defmethod slack-buffer-insert-created ((room slack-group) team) + (call-next-method) + (with-slots (creator) room + (when creator + (let ((user (slack-user--find creator team))) + (insert (format " by %s" (plist-get user :real_name))))) + )) + +(defmethod slack-buffer-insert-purpose ((room slack-group)) + (with-slots (purpose) room + (when purpose + (insert (propertize "Purpose" + 'face 'slack-room-info-section-label-face)) + (insert ": ") + (slack-if-let* + ((purpose-value (plist-get purpose :value)) + (not-blank-p (and purpose-value + (< 0 (length purpose-value))))) + (insert (format "%s\n" purpose-value)) + (insert (propertize "Set purpose" + 'face '(:box (:line-width + 1 + :style + released-button)))) + (insert "\n"))))) + +(defmethod slack-buffer-insert-purpose ((room slack-room))) + +(defmethod slack-buffer-insert-topic ((room slack-group)) + (with-slots (topic) room + (when topic + (insert (propertize "Topic" + 'face 'slack-room-info-section-label-face)) + (insert ": ") + (slack-if-let* + ((topic-value (plist-get topic :value)) + (not-blank-p (and topic-value + (< 0 (length topic-value))))) + (insert (format "%s\n" topic-value)) + (insert (propertize "Set Topic" + 'face '(:box (:line-width + 1 + :style + released-button)))) + (insert "\n"))))) + +(defmethod slack-buffer-insert-topic ((room slack-room))) + +(defmethod slack-create-room-info-buffer ((room slack-room) team) + (slack-if-let* ((buffer (slack-buffer-find 'slack-room-info-buffer + room team))) + buffer + (slack-room-info-buffer :room room :team team))) + +(defmethod slack-buffer-buffer ((this slack-room-info-buffer)) + (slack-if-let* ((buf (get-buffer (slack-buffer-name this)))) + (with-current-buffer buf + (let ((inhibit-read-only t)) + (delete-region (point-min) (point-max)) + (slack-buffer-insert this)) + buf) + (slack-buffer-init-buffer this))) + + +(provide 'slack-room-info-buffer) +;;; slack-room-info-buffer.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room-info-buffer.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room-info-buffer.elc new file mode 100644 index 000000000000..be358a2cf9b1 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room-info-buffer.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room-message-compose-buffer.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room-message-compose-buffer.el new file mode 100644 index 000000000000..02391570f27c --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room-message-compose-buffer.el @@ -0,0 +1,69 @@ +;;; slack-room-message-compose-buffer.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 + +;; Author: <yuya373@yuya373> +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: + +(require 'eieio) +(require 'slack-util) +(require 'slack-message-compose-buffer) + +(defclass slack-room-message-compose-buffer (slack-message-compose-buffer) + ((room :initarg :room type slack-room))) + +(defun slack-create-room-message-compose-buffer (room team) + (slack-if-let* ((buf (slack-buffer-find 'slack-room-message-compose-buffer + room team))) + buf + (slack-room-message-compose-buffer :room room :team team))) + +(defmethod slack-buffer-name :static ((class slack-room-message-compose-buffer) room team) + (format "*Slack - %s : %s Compose Message" + (oref team name) + (slack-room-name room team))) + +(defmethod slack-buffer-name ((this slack-room-message-compose-buffer)) + (with-slots (room team) this + (slack-buffer-name (eieio-object-class-name this) + room team))) + +(defmethod slack-buffer-init-buffer ((this slack-room-message-compose-buffer)) + (let* ((buf (call-next-method))) + (with-current-buffer buf + (setq buffer-read-only nil) + (erase-buffer) + (message "C-c C-c to send edited msg")) + (with-slots (room team) this + (slack-buffer-push-new-3 'slack-room-message-compose-buffer + room team)) + buf)) + +(defmethod slack-buffer-send-message ((this slack-room-message-compose-buffer) message) + (let ((buffer (slack-buffer-buffer this))) + (with-slots (room team) this + (slack-message-send-internal message (oref room id) team) + (call-next-method)))) + + +(provide 'slack-room-message-compose-buffer) +;;; slack-room-message-compose-buffer.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room-message-compose-buffer.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room-message-compose-buffer.elc new file mode 100644 index 000000000000..d7c9f9b5fca8 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room-message-compose-buffer.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room.el new file mode 100644 index 000000000000..a9632e9483e1 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room.el @@ -0,0 +1,471 @@ +;;; 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 ()) + (last-read :initarg :last_read :type string :initform "0") + (members :initarg :members :type list :initform '()))) + + +(defgeneric slack-room-name (room team)) +(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)) + (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)) + 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) team) + (concat "*Slack*" + " : " + (slack-room-display-name room team))) + +(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 team &optional filter collecter) + `(cl-labels + ((latest-ts (room) + (with-slots (latest) room + (if latest (slack-ts latest) "0"))) + (sort-rooms (rooms) + (nreverse (cl-sort rooms #'string< :key #'latest-ts)))) + (cl-loop for room in (sort-rooms (if ,filter + (funcall ,filter ,rooms) + ,rooms)) + as label = (slack-room-label room team) + collect (if (functionp ,collecter) + (funcall ,collecter label room) + (cons label room))))) + +(defun slack-room-select (rooms team) + (let* ((alist (slack-room-names + rooms team #'(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 (slack-ts m))) + (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-display-name ((room slack-room) team) + (let ((room-name (slack-room-name room team))) + (if slack-display-team-name + (format "%s - %s" + (slack-team-name team) + room-name) + room-name))) + +(defmethod slack-room-label-prefix ((_room slack-room) _team) + " ") + +(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) team) + (format "%s%s%s" + (slack-room-label-prefix room team) + (slack-room-display-name room team) + (slack-room-unread-count-str room))) + +(defmethod slack-room-name ((room slack-room) _team) + (oref room name)) + +(defun slack-room-sort-messages (messages) + (cl-sort messages #'string< :key #'slack-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< (slack-ts latest) (slack-ts message))) + (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 (slack-ts m)) + (string= from (slack-ts m)))) + (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))) + team))) + (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 team)))))) + +(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 team))) + 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)))) + team))) + (slack-room-display room team))) + +(defmethod slack-user-find ((room slack-room) team) + (slack-user--find (oref room user) team)) + +(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 team)) + (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 diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room.elc new file mode 100644 index 000000000000..68e4cb9edd7a --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-room.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-search-result-buffer.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-search-result-buffer.el new file mode 100644 index 000000000000..a24792ff25e5 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-search-result-buffer.el @@ -0,0 +1,129 @@ +;;; slack-search-result-buffer.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 + +;; Author: <yuya373@yuya373> +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: + +(require 'eieio) +(require 'slack-util) +(require 'slack-buffer) + +(define-derived-mode slack-search-result-buffer-mode slack-buffer-mode "Slack Search Result" + (remove-hook 'lui-post-output-hook 'slack-display-image t)) + +(defclass slack-search-result-buffer (slack-buffer) + ((search-result :initarg :search-result :type slack-search-result))) + +(defmethod slack-buffer-name :static ((class slack-search-result-buffer) search-result team) + (with-slots (query sort sort-dir) search-result + (format "*Slack - %s : Search Result - QUERY: %s, ORDER BY: %s %s" + (oref team name) + query + sort + (upcase sort-dir)))) + +(defmethod slack-buffer-name ((this slack-search-result-buffer)) + (with-slots (search-result team) this + (slack-buffer-name (eieio-object-class-name this) search-result team))) + +(defun slack-create-search-result-buffer (search-result team) + (slack-if-let* ((buffer (slack-buffer-find 'slack-search-result-buffer + search-result + team))) + buffer + (make-instance 'slack-search-result-buffer + :team team + :search-result search-result))) + +(defmethod slack-buffer-insert ((this slack-search-result-buffer) match) + (with-slots (team) this + (let* ((time (slack-ts-to-time (slack-ts match))) + (lui-time-stamp-time time) + (lui-time-stamp-format "[%Y-%m-%d %H:%M:%S]")) + (lui-insert (slack-message-to-string match team) t) + (lui-insert "" t)))) + +(defmethod slack-buffer-has-next-page-p ((this slack-search-result-buffer)) + (with-slots (search-result) this + (slack-search-has-next-page-p search-result))) + +(defmethod slack-buffer-insert-history ((this slack-search-result-buffer)) + (with-slots (team search-result) this + (let* ((paging (oref search-result paging)) + (per-page (oref paging count)) + (matches (last (oref search-result matches) per-page)) + (cur-point (point))) + (cl-loop for match in matches + do (slack-buffer-insert this match)) + (goto-char cur-point)))) + +(defmethod slack-buffer-request-history ((this slack-search-result-buffer) after-success) + (with-slots (team search-result) this + (slack-search-request search-result after-success team + (slack-search-paging-next-page + (oref search-result paging))))) + +(defmethod slack-buffer-init-buffer ((this slack-search-result-buffer)) + (let ((buffer (generate-new-buffer (slack-buffer-name this)))) + (with-current-buffer buffer + (slack-search-result-buffer-mode) + (slack-buffer-set-current-buffer this) + (with-slots (search-result) this + (let* ((messages (oref search-result matches))) + (cl-loop for m in messages + do (slack-buffer-insert this m))) + (let ((lui-time-stamp-position nil)) + (if (slack-search-has-next-page-p search-result) + (slack-buffer-insert-load-more this))))) + + (with-slots (search-result team) this + (slack-buffer-push-new-3 'slack-search-result-buffer + search-result + team)) + buffer)) + +(defmethod slack-buffer-loading-message-end-point ((this slack-search-result-buffer)) + (previous-single-property-change (point-max) + 'loading-message)) + +(defmethod slack-buffer-delete-load-more-string ((this slack-search-result-buffer)) + (let* ((inhibit-read-only t) + (loading-message-end + (slack-buffer-loading-message-end-point this)) + (loading-message-start + (previous-single-property-change loading-message-end + 'loading-message))) + (delete-region loading-message-start + loading-message-end))) + +(defmethod slack-buffer-prepare-marker-for-history ((_this slack-search-result-buffer))) + +(defmethod slack-buffer-insert--history ((this slack-search-result-buffer)) + (slack-buffer-insert-history this) + (if (slack-buffer-has-next-page-p this) + (slack-buffer-insert-load-more this) + (let ((lui-time-stamp-position nil)) + (lui-insert "(no more messages)\n")))) + +(provide 'slack-search-result-buffer) +;;; slack-search-result-buffer.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-search-result-buffer.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-search-result-buffer.elc new file mode 100644 index 000000000000..ea38b58bc333 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-search-result-buffer.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-search.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-search.el new file mode 100644 index 000000000000..3379220754dd --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-search.el @@ -0,0 +1,263 @@ +;;; slack-search.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2016 ๅๅชไน + +;; 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 'slack-room) +(require 'slack-request) + +(defface slack-search-result-message-header-face + '((t (:weight bold :height 1.1 :underline t))) + "Face used to search message header." + :group 'slack) +;; (:inherit (markdown-code-face font-lock-constant-face)) +(defface slack-search-result-message-username-face + '((t (:inherit slack-message-output-header :underline nil))) + "" + :group 'slack) + +(defclass slack-search-paging () + ((count :initarg :count :type number) + (total :initarg :total :type number) + (page :initarg :page :type number) + (pages :initarg :pages :type number))) + +(defclass slack-search-result (slack-room) + ((query :initarg :query :type string) + (sort :initarg :sort :type string) + (sort-dir :initarg :sort-dir :type string) + (total :initarg :total :type number) + (matches :initarg :matches :initform nil :type (or null list)) + (paging :initarg :paging :type slack-search-paging))) + +(defclass slack-file-search-result (slack-search-result) ()) + +(defclass slack-search-message () + ((message :initarg :message :type slack-message) + + (channel :initarg :channel :type slack-search-message-channel) + (user :initarg :user :type string) + (username :initarg :username :type string) + (permalink :initarg :permalink :type string) + + (previous-2 :initarg :previous-2 :type (or null slack-search-message-around-message) :initform nil) + (previous :initarg :previous :type (or null slack-search-message-around-message) :initform nil) + (next :initarg :next :type (or null slack-search-message-around-message) :initform nil) + (next-2 :initarg :next-2 :type (or null slack-search-message-around-message) :initform nil))) + +(defclass slack-search-message-channel () + ((id :initarg :id :type string) + (name :initarg :name :type string))) + +(defclass slack-search-message-around-message () + ((user :initarg :user :type string) + (username :initarg :username :type string) + (text :initarg :text :type string) + (ts :initarg :ts :type string) + (type :initarg :type :type string))) + +(defmethod slack-merge ((this slack-search-result) other) + (oset this query (oref other query)) + (oset this sort (oref other sort)) + (oset this sort-dir (oref other sort-dir)) + (oset this total (oref other total)) + (oset this matches (append (oref this matches) (oref other matches))) + (oset this paging (oref other paging))) + +(defmethod slack-message-to-string ((this slack-search-message) team) + (with-slots (channel username) this + (let* ((room (slack-room-find (oref channel id) team)) + (header (propertize (format "%s%s" + (if (slack-channel-p room) + "#" "@") + (slack-room-name room team)) + 'face 'slack-search-result-message-header-face))) + (propertize (format "%s\n%s" + header + (slack-message-to-string (oref this message) team)) + 'ts (slack-ts this))))) + +(defmethod slack-ts ((this slack-search-message)) + (slack-ts (oref this message))) + +(defmethod slack-search-has-next-page-p ((this slack-search-result)) + (slack-search-paging-next-page (oref this paging))) + +(defmethod slack-search-paging-next-page ((this slack-search-paging)) + (with-slots (pages page) this + (unless (< pages (1+ page)) + (1+ page)))) + +(defun slack-search-create-message-channel (payload) + (and payload + (make-instance 'slack-search-message-channel + :id (plist-get payload :id) + :name (plist-get payload :name)))) + +(defun slack-search-create-around-message (payload) + (and payload + (make-instance 'slack-search-message-around-message + :user (plist-get payload :user) + :username (plist-get payload :username) + :text (plist-get payload :text) + :ts (plist-get payload :ts) + :type (plist-get payload :type)))) + +(defun slack-search-create-message (payload team) + (setq payload (append payload nil)) + (let* ((channel (slack-search-create-message-channel + (plist-get payload :channel))) + (previous-2 (slack-search-create-around-message + (plist-get payload :previous_2))) + (previous (slack-search-create-around-message + (plist-get payload :previous))) + (next (slack-search-create-around-message + (plist-get payload :next))) + (next-2 (slack-search-create-around-message + (plist-get payload :next_2))) + (room (slack-room-find (oref channel id) team))) + + (unless (< 0 (length (plist-get payload :user))) + (plist-put payload :user nil) + (plist-put payload :subtype "bot_message")) + + (make-instance 'slack-search-message + :message (slack-message-create payload team :room room) + :channel channel + :previous-2 previous-2 + :previous previous + :next next + :next-2 next-2))) + +(defun slack-search-create-paging (payload) + (and payload + (make-instance 'slack-search-paging + :count (plist-get payload :count) + :total (plist-get payload :total) + :page (plist-get payload :page) + :pages (plist-get payload :pages)))) + +(defun slack-search-create-result (payload sort sort-dir team) + (let* ((messages (plist-get payload :messages)) + (matches (mapcar #'(lambda (e) (slack-search-create-message e team)) + (plist-get messages :matches))) + (paging (slack-search-create-paging + (plist-get messages :paging)))) + (make-instance 'slack-search-result + :query (plist-get payload :query) + :total (plist-get messages :total) + :paging paging + :matches matches + :sort sort + :sort-dir sort-dir))) + +(defun slack-search-create-file-result (payload sort sort-dir) + (let* ((files (plist-get payload :files)) + (matches (mapcar #'slack-file-create + (plist-get files :matches))) + (paging (slack-search-create-paging + (plist-get files :paging)))) + (make-instance 'slack-search-result + :query (plist-get payload :query) + :total (plist-get files :total) + :paging paging + :matches matches + :sort sort + :sort-dir sort-dir))) + +(defun slack-search-query-params () + (let ((team (slack-team-select)) + (query (read-from-minibuffer "Query: ")) + (sort (funcall slack-completing-read-function "Sort: " `("score" "timestamp") + nil t)) + (sort-dir (funcall slack-completing-read-function "Direction: " `("desc" "asc") + nil t))) + (list team query sort sort-dir))) + +(defun slack-search-from-messages () + (interactive) + (cl-destructuring-bind (team query sort sort-dir) (slack-search-query-params) + (let ((instance (make-instance 'slack-search-result + :sort sort + :sort-dir sort-dir + :query query))) + (cl-labels + ((after-success () + (let ((buffer (slack-create-search-result-buffer instance team))) + (slack-buffer-display buffer)))) + (slack-search-request instance #'after-success team))))) + +(defun slack-search-from-files () + (interactive) + (cl-destructuring-bind (team query sort sort-dir) (slack-search-query-params) + (let ((instance (make-instance 'slack-file-search-result + :sort sort + :sort-dir sort-dir + :query query))) + (cl-labels + ((after-success () + (let ((buffer (slack-create-search-result-buffer instance team))) + (slack-buffer-display buffer)))) + (slack-search-request instance #'after-success team))))) + +(defmethod slack-search-request-url ((_this slack-search-result)) + "https://slack.com/api/search.messages") + +(defmethod slack-search-request-url ((_this slack-file-search-result)) + "https://slack.com/api/search.files") + +(cl-defmethod slack-search-request ((this slack-search-result) + after-success team &optional (page 1)) + (cl-labels + ((on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-search-request") + (let ((search-result + (if (slack-file-search-result-p this) + (slack-search-create-file-result data + (oref this sort) + (oref this sort-dir)) + (slack-search-create-result data + (oref this sort) + (oref this sort-dir) + team)))) + (slack-merge this search-result) + (funcall after-success))))) + (with-slots (query sort sort-dir) this + (if (< 0 (length query)) + (slack-request + (slack-request-create + (slack-search-request-url this) + team + :type "POST" + :params (list (cons "query" query) + (cons "sort" sort) + (cons "sort_dir" sort-dir) + (cons "page" (number-to-string page))) + :success #'on-success)))))) + + +(provide 'slack-search) +;;; slack-search.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-search.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-search.elc new file mode 100644 index 000000000000..907e9c50c4a8 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-search.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-selectable.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-selectable.el new file mode 100644 index 000000000000..a4a04d8a18f2 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-selectable.el @@ -0,0 +1,88 @@ +;;; slack-selectable.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2018 + +;; Author: <yuya373@yuya373> +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: + +(require 'eieio) +(require 'slack-util) + +(defclass slack-selectable () + ( + ;; one of users, channels, conversations, external or static + (data-source :initarg :data_source :type string :initform "static") + (options :initarg :options :initform nil) + (option-groups :initarg :option_groups :initform nil) + (selected-options :initarg :selected_options :type (or null list) :initform '()) + )) + +(defclass slack-selectable-option () + ((text :initarg :text :type string) + (value :initarg :value :type string))) + +(defclass slack-selectable-option-group () + ((text :initarg :text :type string) + (options :initarg :options :initform nil))) + +(defmethod slack-selectable-text ((this slack-selectable-option)) + (oref this text)) + +(defmethod slack-selectable-text ((this slack-selectable-option-group)) + (oref this text)) + +(defmethod slack-selectable-select-from-static-data-source ((this slack-selectable)) + (cl-labels + ((select-option (options) + (select (slack-selectable-prompt this) + (mapcar #'(lambda (option) + (cons (slack-selectable-text option) + (oref option value))) + options))) + (select-option-group + (option-groups) + (slack-if-let* + ((text (select (slack-selectable-prompt this) + (mapcar #'(lambda (option-group) + (slack-selectable-text option-group)) + option-groups)))) + (find-option text option-groups))) + (find-option (text options) + (cl-find-if #'(lambda (option) + (string= text (slack-selectable-text option))) + options)) + (select (prompt options) + (funcall slack-completing-read-function + prompt + options + nil t))) + (with-slots (options option-groups) this + (slack-if-let* + ((options (if option-groups + (oref (select-option-group option-groups) + options) + options)) + (option-text (select-option options))) + (find-option option-text options))))) + +(provide 'slack-selectable) +;;; slack-selectable.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-selectable.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-selectable.elc new file mode 100644 index 000000000000..f460144295c7 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-selectable.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-slash-commands.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-slash-commands.el new file mode 100644 index 000000000000..4287a3eb9926 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-slash-commands.el @@ -0,0 +1,164 @@ +;;; slack-slash-commands.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 + +;; Author: <yuya373@yuya373> +;; 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) + +(defclass slack-command () + ((name :initarg :name :type string) + (type :initarg :type :type string) + (usage :initarg :usage :type string :initform "") + (desc :initarg :desc :type string :initform "") + (alias-of :initarg :alias_of :type (or null string) :initform nil))) + +(defclass slack-core-command (slack-command) + ((canonical-name :initarg :canonical_name :type string))) + +(defclass slack-app-command (slack-command) + ((app :initarg :app :type string))) + +(defclass slack-service-command (slack-command) + ((service-name :initarg :service_name :type string))) + +(defmethod slack-equalp ((this slack-command) other) + (string= (oref this name) (oref other name))) + +(defun slack-slash-commands-parse (text team) + "Return (command . arguments) or nil." + (when (string-prefix-p "/" text) + (let* ((tokens (split-string text " ")) + (maybe-command (car tokens)) + (command (slack-command-find maybe-command team))) + (when command + (cons command + (mapconcat #'identity (cdr tokens) " ")))))) + +(defun slack-slash-commands-join (team _args) + (slack-channel-join team t)) + +(defun slack-command-create (command) + (cl-labels + ((slack-core-command-create + (payload) + (apply #'make-instance 'slack-core-command + (slack-collect-slots 'slack-core-command payload))) + (slack-app-command-create + (payload) + (apply #'make-instance 'slack-app-command + (slack-collect-slots 'slack-app-command payload))) + (slack-service-command-create + (payload) + (apply #'make-instance 'slack-service-command + (slack-collect-slots 'slack-service-command payload)))) + (let ((type (plist-get command :type))) + (cond + ((string= type "core") + (slack-core-command-create command)) + ((string= type "app") + (slack-app-command-create command)) + ((string= type "service") + (slack-service-command-create command)) + (t (apply #'make-instance 'slack-command command)))))) + +(defun slack-command-list-update (&optional team) + (interactive) + (let ((team (or team (slack-team-select)))) + (cl-labels + ((on-success + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-commands-list-request") + (let ((commands (mapcar #'(lambda (command) (slack-command-create command)) + (cl-remove-if-not #'listp + (plist-get data :commands))))) + (oset team commands commands) + (slack-log "Slack Command List Updated" team :level 'info))))) + (slack-request + (slack-request-create + "https://slack.com/api/commands.list" + team + :type "POST" + :success #'on-success))))) + +(defun slack-command-find (name team) + (let ((commands (oref team commands))) + (cl-find-if #'(lambda (command) (string= name + (oref command name))) + commands))) + +(defmethod slack-command-company-doc-string ((this slack-command) team) + (if (oref this alias-of) + (let ((command (slack-command-find (oref this alias-of) + team))) + (when command + (slack-command-company-doc-string command team))) + (with-slots (usage desc) this + (format "%s%s" + (or (and (< 0 (length usage)) + (format "%s\n" usage)) + "") + desc)))) + +(cl-defmethod slack-command-run ((command slack-command) team channel + &key (text nil)) + (let ((disp "") + (client-token (slack-team-client-token team)) + (command (oref command name))) + (cond + ((or (string= command "/join") + (string= command "/open")) (error "/join and /open are not supported yet")) + (t + (cl-labels + ((on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-command-run") + (slack-if-let* ((response (plist-get data :response))) + (slack-if-let* + ((user (slack-user--find "USLACKBOT" team)) + (payload (list :text response + :is_ephemeral t + :user (plist-get user :id) + :id (plist-get user :id) + :type "message" + :channel channel + :ts (number-to-string + (time-to-seconds)))) + (message (slack-message-create payload team))) + (slack-message-update message team) + (message "%s" (slack-message-unescape-string response + team))))))) + (slack-request + (slack-request-create + "https://slack.com/api/chat.command" + team + :params (list (cons "disp" disp) + (cons "client_token" client-token) + (cons "command" command) + (cons "channel" channel) + (when text + (cons "text" text))) + :success #'on-success))))))) + +(provide 'slack-slash-commands) +;;; slack-slash-commands.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-slash-commands.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-slash-commands.elc new file mode 100644 index 000000000000..5b52059a201e --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-slash-commands.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-star.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-star.el new file mode 100644 index 000000000000..fbe3af0c9330 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-star.el @@ -0,0 +1,250 @@ +;;; slack-stars.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 ๅๅชไน + +;; Author: ๅๅชไน <yuyaminami@minamiyuuya-no-MacBook.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 'slack-util) +(require 'slack-request) + +(defconst slack-stars-list-url "https://slack.com/api/stars.list") + +(defclass slack-star () + ((paging :initarg :paging :type slack-star-paging) + (items :initarg :items :type (or null list) :initform nil))) + +(defclass slack-star-paging () + ((per-page :initarg :per-page :type number) + (spill :initarg :spill :type number) ;; ?? + (total :initarg :total :type number) + (page :initarg :page :type number) + (pages :initarg :pages :type number))) + +(defclass slack-star-item () + ((date-create :initarg :date-create :type string))) + +(defclass slack-star-message (slack-star-item) + ((channel :initarg :channel :type string) + (message :initarg :message :type slack-message))) + +(defclass slack-star-file (slack-star-item) + ((file :initarg :file :type slack-file))) + +(defclass slack-star-channel (slack-star-item) ;; Ch ?? + ((channel :initarg :channel :type string))) ;; ID + +(defclass slack-star-group (slack-star-item) ;; Gh ?? + ((group :initarg :group :type string))) ;; ID + +(defclass slack-star-im (slack-star-item) ;; Dh ?? + ((channel :initarg :channel :type string))) ;; ID + +(defmethod slack-star-item-message ((this slack-star-message)) + (oref this message)) + +(defmethod slack-star-item-message ((this slack-star-file)) + (oref this file)) + +(defmethod slack-ts ((this slack-star-item)) + (oref this date-create)) + +(defmethod slack-next-page ((this slack-star-paging)) + (with-slots (pages page) this + (unless (< pages (1+ page)) + (1+ page)))) + +(defmethod slack-star-has-next-page-p ((this slack-star)) + (slack-next-page (oref this paging))) + +(defmethod slack-per-page ((this slack-star-paging)) + (oref this per-page)) + +(defmethod slack-star-per-page ((this slack-star)) + (slack-per-page (oref this paging))) + +(defmethod slack-star-items ((this slack-star)) + (oref this items)) + +(defmethod slack-merge ((old slack-star) new) + (with-slots (paging items) old + (setq paging (oref new paging)) + (setq items (append (oref new items) items)))) + +(defmethod slack-to-string ((this slack-star-message) team) + (with-slots (message) this + (slack-message-to-string message team))) + +(defmethod slack-to-string ((this slack-star-file) team) + (with-slots (date-create file) this + (slack-message-to-string file date-create team))) + +(defun slack-create-star-paging (payload) + ;; (:per_page 20 :spill 0 :page 1 :total 61 :pages 4) + (make-instance 'slack-star-paging + :per-page (plist-get payload :per_page) + :spill (plist-get payload :spill) + :page (plist-get payload :page) + :total (plist-get payload :total) + :pages (plist-get payload :pages) + )) + +(defun slack-create-star-items (payload team) + (mapcar #'(lambda (e) (slack-create-star-item e team)) + payload)) + +(defun slack-create-star-item (payload team) + (let* ((type (plist-get payload :type)) + (date-create (format "%s" (plist-get payload :date_create))) + (file-payload (plist-get payload :file)) + (file (and file-payload + (if (or (slack-file-p file-payload) + (slack-file-email-p file-payload)) + file-payload + (slack-file-create file-payload)))) + (file-id (and file (oref file id)))) + (cond + ((string= type "message") + (make-instance 'slack-star-message + :date-create date-create + :channel (plist-get payload :channel) + :message (slack-message-create (plist-get payload :message) + team))) + ((string= type "file") + (make-instance 'slack-star-file + :date-create date-create + :file file)) + ((string= type "channel") + (make-instance 'slack-star-channel + :date-create date-create + :channel (plist-get payload :channel))) + ((string= type "im") + (make-instance 'slack-star-im + :date-create date-create + :channel (plist-get payload :channel))) + ((string= type "group") + (make-instance 'slack-star-group + :date-create date-create + :group (plist-get payload :group)))))) + +;; (:per_page 20 :spill 0 :page 1 :total 61 :pages 4) +(defun slack-create-star-paging (payload) + (make-instance 'slack-star-paging + :per-page (plist-get payload :per_page) + :spill (plist-get payload :spill) + :page (plist-get payload :page) + :total (plist-get payload :total) + :pages (plist-get payload :pages))) + +(defun slack-create-star (payload team) + (let ((items (slack-create-star-items (plist-get payload :items) + team)) + (paging (slack-create-star-paging (plist-get payload :paging)))) + (make-instance 'slack-star + :items (reverse items) + :paging paging))) + +(defun slack-stars-list-request (team &optional page after-success) + (cl-labels + ((on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-stars-list-request") + (let ((star (slack-create-star data team))) + (if (oref team star) + (if page + (slack-merge (oref team star) star) + (oset team star star)) + (oset team star star))) + (if after-success + (funcall after-success))))) + (slack-request + (slack-request-create + slack-stars-list-url + team + :type "POST" + :data (list (cons "exclude" "Ch,Gh,Dh") + (cons "count" "20") + (cons "page" (number-to-string (or page 1)))) + :success #'on-success)))) + + +(defun slack-stars-list () + (interactive) + (let* ((team (slack-team-select)) + (buf (slack-buffer-find 'slack-stars-buffer team))) + (if buf (slack-buffer-display buf) + (slack-stars-list-request + team nil + #'(lambda () (slack-buffer-display (slack-create-stars-buffer team))))))) + +(defmethod slack-message-star-api-params ((this slack-star-item)) + (list (slack-message-star-api-params (slack-star-item-message this)))) + +(defmethod slack-message-star-api-params ((this slack-star-message)) + (append (list (cons "channel" (oref this channel))) + (call-next-method))) + +(defmethod slack-star-remove-star ((this slack-star) ts team) + (slack-if-let* ((item (cl-find-if #'(lambda (e) (string= (oref e date-create) ts)) + (oref this items)))) + (slack-message-star-api-request slack-message-stars-remove-url + (slack-message-star-api-params item) + team))) + +(defmethod slack-star-remove ((this slack-star) payload team) + (let ((date-create (format "%s" (plist-get payload :date_create)))) + (oset this items (cl-remove-if #'(lambda (e) (string= (slack-ts e) + date-create)) + (oref this items))) + (slack-if-let* ((buffer (slack-buffer-find 'slack-stars-buffer team))) + (slack-buffer-message-delete buffer date-create)))) + +(defmethod slack-star-add ((this slack-star) payload team) + (setq payload (append payload nil)) + (cl-labels + ((create-star (payload) + (slack-create-star-item payload team)) + (append-star-item (item) + (oset this items (append (oref this items) (list item)))) + (insert-to-buffer (item) + (slack-if-let* ((buffer (slack-buffer-find 'slack-stars-buffer + team))) + (with-current-buffer (slack-buffer-buffer buffer) + (slack-buffer-insert buffer item))))) + (if (plist-get payload :file) + (cl-labels + ((insert-star (payload file) + (let ((item (create-star (plist-put payload :file file)))) + (append-star-item item) + (insert-to-buffer item)))) + (let ((file-id (plist-get (plist-get payload :file) :id))) + (slack-if-let* ((file (slack-file-find file-id team))) + (insert-star payload file) + (slack-file-request-info file-id 1 team + #'(lambda (file _team) + (insert-star payload file)))))) + (let ((item (create-star payload))) + (append-star-item item) + (insert-to-buffer item))))) + +(provide 'slack-star) +;;; slack-stars.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-star.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-star.elc new file mode 100644 index 000000000000..04ad4e22f5d4 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-star.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-stars-buffer.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-stars-buffer.el new file mode 100644 index 000000000000..ed87b6530521 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-stars-buffer.el @@ -0,0 +1,140 @@ +;;; slack-stars-buffer.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 ๅๅชไน + +;; Author: ๅๅชไน <yuyaminami@minamiyuuya-no-MacBook.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 'slack-util) +(require 'slack-team) +(require 'slack-buffer) + +(define-derived-mode slack-stars-buffer-mode slack-buffer-mode "Slack Stars Buffer") + +(defclass slack-stars-buffer (slack-buffer) + ((oldest :type string :initform ""))) + +(defmethod slack-buffer-name :static ((_class slack-stars-buffer) team) + (format "*Slack - %s : Stars*" (oref team name))) + +(defmethod slack-buffer-name ((this slack-stars-buffer)) + (slack-buffer-name 'slack-stars-buffer (oref this team))) + +(defmethod slack-buffer-find :static ((class slack-stars-buffer) team) + (slack-if-let* ((buf (cl-find-if #'(lambda (e) (string= (buffer-name e) + (slack-buffer-name class team))) + (slot-value team class)))) + (with-current-buffer buf slack-current-buffer))) + +(defmethod slack-buffer-insert ((this slack-stars-buffer) item &optional not-tracked-p) + (let ((lui-time-stamp-time (seconds-to-time + (string-to-number + (slack-ts + (slack-star-item-message item)))))) + (lui-insert-with-text-properties + (slack-to-string item (oref this team)) + 'ts (slack-ts item) + 'not-tracked-p not-tracked-p) + (lui-insert "" t))) + +(defmethod slack-buffer-has-next-page-p ((this slack-stars-buffer)) + (with-slots (team) this + (slack-star-has-next-page-p (oref team star)))) + +(defmethod slack-buffer-insert-history ((this slack-stars-buffer)) + (with-slots (team) this + (let ((items (slack-star-items (oref team star))) + (before-oldest (oref this oldest))) + (oset this oldest (slack-ts (car items))) + (cl-loop for item in items + do (and (string< (slack-ts item) before-oldest) + (slack-buffer-insert this item t))) + + (slack-if-let* ((point (slack-buffer-ts-eq (point-min) + (point-max) + before-oldest))) + (goto-char point))))) + +(defmethod slack-buffer-request-history ((this slack-stars-buffer) after-success) + (with-slots (team) this + (slack-stars-list-request team + (slack-next-page (oref (oref team star) paging)) + after-success))) + + +(defmethod slack-buffer-update-oldest ((this slack-stars-buffer) item) + (when (string< (oref this oldest) (slack-ts item)) + (oset this oldest (slack-ts item)))) + +(defmethod slack-buffer-init-buffer ((this slack-stars-buffer)) + (let* ((buf (generate-new-buffer (slack-buffer-name this))) + (star (oref (oref this team) star)) + (items (slack-star-items star)) + (oldest-message (car items))) + (when oldest-message + (slack-buffer-update-oldest this oldest-message)) + (with-current-buffer buf + (slack-stars-buffer-mode) + (slack-buffer-set-current-buffer this) + (slack-buffer-insert-load-more this) + (with-slots (star) (oref this team) + (cl-loop for m in (oref star items) + do (slack-buffer-insert this m))) + (goto-char (point-max))) + (unless (oref (oref this team) slack-stars-buffer) + (push buf (oref (oref this team) slack-stars-buffer))) + buf)) + +(defun slack-create-stars-buffer (team) + (slack-if-let* ((buf (slack-buffer-find 'slack-stars-buffer team))) + buf + (make-instance 'slack-stars-buffer + :team team))) + +(defmethod slack-buffer-remove-star ((this slack-stars-buffer) ts) + (with-slots (team) this + (with-slots (star) team + (slack-star-remove-star star ts team)))) + +(defmethod slack-buffer-message-delete ((this slack-stars-buffer) ts) + (let ((buffer (slack-buffer-buffer this)) + (inhibit-read-only t)) + (with-current-buffer buffer + (slack-if-let* ((beg (slack-buffer-ts-eq (point-min) (point-max) ts)) + (end (next-single-property-change beg 'ts))) + (delete-region beg end))))) + +(defmethod slack-buffer--replace ((this slack-stars-buffer) ts) + (with-slots (team) this + (with-slots (star) team + (let* ((items (slack-star-items star)) + (item (cl-find-if #'(lambda (e) (string= (slack-ts e) + ts)) + items))) + (lui-replace (slack-to-string item team) + #'(lambda () + (string= (get-text-property (point) 'ts) + ts))))))) + +(provide 'slack-stars-buffer) +;;; slack-stars-buffer.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-stars-buffer.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-stars-buffer.elc new file mode 100644 index 000000000000..61dd3bef92cc --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-stars-buffer.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-team.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-team.el new file mode 100644 index 000000000000..abb0ac77288c --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-team.el @@ -0,0 +1,324 @@ +;;; slack-team.el --- team class -*- lexical-binding: t; -*- + +;; Copyright (C) 2016 ๅๅชไน + +;; 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 'slack-util) + +(defvar slack-teams nil) +(defvar slack-current-team nil) +(defcustom slack-prefer-current-team nil + "If set to t, using `slack-current-team' for interactive function. +use `slack-change-current-team' to change `slack-current-team'" + :group 'slack) + +(defcustom slack-modeline-count-only-subscribed-channel t + "Count unread only subscribed channel." + :group 'slack) + +(defclass slack-team-threads () + ((initializedp :initform nil) + (has-more :initform t) + (total-unread-replies :initform 0 :type number) + (new-threads-count :initform 0 :type number))) + +(defclass slack-team () + ((id :initarg :id) + (token :initarg :token :initform nil) + (client-id :initarg :client-id) + (client-secret :initarg :client-secret) + (name :initarg :name :initform nil) + (domain :initarg :domain) + (self :initarg :self) + (self-id :initarg :self-id) + (self-name :initarg :self-name) + (channels :initarg :channels :initform nil) + (groups :initarg :groups :initform nil) + (ims :initarg :ims :initform nil) + (file-room :initform nil) + (search-results :initform nil) + (users :initarg :users :initform nil) + (bots :initarg :bots :initform nil) + (ws-url :initarg :ws-url) + (ws-conn :initarg :ws-conn :initform nil) + (ping-timer :initform nil) + (check-ping-timeout-timer :initform nil) + (check-ping-timeout-sec :initarg :check-ping-timeout-sec :initform 20) + (reconnect-auto :initarg :reconnect-auto :initform t) + (reconnect-timer :initform nil) + (reconnect-after-sec :initform 10) + (reconnect-count :initform 0) + (reconnect-count-max :initform 360) + (last-pong :initform nil) + (waiting-send :initform nil) + (sent-message :initform (make-hash-table)) + (message-id :initform 0) + (connected :initform nil) + (subscribed-channels :initarg :subscribed-channels + :type list :initform nil) + (typing :initform nil) + (typing-timer :initform nil) + (reminders :initform nil :type list) + (ping-check-timers :initform (make-hash-table :test 'equal)) + (threads :type slack-team-threads :initform (make-instance 'slack-team-threads)) + (modeline-enabled :initarg :modeline-enabled :initform nil) + (modeline-name :initarg :modeline-name :initform nil) + (websocket-event-log-enabled :initarg :websocket-event-log-enabled :initform nil) + (display-profile-image :initarg :display-profile-image :initform nil) + (display-attachment-image-inline :initarg :display-attachment-image-inline :initform nil) + (display-file-image-inline :initarg :display-file-image-inline :initform nil) + (waiting-requests :initform nil) + (authorize-request :initform nil) + (emoji-download-watch-timer :initform nil) + (websocket-nowait :initarg :websocket-nowait :initform nil) + (star :initform nil) + (slack-message-buffer :initform nil :type (or null list)) + (slack-file-info-buffer :initform nil :type (or null list)) + (slack-file-list-buffer :initform nil :type (or null list)) + (slack-message-edit-buffer :initform nil :type (or null list)) + (slack-pinned-items-buffer :initform nil :type (or null list)) + (slack-user-profile-buffer :initform nil :type (or null list)) + (slack-thread-message-buffer :initform nil :type (or null list)) + (slack-message-share-buffer :initform nil :type (or null list)) + (slack-room-message-compose-buffer :initform nil :type (or null list)) + (slack-thread-message-compose-buffer :initform nil :type (or null list)) + (slack-stars-buffer :initform nil :type (or null list)) + (slack-search-result-buffer :initform nil :type (or null list)) + (slack-dialog-buffer :initform nil :type (or null list)) + (slack-dialog-edit-element-buffer :initform nil :type (or null list)) + (slack-room-info-buffer :initform nil :type (or null list)) + (reconnect-url :initform "" :type string) + (full-and-display-names :initarg :full-and-display-names :initform nil) + (websocket-connect-timeout-timer :initform nil) + (websocket-connect-timeout-sec :type number :initform 20) ;; websocket url is valid for 30 seconds. + (mark-as-read-immediately :initarg :mark-as-read-immediately :initform t) + (inhibit-reconnection :initform nil) + (commands :initform '() :type list) + )) + +(cl-defmethod slack-team-kill-buffers ((this slack-team) &key (except nil)) + (let* ((l (list 'slack-message-buffer + 'slack-file-info-buffer + 'slack-file-list-buffer + 'slack-message-edit-buffer + 'slack-pinned-items-buffer + 'slack-user-profile-buffer + 'slack-thread-message-buffer + 'slack-message-share-buffer + 'slack-room-message-compose-buffer + 'slack-thread-message-compose-buffer + 'slack-search-result-buffer + 'slack-stars-buffer)) + (slots (cl-remove-if #'(lambda (e) (cl-find e except)) l))) + (cl-loop for slot in slots + do (cl-loop for buffer in (slot-value this slot) + do (kill-buffer buffer))))) + +(defun slack-team-find (id) + (cl-find-if #'(lambda (team) (string= id (oref team id))) + slack-teams)) + +(defmethod slack-team-disconnect ((team slack-team)) + (slack-ws-close team)) + +(defmethod slack-team-equalp ((team slack-team) other) + (with-slots (token) team + (string= token (oref other token)))) + +(defmethod slack-team-name ((team slack-team)) + (oref team name)) + +;;;###autoload +(defun slack-register-team (&rest plist) + "PLIST must contain :name :client-id :client-secret with value. +setting :token will reduce your configuration step. +you will notified when receive message with channel included in subscribed-channels. +if :default is t and `slack-prefer-current-team' is t, skip selecting team when channels listed. +you can change current-team with `slack-change-current-team'" + (interactive + (let ((name (read-from-minibuffer "Team Name: ")) + (client-id (read-from-minibuffer "Client Id: ")) + (client-secret (read-from-minibuffer "Client Secret: ")) + (token (read-from-minibuffer "Token: "))) + (list :name name :client-id client-id :client-secret client-secret + :token token))) + (cl-labels ((same-client-id + (client-id) + (cl-find-if #'(lambda (team) + (string= client-id (oref team client-id))) + slack-teams)) + (missing (plist) + (cl-remove-if + #'null + (mapcar #'(lambda (key) + (unless (plist-member plist key) + key)) + '(:name :client-id :client-secret))))) + (let ((missing (missing plist))) + (if missing + (error "Missing Keyword: %s" missing))) + (let ((team (apply #'slack-team "team" + (slack-collect-slots 'slack-team plist)))) + (let ((same-team (cl-find-if + #'(lambda (o) (slack-team-equalp team o)) + slack-teams))) + (if same-team + (progn + (slack-team-disconnect same-team) + (slack-start team)))) + + (setq slack-teams + (cons team + (cl-remove-if #'(lambda (other) + (slack-team-equalp team other)) + slack-teams))) + (if (plist-get plist :default) + (setq slack-current-team team))))) + +(defun slack-team-find-by-name (name) + (if name + (cl-find-if #'(lambda (team) (string= name (oref team name))) + slack-teams))) + +(cl-defun slack-team-select (&optional no-default include-not-connected) + (cl-labels ((select-team () + (slack-team-find-by-name + (funcall slack-completing-read-function + "Select Team: " + (mapcar #'(lambda (team) (oref team name)) + (if include-not-connected + slack-teams + (slack-team-connected-list))))))) + (let ((team (if (and slack-prefer-current-team + slack-current-team + (not no-default)) + slack-current-team + (select-team)))) + ;; (if (and slack-prefer-current-team + ;; (not slack-current-team) + ;; (not no-default)) + ;; (if (yes-or-no-p (format "Set %s to current-team?" + ;; (oref team name))) + ;; (setq slack-current-team team))) + team))) + +(defmethod slack-team-connectedp ((team slack-team)) + (oref team connected)) + +(defun slack-team-connected-list () + (cl-remove-if #'null + (mapcar #'(lambda (team) + (if (slack-team-connectedp team) team)) + slack-teams))) + +(defun slack-change-current-team () + (interactive) + (let ((team (slack-team-find-by-name + (funcall slack-completing-read-function + "Select Team: " + (mapcar #'(lambda (team) (oref team name)) + slack-teams))))) + (setq slack-current-team team) + (message "Set slack-current-team to %s" (or (and team (oref team name)) + "nil")) + (setq slack-teams + (cons team (cl-remove-if #'(lambda (e) + (string= (oref e id) + (oref slack-current-team id))) + slack-teams))) + (if team + (slack-team-connect team)))) + +(defmethod slack-team-connect ((team slack-team)) + (unless (slack-team-connectedp team) + (slack-start team))) + +(defun slack-team-delete () + (interactive) + (let ((selected (slack-team-select t t))) + (if (yes-or-no-p (format "Delete %s from `slack-teams'?" + (oref selected name))) + (progn + (setq slack-teams + (cl-remove-if #'(lambda (team) + (slack-team-equalp selected team)) + slack-teams)) + (slack-team-disconnect selected) + (message "Delete %s from `slack-teams'" (oref selected name)))))) + +(defmethod slack-team-init-ping-check-timers ((team slack-team)) + (oset team ping-check-timers (make-hash-table :test 'equal))) + +(defmethod slack-team-get-ping-check-timers ((team slack-team)) + (if (not (slot-boundp team 'ping-check-timers)) + (slack-team-init-ping-check-timers team)) + (oref team ping-check-timers)) + +(defmethod slack-team-need-token-p ((team slack-team)) + (with-slots (token) team + (or (not token) (< (length token) 1)))) + +(defun slack-team-get-unread-messages (team) + (cl-labels + ((count-unread (rooms) + (cl-reduce #'(lambda (a e) (+ a (oref e unread-count-display))) + rooms :initial-value 0))) + (with-slots (ims channels groups) team + (let ((rooms (append ims channels groups))) + (+ (count-unread (if slack-modeline-count-only-subscribed-channel + (cl-remove-if-not #'(lambda (e) (slack-room-subscribedp e team)) + rooms) + rooms))))))) + +(defun slack-team-modeline-enabledp (team) + (oref team modeline-enabled)) + +(defmethod slack-team-event-log-enabledp ((team slack-team)) + (oref team websocket-event-log-enabled)) + +(defmethod slack-team-display-profile-imagep ((team slack-team)) + (oref team display-profile-image)) + +(defmethod slack-team-display-attachment-image-inlinep ((team slack-team)) + (oref team display-attachment-image-inline)) + +(defmethod slack-team-display-file-image-inlinep ((team slack-team)) + (oref team display-file-image-inline)) + +(defmethod slack-team-mark-as-read-immediatelyp ((team slack-team)) + (oref team mark-as-read-immediately)) + +(defvar slack-team-random-numbers-for-client-token + (let ((result nil)) + (dotimes (_ 10) + (push (random 10) result)) + (mapconcat #'number-to-string result ""))) + +(defmethod slack-team-client-token ((team slack-team)) + (format "EmacsSlack-%s-%s" + (oref team id) + slack-team-random-numbers-for-client-token)) + +(provide 'slack-team) +;;; slack-team.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-team.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-team.elc new file mode 100644 index 000000000000..8e09ae2b86f1 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-team.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-thread-message-buffer.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-thread-message-buffer.el new file mode 100644 index 000000000000..6ad6e5a93e42 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-thread-message-buffer.el @@ -0,0 +1,148 @@ +;;; slack-thread-message-buffer.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 + +;; Author: <yuya373@yuya373> +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: + +(require 'eieio) +(require 'slack-util) +(require 'slack-room-buffer) + +(define-derived-mode slack-thread-message-buffer-mode + slack-buffer-mode + "Slack Thread Message" + (lui-set-prompt lui-prompt-string) + (setq lui-input-function 'slack-thread-message--send)) + +(defclass slack-thread-message-buffer (slack-room-buffer) + ((thread-ts :initarg :thread-ts :type string))) + +(defmethod slack-buffer-find :static ((class slack-thread-message-buffer) room ts team) + (slack-buffer-find-4 class room ts team)) + +(defun slack-create-thread-message-buffer (room team thread-ts) + (slack-if-let* ((buf (slack-buffer-find 'slack-thread-message-buffer + room thread-ts team))) + buf + (slack-thread-message-buffer :room room + :team team + :thread-ts thread-ts))) + +(defmethod slack-buffer-name :static ((class slack-thread-message-buffer) room ts team) + (format "*Slack - %s : %s Thread - %s" + (oref team name) + (slack-room-name room team) + ts)) + +(defmethod slack-buffer-name ((this slack-thread-message-buffer)) + (with-slots (room thread-ts team) this + (slack-buffer-name 'slack-thread-message-buffer + room thread-ts team))) + +(defmethod slack-buffer-init-buffer ((this slack-thread-message-buffer)) + (let* ((buf (generate-new-buffer (slack-buffer-name this)))) + (with-current-buffer buf + (slack-thread-message-buffer-mode) + (slack-buffer-set-current-buffer this) + (goto-char lui-input-marker) + (with-slots (room thread-ts team) this + (slack-if-let* ((message (slack-room-find-message room thread-ts))) + (progn + (slack-buffer-insert this message t) + (let ((lui-time-stamp-position nil)) + (lui-insert (format "%s\n" (make-string lui-fill-column ?=)) t)) + (let ((thread (slack-message-thread message room))) + (and thread + (cl-loop for m in (oref thread messages) + do (slack-buffer-insert this m)))))))) + + (with-slots (room thread-ts team) this + (slack-buffer-push-new-4 (eieio-object-class-name this) + room + thread-ts + team)) + + buf)) + +(defmethod slack-buffer-display-message-compose-buffer + ((this slack-thread-message-buffer)) + (with-slots (room team thread-ts) this + (let ((buf (slack-create-thread-message-compose-buffer + room thread-ts team))) + (slack-buffer-display buf)))) + + +(defmethod slack-buffer-send-message ((this slack-thread-message-buffer) message) + (with-slots (room team thread-ts) this + (slack-thread-send-message room team message thread-ts))) + +(defmethod slack-buffer-add-reaction-to-message + ((this slack-thread-message-buffer) reaction ts) + (with-slots (room team) this + (slack-message-reaction-add reaction ts room team))) + +(defmethod slack-buffer-remove-reaction-from-message + ((this slack-thread-message-buffer) ts) + (with-slots (room team) this + (let* ((message (slack-room-find-message room ts)) + (reaction (slack-message-reaction-select + (slack-message-reactions message)))) + (slack-message-reaction-remove reaction ts room team)))) + +(defmethod slack-buffer-add-star ((this slack-thread-message-buffer) ts) + (with-slots (room team) this + (slack-if-let* ((message (slack-room-find-message room ts))) + (slack-message-star-api-request slack-message-stars-add-url + (list (cons "channel" (oref room id)) + (slack-message-star-api-params message)) + team)))) + +(defmethod slack-buffer-remove-star ((this slack-thread-message-buffer) ts) + (with-slots (room team) this + (slack-if-let* ((message (slack-room-find-message room ts))) + (slack-message-star-api-request slack-message-stars-remove-url + (list (cons "channel" (oref room id)) + (slack-message-star-api-params message)) + team)))) + +(cl-defmethod slack-buffer-update ((this slack-thread-message-buffer) message &key replace) + (if replace (slack-buffer-replace this message) + (with-current-buffer (slack-buffer-buffer this) + (slack-buffer-insert this message)))) + +(defmethod slack-buffer-display-edit-message-buffer ((this slack-thread-message-buffer) ts) + (with-slots (room team) this + (let ((buf (slack-create-edit-message-buffer room team ts))) + (slack-buffer-display buf)))) + +(defmethod slack-buffer-share-message ((this slack-thread-message-buffer) ts) + (with-slots (room team) this + (let ((buf (slack-create-message-share-buffer room team ts))) + (slack-buffer-display buf)))) + +(defmethod slack-file-upload-params ((this slack-thread-message-buffer)) + (list (cons "thread_ts" (oref this thread-ts)) + (cons "channels" (oref (oref this room) id)))) + +(provide 'slack-thread-message-buffer) +;;; slack-thread-message-buffer.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-thread-message-buffer.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-thread-message-buffer.elc new file mode 100644 index 000000000000..0b1a149cc504 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-thread-message-buffer.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-thread-message-compose-buffer.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-thread-message-compose-buffer.el new file mode 100644 index 000000000000..4c4f276d1fe5 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-thread-message-compose-buffer.el @@ -0,0 +1,79 @@ +;;; slack-thread-message-compose-buffer.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 + +;; Author: <yuya373@yuya373> +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: + +(require 'eieio) +(require 'slack-util) +(require 'slack-message-compose-buffer) + +(defclass slack-thread-message-compose-buffer (slack-message-compose-buffer) + ((room :initarg :room :type slack-room) + (thread-ts :initarg :thread-ts :type string))) + +(defmethod slack-buffer-find :static ((class slack-thread-message-compose-buffer) room ts team) + (slack-buffer-find-4 class room ts team)) + +(defmethod slack-buffer-name :static + ((class slack-thread-message-compose-buffer) room ts team) + (format "*Slack - %s : %s Compose Thread Message - %s*" + (oref team name) + (slack-room-name room team) + ts)) + +(defmethod slack-buffer-name ((this slack-thread-message-compose-buffer)) + (with-slots (room thread-ts team) this + (slack-buffer-name 'slack-thread-message-compose-buffer + room thread-ts team))) + +(defmethod slack-buffer-init-buffer ((this slack-thread-message-compose-buffer)) + (let ((buf (call-next-method))) + (with-current-buffer buf + (slack-message-compose-buffer-mode) + (slack-buffer-set-current-buffer this) + (setq buffer-read-only nil) + (erase-buffer)) + (with-slots (room thread-ts team) this + (slack-buffer-push-new-4 'slack-thread-message-compose-buffer + room thread-ts team)) + buf)) + +(defun slack-create-thread-message-compose-buffer (room ts team) + (slack-if-let* ((buf (slack-buffer-find 'slack-thread-message-compose-buffer + room ts team))) + buf + (slack-thread-message-compose-buffer :room room + :team team + :thread-ts ts))) + +(defmethod slack-buffer-send-message + ((this slack-thread-message-compose-buffer) message) + (let ((buffer (slack-buffer-buffer this))) + (with-slots (room team thread-ts) this + (slack-thread-send-message room team message thread-ts))) + (call-next-method)) + + +(provide 'slack-thread-message-compose-buffer) +;;; slack-thread-message-compose-buffer.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-thread-message-compose-buffer.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-thread-message-compose-buffer.elc new file mode 100644 index 000000000000..a9a504d44dfb --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-thread-message-compose-buffer.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-thread.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-thread.el new file mode 100644 index 000000000000..2a9c6f98a8a0 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-thread.el @@ -0,0 +1,333 @@ +;;; slack-thread.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 ๅๅชไน + +;; Author: ๅๅชไน <yuyaminami@minamiyuuya-no-MacBook.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-room) +(require 'slack-channel) +(require 'slack-im) +(require 'slack-message) +(require 'slack-request) + +(defvar lui-prompt-string "> ") +(defconst all-threads-url "https://slack.com/api/subscriptions.thread.getView") +(defconst thread-mark-url "https://slack.com/api/subscriptions.thread.mark") + +(defcustom slack-thread-also-send-to-room 'ask + "Whether a thread message should also be sent to its room. +If nil: don't send to the room. +If `ask': ask the user every time. +Any other non-nil value: send to the room." + :type '(choice (const :tag "Never send message to the room." nil) + (const :tag "Ask the user every time." ask) + (const :tag "Always send message to the room." t))) + +(define-derived-mode slack-thread-mode slack-mode "Slack - Thread" + "" + (lui-set-prompt lui-prompt-string) + (setq lui-input-function 'slack-thread-message--send)) + +(defclass slack-thread () + ((thread-ts :initarg :thread_ts :initform "") + (messages :initarg :messages :initform '()) + (has-unreads :initarg :has_unreads :initform nil) + (mention-count :initarg :mention_count :initform 0) + (reply-count :initarg :reply_count :initform 0) + (replies :initarg :replies :initform '()) + (active :initarg :active :initform t) + (root :initarg :root :type slack-message) + (unread-count :initarg :unread_count :initform 0) + (last-read :initarg :last_read :initform "0"))) + +(defmethod slack-thread-messagep ((m slack-message)) + (if (and (oref m thread-ts) (not (slack-message-thread-parentp m))) + t + nil)) + +(defun slack-thread-start () + (interactive) + (slack-if-let* ((buf slack-current-buffer)) + (slack-buffer-start-thread buf (slack-get-ts)))) + +(defun slack-thread-message--send (message) + (slack-if-let* ((buf slack-current-buffer)) + (slack-buffer-send-message buf message))) + +(defun slack-thread-send-message (room team message thread-ts) + (let ((message (slack-message-prepare-links + (slack-escape-message message) + team)) + (broadcast (if (eq slack-thread-also-send-to-room 'ask) + (y-or-n-p (format "Also send to %s ? " + (slack-room-name room team))) + slack-thread-also-send-to-room))) + (progn + (slack-message-inc-id team) + (with-slots (message-id sent-message self-id) team + (let* ((payload (list :id message-id + :channel (oref room id) + :reply_broadcast broadcast + :thread_ts thread-ts + :type "message" + :user self-id + :text message)) + (obj (slack-message-create payload team :room room))) + (slack-ws-send payload team) + (puthash message-id obj sent-message)))))) + +(defun slack-thread-show-or-create () + (interactive) + (slack-if-let* ((buf slack-current-buffer)) + (if (slack-thread-message-buffer-p buf) + (error "Already in thread") + (slack-buffer-display-thread buf (slack-get-ts))))) + +(cl-defmethod slack-thread-request-messages ((thread slack-thread) room team &key after-success) + (cl-labels + ((on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-thread-request-messages") + (let ((messages (mapcar #'(lambda (payload) + (slack-message-create payload + team + :room room)) + (plist-get data :messages)))) + (oset thread messages + (slack-room-sort-messages + (cl-remove-if #'slack-message-thread-parentp + messages))))) + (if after-success + (funcall after-success)))) + + (slack-request + (slack-request-create + (slack-room-replies-url room) + team + :params (list (cons "thread_ts" (oref thread thread-ts)) + (cons "channel" (oref room id))) + :success #'on-success)))) + +(defmethod slack-thread-show-messages ((thread slack-thread) room team) + (cl-labels + ((after-success () + (let ((buf (slack-create-thread-message-buffer + room team (oref thread thread-ts)))) + (slack-buffer-display buf)))) + (slack-thread-request-messages thread room team + :after-success #'after-success))) + +(defmethod slack-thread-to-string ((m slack-message) team) + (with-slots (thread) m + (if thread + (let* ((usernames (mapconcat #'identity + (cl-remove-duplicates + (mapcar #'(lambda (reply) + (slack-user-name + (plist-get reply :user) + team)) + (oref thread replies)) + :test #'string=) + " ")) + (text (format "\n%s reply from %s" + (oref thread reply-count) + usernames))) + (propertize text + 'face '(:underline t) + 'keymap (let ((map (make-sparse-keymap))) + (define-key map [mouse-1] #'slack-thread-show-or-create) + (define-key map (kbd "RET") #'slack-thread-show-or-create) + map))) + ""))) + +(defmethod slack-thread-create ((m slack-message) team &optional payload) + (if payload + (let ((replies (plist-get payload :replies)) + (reply-count (plist-get payload :reply_count)) + (unread-count (plist-get payload :unread_count)) + (last-read (plist-get payload :last_read))) + (make-instance 'slack-thread + :thread_ts (slack-ts m) + :root m + :replies replies + :reply_count (or reply-count 0) + :unread_count (or unread-count 1) + :last_read last-read)) + (make-instance 'slack-thread + :thread_ts (slack-ts m) + :root m))) + +(defmethod slack-merge ((old slack-thread) new) + (oset old replies (oref new replies)) + (oset old reply-count (oref new reply-count)) + (oset old unread-count (oref new unread-count))) + +(defun slack-thread-update-state (payload team) + (slack-if-let* ((message-payload (plist-get payload :message)) + (thread-ts (plist-get message-payload :thread_ts)) + (room (slack-room-find (plist-get payload :channel) team)) + (message (slack-room-find-message room thread-ts)) + (thread (slack-message-get-thread message team)) + (new-thread (slack-thread-create message team message-payload))) + (progn + (slack-merge thread new-thread) + (slack-message-update message team t t)) + (message "THREAD_TS: %s, ROOM: %s, MESSAGE: %s THREAD: %s, NEW_THREAD:%s" + thread-ts + (not (null room)) + (not (null message)) + (not (null thread)) + (not (null new-thread))))) + +(defmethod slack-thread-equal ((thread slack-thread) other) + (and (string-equal (oref thread thread-ts) + (oref other thread-ts)) + (string-equal (oref (oref thread root) channel) + (oref (oref other root) channel)))) + +(cl-defun slack-thread-get-all (&key (sync nil) (ts nil)) + (let ((team (slack-team-select))) + (cl-labels + ((on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-thread-get-all") + (let ((threads-data (append (plist-get data :threads) nil)) + (total-unread (plist-get data :total_unread_replies)) + (more (if (eq :json-false (plist-get data :has_more)) nil t)) + (new-count (plist-get data :new_threads_count))) + (with-slots (threads) team + (with-slots + (initializedp total-unread-replies new-threads-count has-more) threads + (setq has-more more) + (setq initializedp t) + (setq total-unread-replies total-unread) + (setq new-threads-count new-count) + (let ((parents (cl-loop for thread in threads-data + collect (slack-message-create + (plist-get thread :root_msg) team)))) + (mapc #'(lambda (parent) (slack-message-update parent team nil t)) + parents)))))))) + (slack-request + (slack-request-create + all-threads-url + team + :type "POST" + :params (list (cons "limit" "10") + (cons "current_ts" (or ts (format-time-string "%s")))) + :success #'on-success))))) + +(defmethod slack-thread-title ((thread slack-thread) team) + (with-slots (root) thread + (let ((room (slack-room-find (oref root channel) team)) + (body (slack-message-body root team))) + (when room + (format "%s - %s" (slack-room-name room team) + (concat (substring body 0 (min 50 (length body))) "...")))))) + +(defun slack-thread-select (&optional reload) + (interactive) + (cl-labels + ((load-threads (threads) + (slack-thread-get-all :sync t + :ts (cl-first + (cl-sort + (mapcar #'(lambda (thread) (oref thread thread-ts)) threads) + #'string<)))) + (select-thread (threads team has-more) + (let* ((alist (cl-remove-if-not + #'(lambda (cons) (car cons)) + (mapcar #'(lambda (thread) + (let ((title (slack-thread-title thread team))) + (and title (cons title thread)))) + threads))) + (maybe-has-more (if has-more + (append alist (list (cons "(load more)" 'load-more))) alist)) + (selected (slack-select-from-list (maybe-has-more "Select Thread: ")))) + selected)) + (collect-thread-parents (messages) + (mapcar #'(lambda (m) (oref m thread)) + (cl-remove-if #'(lambda (m) (not (slack-message-thread-parentp m))) + messages))) + (collect-threads (team) + (cl-loop for room in (with-slots (groups ims channels) team + (append ims groups channels)) + append (collect-thread-parents (oref room messages))))) + + (let* ((team (slack-team-select))) + + (with-slots (initializedp has-more) (oref team threads) + (if (or (not initializedp) has-more) (load-threads (collect-threads team)))) + + (let ((selected (select-thread (collect-threads team) team nil))) + (if (eq selected 'load-more) + (slack-thread-select t) + (slack-thread-show-messages selected + (slack-room-find (oref (oref selected root) channel) team) + team)))))) + +(defmethod slack-thread-delete-message ((thread slack-thread) message) + (with-slots (messages reply-count) thread + (setq messages (cl-remove-if #'(lambda (e) + (string= (slack-ts e) + (slack-ts message))) + messages)) + (setq reply-count (length messages)))) + +(defmethod slack-thread-update-mark ((thread slack-thread) room msg team) + (with-slots (thread-ts) thread + (with-slots (id) room + (with-slots (ts) msg + (cl-labels + ((on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-thread-mark")))) + + (slack-request + (slack-request-create + thread-mark-url + team + :params (list (cons "channel" id) + (cons "thread_ts" thread-ts) + (cons "ts" ts)) + :success #'on-success))))))) + +(defmethod slack-thread-marked ((thread slack-thread) payload) + (let ((unread-count (plist-get payload :unread_count)) + (last-read (plist-get payload :last_read))) + (oset thread unread-count unread-count) + (oset thread last-read last-read))) + +(defun slack-room-unread-threads () + (interactive) + (slack-if-let* ((buf slack-current-buffer)) + (slack-buffer-display-unread-threads buf))) + +(defmethod slack-thread-update-last-read ((thread slack-thread) msg) + (with-slots (ts) msg + (oset thread last-read ts))) + +(provide 'slack-thread) +;;; slack-thread.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-thread.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-thread.elc new file mode 100644 index 000000000000..3612ab3223ab --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-thread.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-user-message.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-user-message.el new file mode 100644 index 000000000000..a79edb9de110 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-user-message.el @@ -0,0 +1,35 @@ +;;; package --- Summary +;;; Commentary: + +;;; Code: + +(require 'eieio) +(require 'slack-message-formatter) +(require 'slack-message-reaction) +(require 'slack-message-editor) + +(defvar slack-user-message-keymap + (let ((keymap (make-sparse-keymap))) + keymap)) + +(defmethod slack-message-sender-equalp ((m slack-user-message) sender-id) + (string= (oref m user) sender-id)) + +(defmethod slack-message-header ((m slack-user-message) team) + (with-slots (ts deleted-at) m + (let* ((name (slack-message-sender-name m team)) + (status (slack-user-status (slack-message-sender-id m) team)) + (time (slack-message-time-to-string ts)) + (edited-at (slack-message-time-to-string (slack-message-edited-at m))) + (deleted-at (slack-message-time-to-string deleted-at)) + (header (or (and status (< 0 (length status)) + (format "%s %s" name status)) + (format "%s" name)))) + (if deleted-at + (format "%s deleted_at: %s" header deleted-at) + (if edited-at + (format "%s edited_at: %s" header edited-at) + header))))) + +(provide 'slack-user-message) +;;; slack-user-message.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-user-message.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-user-message.elc new file mode 100644 index 000000000000..627aaa504562 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-user-message.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-user-profile-buffer.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-user-profile-buffer.el new file mode 100644 index 000000000000..e0e645c27a22 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-user-profile-buffer.el @@ -0,0 +1,96 @@ +;;; slack-user-profile-buffer.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 + +;; Author: <yuya373@yuya373> +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: + +(require 'eieio) +(require 'slack-util) +(require 'slack-buffer) + +(define-derived-mode slack-user-profile-buffer-mode slack-buffer-mode "Slack User Profile") + +(defclass slack-user-profile-buffer (slack-buffer) + ((user-id :initarg :user-id :type string))) + +(defun slack-create-user-profile-buffer (team user-id) + (slack-if-let* ((buf (slack-buffer-find 'slack-user-profile-buffer + user-id team))) + buf + (slack-user-profile-buffer :team team + :user-id user-id))) + +(defmethod slack-buffer-buffer ((this slack-user-profile-buffer)) + (slack-if-let* ((buf (get-buffer (slack-buffer-name this)))) + (progn + (slack-buffer--insert this) + buf) + (slack-buffer-init-buffer this))) + +(defmethod slack-buffer-name :static ((class slack-user-profile-buffer) user-id team) + (format "*Slack - %s : Profile - %s*" (oref team name) (slack-user-name user-id team))) + +(defmethod slack-buffer-name ((this slack-user-profile-buffer)) + (with-slots (user-id team) this + (slack-buffer-name 'slack-user-profile-buffer + user-id + team))) + +(defmethod slack-buffer--insert ((this slack-user-profile-buffer)) + (let ((buf (get-buffer (slack-buffer-name this)))) + (with-current-buffer buf + (let ((inhibit-read-only t)) + (setq buffer-read-only nil) + (erase-buffer) + (goto-char (point-min)) + (with-slots (user-id team) this + (insert (propertize (slack-user-profile-to-string user-id team) + 'ts 'dummy))) + (setq buffer-read-only t) + (slack-buffer-enable-emojify) + (goto-char (point-min)) + (slack-display-image))))) + +(defmethod slack-buffer-init-buffer ((this slack-user-profile-buffer)) + (let ((buf (call-next-method))) + (with-current-buffer buf + (slack-user-profile-buffer-mode) + (slack-buffer-set-current-buffer this)) + (slack-buffer--insert this) + buf)) + +(defmethod slack-buffer-display-im ((this slack-user-profile-buffer)) + (with-slots (user-id team) this + (let ((im (slack-im-find-by-user-id user-id team))) + (slack-room-display im team)))) + +(defmethod slack-buffer--replace ((this slack-user-profile-buffer) _ts) + (with-current-buffer (current-buffer) + (let ((inhibit-read-only t)) + (delete-region (point-min) (point-max)) + (slack-buffer--insert this)))) + + + +(provide 'slack-user-profile-buffer) +;;; slack-user-profile-buffer.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-user-profile-buffer.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-user-profile-buffer.elc new file mode 100644 index 000000000000..9c0175679046 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-user-profile-buffer.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-user.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-user.el new file mode 100644 index 000000000000..3653a6d1c184 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-user.el @@ -0,0 +1,398 @@ +;;; slack-user.el ---slack user 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 'slack-util) +(require 'slack-request) +(require 'slack-room) + +(defconst slack-dnd-team-info-url "https://slack.com/api/dnd.teamInfo") +(defconst slack-dnd-end-dnd-url "https://slack.com/api/dnd.endDnd") +(defconst slack-dnd-set-snooze-url "https://slack.com/api/dnd.setSnooze") +(defconst slack-set-presence-url "https://slack.com/api/users.setPresence") +(defconst slack-user-info-url "https://slack.com/api/users.info") +(defconst slack-user-profile-set-url "https://slack.com/api/users.profile.set") +(defconst slack-bot-info-url "https://slack.com/api/bots.info") +(defconst slack-bot-list-url "https://slack.com/api/bots.list") +(defvar slack-current-user-id nil) + +(defun slack-user--find (id team) + (with-slots (users) team + (cl-find-if (lambda (user) + (string= id (plist-get user :id))) + users))) + +(defun slack-user-find-by-name (name team) + (with-slots (users) team + (cl-find-if (lambda (user) + (string= name (plist-get user :name))) + users))) + +(defun slack-user-get-id (name team) + (let ((user (slack-user-find-by-name name team))) + (if user + (plist-get user :id)))) + +(defun slack-user-name (id team) + (slack-if-let* ((user (slack-user--find id team))) + (if (oref team full-and-display-names) + (plist-get user :real_name) + (plist-get user :name)))) + +(defun slack-user-status (id team) + (let* ((user (slack-user--find id team)) + (profile (and user (plist-get user :profile))) + (emoji (and profile (plist-get profile :status_emoji))) + (text (and profile (plist-get profile :status_text)))) + (mapconcat #'identity (cl-remove-if #'null (list emoji text)) + " "))) + +(defun slack-user-names (team) + (with-slots (users) team + (mapcar (lambda (u) (cons (plist-get u :name) u)) + (cl-remove-if #'slack-user-hidden-p users)))) + +(defun slack-user-dnd-in-range-p (user) + (let ((current (time-to-seconds)) + (dnd-start (plist-get (plist-get user :dnd_status) :next_dnd_start_ts)) + (dnd-end (plist-get (plist-get user :dnd_status) :next_dnd_end_ts))) + (and dnd-start dnd-end + (<= dnd-start current) + (<= current dnd-end)))) + +(defun slack-user-dnd-status-to-string (user) + (if (slack-user-dnd-in-range-p user) + "Z" + nil)) + +(defun slack-user-presence-to-string (user) + (if (string= (plist-get user :presence) "active") + "*" + " ")) + +(defun slack-user-set-status () + (interactive) + (let ((team (slack-team-select)) + (emoji (slack-select-emoji)) + (text (read-from-minibuffer "Text: "))) + (slack-user-set-status-request team emoji text))) + +(defun slack-user-set-status-request (team emoji text) + (cl-labels ((on-success + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-user-set-status-request")))) + (slack-request + (slack-request-create + slack-user-profile-set-url + team + :type "POST" + :data (list (cons "id" (oref team self-id)) + (cons "profile" + (json-encode (list (cons "status_text" text) + (cons "status_emoji" emoji))))) + :success #'on-success)))) + +(defun slack-bot-info-request (bot_id team &optional after-success) + (cl-labels + ((on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-bot-info-request") + (push (plist-get data :bot) (oref team bots)) + (if after-success + (funcall after-success team))))) + (slack-request + (slack-request-create + slack-bot-info-url + team + :params (list (cons "bot" bot_id)) + :success #'on-success)))) + +(defun slack-bot-list-update (&optional team) + (interactive) + (let ((team (or team (slack-team-select)))) + (cl-labels + ((on-success + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-bot-list-update") + (oset team bots (append (plist-get data :bots) nil))))) + (slack-request + (slack-request-create + slack-bot-list-url + team + :success #'on-success))))) + +(defface slack-user-profile-header-face + '((t (:foreground "#FFA000" + :weight bold + :height 1.5))) + "Face used to user profile header." + :group 'slack) + +(defface slack-user-profile-property-name-face + '((t (:weight bold :height 1.2))) + "Face used to user property." + :group 'slack) + +(define-derived-mode slack-user-profile-mode fundamental-mode "Slack User" + "" + (setq-local default-directory slack-default-directory)) + +(defun slack-user-profile (user) + (plist-get user :profile)) + +(defun slack-user-fname (user) + (plist-get (slack-user-profile user) :first_name)) + +(defun slack-user-lname (user) + (plist-get (slack-user-profile user) :last_name)) + +(defun slack-user-header (user) + (let* ((fname (slack-user-fname user)) + (lname (slack-user-lname user)) + (name (plist-get user :name))) + (or (and fname lname + (format "%s %s - @%s" + (slack-user-fname user) + (slack-user-lname user) + (plist-get user :name))) + name))) + +(defun slack-user-timezone (user) + (let ((offset (/ (plist-get user :tz_offset) (* 60 60)))) + (format "%s, %s" + (or (plist-get user :tz) + (plist-get user :tz_label)) + (if (<= 0 offset) + (format "+%s hour" offset) + (format "%s hour" offset))))) + +(defun slack-user-property-to-str (value title) + (and value (< 0 (length value)) + (format "%s\n\t%s" + (propertize title 'face 'slack-user-profile-property-name-face) + value))) + +(defun slack-user-profile-to-string (id team) + (let* ((user (slack-user--find id team)) + (image (slack-image-string (list (slack-user-image-url user 512) + nil nil nil (window-width + (get-buffer-window + (current-buffer)) + t)) + nil t)) + (profile (slack-user-profile user)) + (header (propertize (slack-user-header user) + 'face 'slack-user-profile-header-face)) + (presence (slack-user-property-to-str (plist-get user :presence) "Presence")) + (status (slack-user-property-to-str (slack-user-status id team) "Status")) + (timezone (slack-user-property-to-str (slack-user-timezone user) "Timezone")) + (email (slack-user-property-to-str (plist-get profile :email) "Email")) + (phone (slack-user-property-to-str (plist-get profile :phone) "Phone")) + (skype (slack-user-property-to-str (plist-get profile :skype) "Skype")) + (body (mapconcat #'identity + (cl-remove-if #'null + (list presence status timezone email phone skype)) + "\n")) + (dm-button (propertize "[Open Direct Message]" + 'face '(:underline t) + 'keymap (let ((map (make-sparse-keymap))) + (define-key map (kbd "RET") + #'(lambda () + (interactive) + (slack-if-let* ((buf slack-current-buffer)) + (slack-buffer-display-im buf)))) + map)))) + (format "\n%s\n\n%s%s\n%s\n\n%s" image header (format " (%s)" id) body dm-button))) + +(defun slack-user-self-p (user-id team) + (string= user-id (oref team self-id))) + +(defun slack-user-name-alist (team &key filter) + (let ((users (oref team users))) + (mapcar #'(lambda (e) (cons (slack-user-name (plist-get e :id) team) e)) + (if filter (funcall filter users) + users)))) + +(defun slack-user-hidden-p (user) + (not (eq (plist-get user :deleted) :json-false))) + +(defun slack--user-select (team) + (slack-select-from-list ((slack-user-names team) "Select User: "))) + +(defun slack-user-select () + (interactive) + (let* ((team (slack-team-select)) + (alist (slack-user-name-alist + team + :filter #'(lambda (users) + (cl-remove-if #'slack-user-hidden-p users))))) + (slack-select-from-list (alist "Select User: ") + (let ((buf (slack-create-user-profile-buffer team (plist-get selected :id)))) + (slack-buffer-display buf))))) + +(cl-defun slack-user-info-request (user-id team &key after-success) + (cl-labels + ((on-success + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-user-info-request") + (oset team users (cons (plist-get data :user) + (cl-remove-if #'(lambda (user) + (string= (plist-get user :id) user-id)) + (oref team users)))) + (slack-im-open (plist-get data :user)) + (when after-success (funcall after-success))))) + (slack-request + (slack-request-create + slack-user-info-url + team + :params (list (cons "user" user-id)) + :success #'on-success)))) + +(defun slack-user-image-url-24 (user) + (plist-get (slack-user-profile user) :image_24)) + +(defun slack-user-image-url-32 (user) + (plist-get (slack-user-profile user) :image_32)) + +(defun slack-user-image-url-48 (user) + (plist-get (slack-user-profile user) :image_48)) + +(defun slack-user-image-url-72 (user) + (plist-get (slack-user-profile user) :image_72)) + +(defun slack-user-image-url-512 (user) + (plist-get (slack-user-profile user) :image_512)) + +(defun slack-user-image-url (user size) + (cond + ((eq size 24) (slack-user-image-url-24 user)) + ((eq size 32) (slack-user-image-url-32 user)) + ((eq size 48) (slack-user-image-url-48 user)) + ((eq size 72) (slack-user-image-url-72 user)) + ((eq size 512) (slack-user-image-url-512 user)) + (t (slack-user-image-url-32 user)))) + +(defun slack-user-fetch-image (user size team) + (let* ((image-url (slack-user-image-url user size)) + (file-path (and image-url (slack-profile-image-path image-url team)))) + (when file-path + (if (file-exists-p file-path) file-path + (slack-url-copy-file image-url file-path + :success (lambda () + (slack-log (format "Success download Image: %s" + file-path) + team))))) + file-path)) + +(cl-defun slack-user-image (user team &optional (size 32)) + (when user + (let ((image (slack-user-fetch-image user size team))) + (when image + (create-image image nil nil :ascent 80))))) + +(defun slack-user-presence (user) + (plist-get user :presence)) + +(defun slack-request-set-presence (team &optional presence) + (unless presence + (let ((current-presence (slack-user-presence (slack-user--find (oref team self-id) + team)))) + + (setq presence (or (and (string= current-presence "away") "auto") + "away")) + )) + (cl-labels + ((on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-request-set-presence")))) + (slack-request + (slack-request-create + slack-set-presence-url + team + :success #'on-success + :params (list (cons "presence" presence)))))) + +(defun slack-request-dnd-set-snooze (team time) + (cl-labels + ((on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-request-dnd-set-snooze") + (message "setSnooze: %s" data)))) + (let* ((input (slack-parse-time-string time)) + (num-minutes (and time (/ (- (time-to-seconds input) (time-to-seconds)) + 60)))) + (unless num-minutes + (error "Invalid time string %s" time)) + (slack-request + (slack-request-create + slack-dnd-set-snooze-url + team + :success #'on-success + :params (list (cons "num_minutes" (format "%s" num-minutes)))))))) + +(defun slack-request-dnd-end-dnd (team) + (cl-labels + ((on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-request-dnd-end-dnd") + (message "endDnd: %s" data)))) + (slack-request + (slack-request-create + slack-dnd-end-dnd-url + team + :success #'on-success + )))) + +(defun slack-user-update-dnd-status (user dnd-status) + (plist-put user :dnd_status dnd-status)) + +(defun slack-request-dnd-team-info (team &optional after-success) + (cl-labels + ((on-success + (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-request-dnd-team-info") + (let ((users (plist-get data :users))) + (oset team users + (cl-loop for user in (oref team users) + collect (plist-put + user + :dnd_status + (plist-get users + (intern (format ":%s" + (plist-get user :id))))))))) + (when (functionp after-success) + (funcall after-success team)))) + (slack-request + (slack-request-create + slack-dnd-team-info-url + team + :success #'on-success)))) + +(provide 'slack-user) +;;; slack-user.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-user.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-user.elc new file mode 100644 index 000000000000..530af0770d6f --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-user.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-util.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-util.el new file mode 100644 index 000000000000..dd415a941d02 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-util.el @@ -0,0 +1,481 @@ +;;; slack-util.el ---utility functions -*- lexical-binding: t; -*- + +;; Copyright (C) 2015 yuya.minami + +;; Author: yuya.minami <yuya.minami@yuyaminami-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 'timer) +(require 'diary-lib) + +(defcustom slack-profile-image-file-directory temporary-file-directory + "Default directory for slack profile images." + :group 'slack) + +(defcustom slack-image-file-directory temporary-file-directory + "Default directory for slack images." + :group 'slack) + +(defcustom slack-image-max-height 300 + "Max Height of image. nil is unlimited. integer." + :group 'slack) + +(defconst slack-log-levels + '(;; debugging + (trace . 40) (debug . 30) + ;; information + (info . 20) + ;; errors + (warn . 10) (error . 0)) + "Named logging levels.") + +(defcustom slack-log-level 'info + "Used in `slack-message-logger'. +One of 'info, 'debug" + :group 'slack) + +(defcustom slack-log-time-format + "[%Y-%m-%d %H:%M:%S]" + "Time format for log." + :group 'slack) + +(defalias 'slack-if-let* + (if (fboundp 'if-let*) + 'if-let* + 'if-let)) + +(defun slack-seq-to-list (seq) + (if (listp seq) seq (append seq nil))) + +(defun slack-decode (seq) + (cl-loop for e in (slack-seq-to-list seq) + collect (if (stringp e) + (decode-coding-string e 'utf-8) + (if (listp e) + (slack-decode e) + e)))) + +(defun slack-class-have-slot-p (class slot) + (and (symbolp slot) + (let* ((stripped (substring (symbol-name slot) 1)) + (replaced (replace-regexp-in-string "_" "-" + stripped)) + (symbolized (intern replaced))) + (slot-exists-p class symbolized)))) + +(defun slack-collect-slots (class seq) + (let ((plist (slack-seq-to-list seq))) + (cl-loop for p in plist + if (and (slack-class-have-slot-p class p) + (plist-member plist p)) + nconc (let ((value (plist-get plist p))) + (list p (if (stringp value) + (decode-coding-string value 'utf-8) + (if (eq :json-false value) + nil + value))))))) +(defun slack-log-level-to-int (level) + (slack-if-let* ((cell (cl-assoc level slack-log-levels))) + (cdr cell) + 20)) + + +(defun slack-message-logger (message level team) + "Display message using `message'." + (let ((user-level (slack-log-level-to-int slack-log-level)) + (current-level (slack-log-level-to-int level))) + (when (<= current-level user-level) + (message (format "%s [%s] [%s] %s" + (format-time-string slack-log-time-format) + level + (oref team name) + message))))) + +(cl-defun slack-log (msg team &key + (logger #'slack-message-logger) + (level 'debug)) + "LEVEL is one of 'trace, 'debug, 'info, 'warn, 'error" + (let ((log (format "%s [%s] %s - %s" + (format-time-string slack-log-time-format) + level + msg + (oref team name))) + (buf (get-buffer-create (slack-log-buffer-name team)))) + (when (functionp logger) + (funcall logger msg level team)) + (with-current-buffer buf + (setq buffer-read-only nil) + (save-excursion + (goto-char (point-max)) + (insert log) + (insert "\n")) + (setq buffer-read-only t)))) + +(defun company-slack-backend (command &optional arg &rest ignored) + "Completion backend for slack chats. It currently understands +@USER; adding #CHANNEL should be a simple matter of programming." + (interactive (list 'interactive)) + (cl-labels + ((start-from-line-beginning (str) + (let ((prompt-length (length lui-prompt-string))) + (>= 0 (- (current-column) prompt-length (length str))))) + (prefix-type (str) (cond + ((string-prefix-p "@" str) 'user) + ((string-prefix-p "#" str) 'channel) + ((and (string-prefix-p "/" str) + (start-from-line-beginning str)) + 'slash))) + (content (str) (substring str 1 nil))) + (cl-case command + (interactive (company-begin-backend 'company-slack-backend)) + (prefix (when (string= "slack" (car (split-string (format "%s" major-mode) "-"))) + ;; (cl-find major-mode '(slack-mode + ;; slack-edit-message-mode + ;; slack-thread-mode)) + (company-grab-line "\\(\\W\\|^\\)\\(@\\w*\\|#\\w*\\|/\\w*\\)" + 2))) + (candidates (let ((content (content arg))) + (cl-case (prefix-type arg) + (user + (cl-loop for user in (oref slack-current-team users) + if (and (not (eq (plist-get user :deleted) t)) + (string-prefix-p content + (plist-get user :name))) + collect (concat "@" (plist-get user :name)))) + (channel + (cl-loop for team in (oref slack-current-team channels) + if (string-prefix-p content + (oref team name)) + collect (concat "#" (oref team name)))) + (slash + (cl-loop for command in (oref slack-current-team commands) + if (string-prefix-p (concat "/" content) + (oref command name)) + collect (oref command name)) + )))) + (doc-buffer + (cl-case (prefix-type arg) + (slash + (company-doc-buffer + (let* ((team slack-current-team) + (command (slack-command-find arg team))) + (when command + (slack-command-company-doc-string command team)))))))))) + +(defun slack-get-ts () + (get-text-property 0 'ts (thing-at-point 'line))) + +(defun slack-linkfy (text link) + (if (not (slack-string-blankp link)) + (format "<%s|%s>" link text) + text)) + +(defun slack-string-blankp (str) + (if str + (> 1 (length str)) + t)) + +(defun slack-log-buffer-name (team) + (format "*Slack Log - %s*" (slack-team-name team))) + +(defun slack-log-open-buffer () + (interactive) + (let ((team (slack-team-select))) + (funcall slack-buffer-function (get-buffer-create (slack-log-buffer-name team))))) + +(defun slack-event-log-buffer-name (team) + (format "*Slack Event Log - %s*" (slack-team-name team))) + +(defun slack-log-websocket-payload (payload team) + (let* ((bufname (slack-event-log-buffer-name team)) + (buf (get-buffer-create bufname))) + (when buf + (with-current-buffer buf + (setq buffer-read-only nil) + (save-excursion + (goto-char (point-max)) + (insert (format "[%s] %s\n" + (format-time-string "%Y-%m-%d %H:%M:%S") + payload))) + (setq buffer-read-only t))))) + +(defun slack-log-open-websocket-buffer () + (interactive) + (if websocket-debug + (progn + (let* ((team (slack-team-select)) + (websocket (oref team ws-conn))) + (if websocket + (funcall slack-buffer-function + (websocket-get-debug-buffer-create websocket)) + (error "Websocket is not connected")))) + (error "`websocket-debug` is not t"))) + +(defun slack-log-open-event-buffer () + (interactive) + (let* ((team (slack-team-select)) + (bufname (slack-event-log-buffer-name team)) + (buf (get-buffer bufname))) + (if buf + (funcall slack-buffer-function buf) + (error "No Event Log Buffer")))) + +(defun slack-profile-image-path (image-url team) + (expand-file-name + (concat (md5 (concat (slack-team-name team) "-" image-url)) + "." + (file-name-extension image-url)) + slack-profile-image-file-directory)) + +(cl-defun slack-image--create (path &key (width nil) (height nil) (max-height nil) (max-width nil)) + (let* ((imagemagick-available-p (image-type-available-p 'imagemagick)) + (image (apply #'create-image (append (list path (and imagemagick-available-p 'imagemagick) nil) + (if height (list :height height)) + (if width (list :width width)) + (if max-height + (list :max-height max-height)) + (if max-width + (list :max-width max-width)))))) + (if (and (display-graphic-p) imagemagick-available-p) + (slack-image-shrink image max-height) + image))) + +(defun slack-image-exists-p (image-spec) + (file-exists-p (slack-image-path (car image-spec)))) + +(defun slack-image-string (spec &optional pad no-token) + "SPEC: (list URL WIDTH HEIGHT MAX-HEIGHT MAX-WIDTH)" + (if spec + (slack-if-let* ((path (slack-image-path (car spec)))) + (if (file-exists-p path) + (slack-mapconcat-images + (slack-image-slice + (slack-image--create path + :width (cadr spec) + :height (caddr spec) + :max-height (cadddr spec) + :max-width (cadr (cdddr spec)))) + pad) + (propertize "[Image]" + 'slack-image-spec spec + 'no-token no-token)) + "") + "")) + +(defun slack-image-path (image-url) + (and image-url + (expand-file-name + (concat (md5 image-url) + "." + (file-name-extension image-url)) + slack-image-file-directory))) + +(defun slack-image-slice (image) + (when image + (let* ((line-height 50.0) + (height (or (plist-get (cdr image) :height) + (cdr (image-size image t)))) + (line-count (/ height line-height)) + (line (/ 1.0 line-count))) + (if (< line-height height) + (cl-loop for i from 0 to (- line-count 1) + collect (list (list 'slice 0 (* line i) 1.0 line) + image)) + (list image))))) + +(defun slack-image-shrink (image &optional max-height) + (unless (image-type-available-p 'imagemagick) + (error "Need Imagemagick")) + (if max-height + (let* ((data (plist-get (cdr image) :data)) + (file (plist-get (cdr image) :file)) + (size (image-size image t)) + (height (cdr size)) + (width (car size)) + (h (min height max-height)) + (w (if (< max-height height) + (ceiling + (* (/ (float max-height) height) + width)) + width))) + (create-image (or file data) 'imagemagick data :height h :width w)) + image)) + +(defun slack-mapconcat-images (images &optional pad) + (when images + (cl-labels + ((sort-images (images) + (let ((compare (if (or (and (eq system-type 'darwin) + (< emacs-major-version 26)) + (< emacs-major-version 25)) + #'> + #'<))) + (cl-sort images compare :key + #'(lambda (image) (caddr (car image)))))) + (propertize-image (image) + (propertize "image" + 'display image + 'face 'slack-profile-image-face))) + (mapconcat #'propertize-image + (sort-images images) + (format "\n%s" (or pad "")))))) + +(cl-defun slack-url-copy-file (url newname &key (success nil) (error nil) (sync nil) (token nil)) + (if (executable-find "curl") + (slack-curl-downloader url newname + :success success + :error error + :token token) + (cl-labels + ((on-success (&key data &allow-other-keys) + (when (functionp success) (funcall success))) + (on-error (&key error-thrown symbol-status response data) + (message "Error Fetching Image: %s %s %s, url: %s" + (request-response-status-code response) + error-thrown symbol-status url) + (if (file-exists-p newname) + (delete-file newname)) + (case (request-response-status-code response) + (403 nil) + (404 nil) + (t (when (functionp error) + (funcall error + (request-response-status-code response) + error-thrown + symbol-status + url))))) + (parser () (mm-write-region (point-min) (point-max) + newname nil nil nil 'binary t))) + (let* ((url-obj (url-generic-parse-url url)) + (need-token-p (and url-obj + (string-match-p "slack" + (url-host url-obj)))) + (use-https-p (and url-obj + (string= "https" (url-type url-obj))))) + (request + url + :success #'on-success + :error #'on-error + :parser #'parser + :sync sync + :headers (if (and token use-https-p need-token-p) + (list (cons "Authorization" (format "Bearer %s" token))))))))) + +(defun slack-render-image (image team) + (let ((buf (get-buffer-create + (format "*Slack - %s Image*" (slack-team-name team))))) + (with-current-buffer buf + (setq buffer-read-only nil) + (erase-buffer) + (if image + (insert (slack-mapconcat-images (slack-image-slice image))) + (insert "Loading Image...")) + (setq buffer-read-only t) + (goto-char (point-min))) + + buf)) + +(defun slack-parse-time-string (time) + "TIME should be one of: +- a string giving todayโs time like \"11:23pm\" + (the acceptable formats are HHMM, H:MM, HH:MM, HHam, HHAM, + HHpm, HHPM, HH:MMam, HH:MMAM, HH:MMpm, or HH:MMPM; + a period โ.โ can be used instead of a colon โ:โ to separate + the hour and minute parts); +- a string giving specific date and time like \"1991/03/23 03:00\"; +- a string giving a relative time like \"90\" or \"2 hours 35 minutes\" + (the acceptable forms are a number of seconds without units + or some combination of values using units in โtimer-duration-wordsโ); +- a number of seconds from now;" + (if (numberp time) + (setq time (timer-relative-time nil time))) + (if (stringp time) + (let ((secs (timer-duration time))) + (if secs + (setq time (timer-relative-time nil secs))))) + (if (stringp time) + (progn + (let* ((date-and-time (split-string time " ")) + (date (and (eq (length date-and-time) 2) (split-string (car date-and-time) "/"))) + (time-str (or (and (eq (length date-and-time) 2) (cadr date-and-time)) + (car date-and-time))) + (hhmm (diary-entry-time time-str)) + (now (or (and date (decode-time + (encode-time 0 0 0 + (string-to-number (nth 2 date)) + (string-to-number (nth 1 date)) + (string-to-number (nth 0 date)) + ))) + (decode-time)))) + (if (>= hhmm 0) + (setq time + (encode-time 0 (% hhmm 100) (/ hhmm 100) (nth 3 now) + (nth 4 now) (nth 5 now) (nth 8 now))))))) + time) + +(defmacro slack-merge-list (old-list new-list) + `(cl-loop for n in ,new-list + do (let ((o (cl-find-if #'(lambda (e) (slack-equalp n e)) + ,old-list))) + (if o (slack-merge o n) + (push n ,old-list))))) + +(cl-defun slack-curl-downloader (url name &key (success nil) (error nil) (token nil)) + (cl-labels + ((sentinel (proc event) + (cond + ((string-equal "finished\n" event) + (when (functionp success) (funcall success))) + (t + (let ((status (process-status proc)) + (output (with-current-buffer (process-buffer proc) + (buffer-substring-no-properties (point-min) + (point-max))))) + (if (functionp error) + (funcall error status output url name) + (message "Download Failed. STATUS: %s, EVENT: %s, URL: %s, NAME: %s, OUTPUT: %s" + status + event + url + name + output)) + (if (file-exists-p name) + (delete-file name)) + (delete-process proc)))))) + (let* ((url-obj (url-generic-parse-url url)) + (need-token-p (and url-obj + (string-match-p "slack" (url-host url-obj)))) + (header (or (and token + need-token-p + (string-prefix-p "https" url) + (format "-H 'Authorization: Bearer %s'" token)) + "")) + (output (format "--output '%s'" name)) + (command (format "curl --silent --show-error --fail --location %s %s '%s'" output header url)) + (proc (start-process-shell-command "slack-curl-downloader" + "slack-curl-downloader" + command))) + (set-process-sentinel proc #'sentinel)))) + +(provide 'slack-util) +;;; slack-util.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-util.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-util.elc new file mode 100644 index 000000000000..ee44e25c6994 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-util.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-websocket.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-websocket.el new file mode 100644 index 000000000000..b81d72b268b9 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-websocket.el @@ -0,0 +1,1073 @@ +;;; slack-websocket.el --- slack websocket 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 'websocket) +(require 'slack-util) +(require 'slack-request) +(require 'slack-message) +(require 'slack-team) +(require 'slack-reply) +(require 'slack-file) +(require 'slack-dialog) +(defconst slack-api-test-url "https://slack.com/api/api.test") + +(defclass slack-typing () + ((room :initarg :room :initform nil) + (limit :initarg :limit :initform nil) + (users :initarg :users :initform nil))) + +(defclass slack-typing-user () + ((limit :initarg :limit :initform nil) + (user-name :initarg :user-name :initform nil))) + +(defun slack-ws-set-connect-timeout-timer (team) + (slack-ws-cancel-connect-timeout-timer team) + (cl-labels + ((on-timeout () + (slack-log (format "websocket open timeout") + team) + (slack-ws-close team) + (slack-ws-set-reconnect-timer team))) + (oset team websocket-connect-timeout-timer + (run-at-time (oref team websocket-connect-timeout-sec) + nil + #'on-timeout)))) + +(defun slack-ws-cancel-connect-timeout-timer (team) + (when (timerp (oref team websocket-connect-timeout-timer)) + (cancel-timer (oref team websocket-connect-timeout-timer)) + (oset team websocket-connect-timeout-timer nil))) + +(cl-defun slack-ws-open (team &key (on-open nil) (ws-url nil)) + (slack-if-let* ((conn (oref team ws-conn)) + (state (websocket-ready-state conn))) + (cond ((websocket-openp conn) + (slack-log "Websocket is Already Open" team)) + ((eq state 'connecting) + (slack-log "Websocket is connecting" team)) + ((eq state 'closed) + (slack-log "Websocket is closed" team))) + + (progn + (slack-ws-set-connect-timeout-timer team) + (cl-labels + ((on-message (websocket frame) + (slack-ws-on-message websocket frame team)) + (handle-on-open (_websocket) + (oset team reconnect-count 0) + (oset team connected t) + (slack-log "WebSocket on-open" + team :level 'debug) + (when (functionp on-open) + (funcall on-open))) + (on-close (websocket) + (oset team ws-conn nil) + (oset team connected nil) + (slack-log (format "Websocket on-close: STATE: %s" + (websocket-ready-state websocket)) + team :level 'debug) + (unwind-protect + (progn + (unless (oref team inhibit-reconnection) + (slack-ws-set-reconnect-timer team))) + (oset team inhibit-reconnection nil))) + (on-error (_websocket type err) + (slack-log (format "Error on `websocket-open'. TYPE: %s, ERR: %s" + type err) + team + :level 'error))) + (oset team ws-conn + (condition-case error-var + (websocket-open (or ws-url (oref team ws-url)) + :on-message #'on-message + :on-open #'handle-on-open + :on-close #'on-close + :on-error #'on-error + :nowait (oref team websocket-nowait)) + (error + (slack-log (format "An Error occured while opening websocket connection: %s" + error-var) + team + :level 'error) + ;; (slack-ws-close team) + ;; (slack-ws-set-reconnect-timer team) + nil))))))) + +(cl-defun slack-ws-close (&optional team (close-reconnection nil)) + (interactive) + (unless team + (setq team slack-teams)) + (let ((called-interactively (called-interactively-p 'any))) + (cl-labels + ((close (team) + (slack-ws-cancel-ping-timer team) + (slack-ws-cancel-ping-check-timers team) + (when (or close-reconnection + called-interactively) + (slack-ws-cancel-reconnect-timer team) + (oset team inhibit-reconnection t)) + (with-slots (connected ws-conn last-pong) team + (when ws-conn + (websocket-close ws-conn) + (slack-log "Slack Websocket Closed" team))))) + (if (listp team) + (progn + (mapc #'close team) + (slack-request-worker-quit)) + (close team) + (slack-request-worker-remove-request team) + ) + ))) + +(defun slack-ws-send (payload team) + (with-slots (waiting-send ws-conn) team + (push payload waiting-send) + (cl-labels + ((reconnect () + (slack-ws-close team) + (slack-ws-set-reconnect-timer team))) + (if (websocket-openp ws-conn) + (condition-case err + (websocket-send-text ws-conn (json-encode payload)) + (error + (slack-log (format "Error in `slack-ws-send`: %s" err) + team :level 'debug) + (reconnect))) + (reconnect))))) + +(defun slack-ws-resend (team) + (with-slots (waiting-send) team + (let ((candidate waiting-send)) + (setq waiting-send nil) + (cl-loop for msg in candidate + do (slack-ws-send msg team))))) + +;; (:type error :error (:msg Socket URL has expired :code 1)) +(defun slack-ws-handle-error (payload team) + (let* ((err (plist-get payload :error)) + (code (plist-get err :code))) + (cond + ((eq 1 code) + (slack-ws-close team) + (slack-ws-set-reconnect-timer team)) + (t (slack-log (format "Unknown Error: %s, MSG: %s" + code (plist-get err :msg)) + team))))) + +(defun slack-ws-on-message (_websocket frame team) + ;; (message "%s" (slack-request-parse-payload + ;; (websocket-frame-payload frame))) + (when (websocket-frame-completep frame) + (let* ((payload (slack-request-parse-payload + (websocket-frame-payload frame))) + (decoded-payload (and payload (slack-decode payload))) + (type (and decoded-payload + (plist-get decoded-payload :type)))) + ;; (message "%s" decoded-payload) + (when (slack-team-event-log-enabledp team) + (slack-log-websocket-payload decoded-payload team)) + (when decoded-payload + (cond + ((string= type "error") + (slack-ws-handle-error decoded-payload team)) + ((string= type "pong") + (slack-ws-handle-pong decoded-payload team)) + ((string= type "hello") + (slack-ws-cancel-connect-timeout-timer team) + (slack-ws-cancel-reconnect-timer team) + (slack-cancel-notify-adandon-reconnect) + (slack-ws-set-ping-timer team) + (slack-ws-resend team) + (slack-log "Slack Websocket Is Ready!" team :level 'info)) + ((plist-get decoded-payload :reply_to) + (slack-ws-handle-reply decoded-payload team)) + ((string= type "message") + (slack-ws-handle-message decoded-payload team)) + ((string= type "reaction_added") + (slack-ws-handle-reaction-added decoded-payload team)) + ((string= type "reaction_removed") + (slack-ws-handle-reaction-removed decoded-payload team)) + ((string= type "channel_created") + (slack-ws-handle-channel-created decoded-payload team)) + ((or (string= type "channel_archive") + (string= type "group_archive")) + (slack-ws-handle-room-archive decoded-payload team)) + ((or (string= type "channel_unarchive") + (string= type "group_unarchive")) + (slack-ws-handle-room-unarchive decoded-payload team)) + ((string= type "channel_deleted") + (slack-ws-handle-channel-deleted decoded-payload team)) + ((or (string= type "channel_rename") + (string= type "group_rename")) + (slack-ws-handle-room-rename decoded-payload team)) + ((or (string= type "channel_left") + (string= type "group_left")) + (slack-ws-handle-room-left decoded-payload team)) + ((string= type "channel_joined") + (slack-ws-handle-channel-joined decoded-payload team)) + ((string= type "group_joined") + (slack-ws-handle-group-joined decoded-payload team)) + ((string= type "presence_change") + (slack-ws-handle-presence-change decoded-payload team)) + ((or (string= type "bot_added") + (string= type "bot_changed")) + (slack-ws-handle-bot decoded-payload team)) + ((string= type "file_created") + (slack-ws-handle-file-created decoded-payload team)) + ((or (string= type "file_deleted") + (string= type "file_unshared")) + (slack-ws-handle-file-deleted decoded-payload team)) + ((or (string= type "im_marked") + (string= type "channel_marked") + (string= type "group_marked")) + (slack-ws-handle-room-marked decoded-payload team)) + ((string= type "thread_marked") + (slack-ws-handle-thread-marked decoded-payload team)) + ((string= type "thread_subscribed") + (slack-ws-handle-thread-subscribed decoded-payload team)) + ((string= type "im_open") + (slack-ws-handle-im-open decoded-payload team)) + ((string= type "im_close") + (slack-ws-handle-im-close decoded-payload team)) + ((string= type "team_join") + (slack-ws-handle-team-join decoded-payload team)) + ((string= type "user_typing") + (slack-ws-handle-user-typing decoded-payload team)) + ((string= type "user_change") + (slack-ws-handle-user-change decoded-payload team)) + ((string= type "member_joined_channel") + (slack-ws-handle-member-joined-channel decoded-payload team)) + ((string= type "member_left_channel") + (slack-ws-handle-member-left_channel decoded-payload team)) + ((or (string= type "dnd_updated") + (string= type "dnd_updated_user")) + (slack-ws-handle-dnd-updated decoded-payload team)) + ((string= type "star_added") + (slack-ws-handle-star-added decoded-payload team)) + ((string= type "star_removed") + (slack-ws-handle-star-removed decoded-payload team)) + ((string= type "reconnect_url") + (slack-ws-handle-reconnect-url decoded-payload team)) + ((string= type "app_conversation_invite_request") + (slack-ws-handle-app-conversation-invite-request decoded-payload team)) + ((string= type "commands_changed") + (slack-ws-handle-commands-changed decoded-payload team)) + ((string= type "dialog_opened") + (slack-ws-handle-dialog-opened decoded-payload team)) + ))))) + +(defun slack-ws-handle-reconnect-url (payload team) + (oset team reconnect-url (plist-get payload :url))) + +(defun slack-user-typing (team) + (with-slots (typing typing-timer) team + (with-slots (limit users room) typing + (let ((current (float-time))) + (if (and typing-timer (timerp typing-timer) + (< limit current)) + (progn + (cancel-timer typing-timer) + (setq typing-timer nil) + (setq typing nil)) + (if (slack-buffer-show-typing-p + (get-buffer (slack-room-buffer-name room team))) + (let ((team-name (slack-team-name team)) + (room-name (slack-room-name room team)) + (visible-users (cl-remove-if + #'(lambda (u) (< (oref u limit) current)) + users))) + (slack-log + (format "Slack [%s - %s] %s is typing..." + team-name room-name + (mapconcat #'(lambda (u) (oref u user-name)) + visible-users + ", ")) + team + :level 'info)))))))) + +(defun slack-ws-handle-user-typing (payload team) + (let* ((user (slack-user-name (plist-get payload :user) team)) + (room (slack-room-find (plist-get payload :channel) team))) + (if (and user room + (slack-buffer-show-typing-p (get-buffer (slack-room-buffer-name room team)))) + (let ((limit (+ 3 (float-time)))) + (with-slots (typing typing-timer) team + (if (and typing (equal room (oref typing room))) + (with-slots ((typing-limit limit) + (typing-room room) users) typing + (setq typing-limit limit) + (let ((typing-user (make-instance 'slack-typing-user + :limit limit + :user-name user))) + (setq users + (cons typing-user + (cl-remove-if #'(lambda (u) + (string= (oref u user-name) + user)) + users)))))) + (unless typing + (let ((new-typing (make-instance 'slack-typing + :room room :limit limit)) + (typing-user (make-instance 'slack-typing-user + :limit limit :user-name user))) + (oset new-typing users (list typing-user)) + (setq typing new-typing)) + (setq typing-timer + (run-with-timer t 1 #'slack-user-typing team)))))))) + +(defun slack-ws-handle-team-join (payload team) + (let ((user (slack-decode (plist-get payload :user)))) + (slack-user-info-request + (plist-get user :id) team + :after-success #'(lambda () + (slack-log (format "User %s Joind Team: %s" + (plist-get (slack-user--find (plist-get user :id) + team) + :name) + (slack-team-name team)) + team + :level 'info))))) + +(defun slack-ws-handle-im-open (payload team) + (cl-labels + ((notify + (im) + (slack-room-history-request + im team + :after-success #'(lambda (&rest _ignore) + (slack-log (format "Direct Message Channel with %s is Open" + (slack-user-name (oref im user) team)) + team :level 'info)) + :async t))) + (let ((exist (slack-room-find (plist-get payload :channel) team))) + (if exist + (progn + (oset exist is-open t) + (notify exist)) + (with-slots (ims) team + (let ((im (slack-room-create + (list :id (plist-get payload :channel) + :user (plist-get payload :user)) + team 'slack-im))) + (setq ims (cons im ims)) + (notify im))))))) + +(defun slack-ws-handle-im-close (payload team) + (let ((im (slack-room-find (plist-get payload :channel) team))) + (when im + (oset im is-open nil) + (slack-log (format "Direct Message Channel with %s is Closed" + (slack-user-name (oref im user) team)) + team :level 'info)))) + +(defun slack-ws-handle-message (payload team) + (let ((subtype (plist-get payload :subtype))) + (cond + ((and subtype (string= subtype "message_changed")) + (slack-ws-change-message payload team)) + ((and subtype (string= subtype "message_deleted")) + (slack-ws-delete-message payload team)) + ((and subtype (string= subtype "message_replied")) + (slack-thread-update-state payload team)) + (t + (slack-ws-update-message payload team))))) + +(defun slack-ws-change-message (payload team) + (slack-if-let* ((room-id (plist-get payload :channel)) + (room (slack-room-find room-id team)) + (message-payload (plist-get payload :message)) + (ts (plist-get message-payload :ts)) + (base (slack-room-find-message room ts)) + (new-message (slack-message-create message-payload + team + :room room))) + (slack-message-update base team t + (not (slack-message-changed--copy base new-message))))) + + +(defun slack-ws-delete-message (payload team) + (slack-if-let* ((room-id (plist-get payload :channel)) + (room (slack-room-find room-id team)) + (ts (plist-get payload :deleted_ts)) + (message (slack-room-find-message room ts))) + (slack-message-deleted message room team))) + +(defun slack-ws-update-message (payload team) + (let ((subtype (plist-get payload :subtype))) + (if (string= subtype "bot_message") + (slack-ws-update-bot-message payload team) + (slack-message-update (slack-message-create payload team) + team)))) + +(defun slack-ws-update-bot-message (payload team) + (let* ((bot-id (plist-get payload :bot_id)) + (username (plist-get payload :username)) + (user (plist-get payload :user)) + (bot (or (slack-find-bot bot-id team) + (slack-find-bot-by-name username team) + (slack-user--find user team))) + (message (slack-message-create payload team))) + (if bot + (slack-message-update message team) + (slack-bot-info-request bot-id + team + #'(lambda (team) + (slack-message-update message team)))))) + +(defun slack-ws-remove-from-resend-queue (payload team) + (with-slots (waiting-send) team + (slack-log (format "waiting-send: %s" (length waiting-send)) + team :level 'trace) + (setq waiting-send + (cl-remove-if #'(lambda (e) (eq (plist-get e :id) + (plist-get payload :reply_to))) + waiting-send)) + (slack-log (format "waiting-send: %s" (length waiting-send)) + team :level 'trace))) + +(defun slack-ws-handle-reply (payload team) + (let ((ok (plist-get payload :ok))) + (if (eq ok :json-false) + (let ((err (plist-get payload :error))) + (slack-log (format "Error code: %s msg: %s" + (plist-get err :code) + (plist-get err :msg)) + team)) + (let ((message-id (plist-get payload :reply_to))) + (when (integerp message-id) + (slack-message-handle-reply + (slack-message-create payload team) + team) + (slack-ws-remove-from-resend-queue payload team)))))) + +(defun slack-ws-handle-reaction-added-to-file (file-id reaction team) + (let* ((file (slack-file-find file-id team)) + (item-type "file")) + (cl-labels + ((update (&rest _args) + (slack-with-file file-id team + (slack-message-append-reaction file reaction) + (slack-message-update file team) + (cl-loop for channel in (slack-file-channel-ids file) + do (slack-if-let* + ((channel (slack-room-find channel team)) + (message (slack-room-find-file-share-message + channel (oref file id)))) + + (progn + (slack-message-append-reaction message + reaction + item-type + file-id) + (slack-message-update message + team t t))))))) + (if file (update) + (slack-file-request-info file-id 1 team #'update))))) + +(defun slack-ws-handle-reaction-added (payload team) + (let* ((item (plist-get payload :item)) + (item-type (plist-get item :type)) + (reaction (make-instance 'slack-reaction + :name (plist-get payload :reaction) + :count 1 + :users (list (plist-get payload :user))))) + (cl-labels + ((update-message (message) + (slack-message-append-reaction message reaction item-type) + (slack-message-update message team t t))) + (cond + ((string= item-type "file") + (slack-ws-handle-reaction-added-to-file (plist-get item :file) + reaction + team)) + ((string= item-type "message") + (slack-if-let* ((room (slack-room-find (plist-get item :channel) team)) + (message (slack-room-find-message room (plist-get item :ts)))) + (progn + (update-message message) + (slack-reaction-notify payload team room)))))))) + +(defun slack-ws-handle-reaction-removed-from-file (file-id reaction team) + (let* ((file (slack-file-find file-id team)) + (item-type "file")) + (cl-labels + ((update (&rest _args) + (slack-with-file file-id team + (slack-message-pop-reaction file reaction) + (slack-message-update file team) + (cl-loop for channel in (slack-file-channel-ids file) + do (slack-if-let* + ((channel (slack-room-find channel team)) + (message (slack-room-find-file-share-message + channel (oref file id)))) + (progn + (slack-message-pop-reaction message + reaction + item-type + file-id) + (slack-message-update message team t t))))))) + (if file (update) + (slack-file-request-info file-id 1 team #'update))))) + +(defun slack-ws-handle-reaction-removed (payload team) + (let* ((item (plist-get payload :item)) + (item-type (plist-get item :type)) + (reaction (make-instance 'slack-reaction + :name (plist-get payload :reaction) + :count 1 + :users (list (plist-get payload :user))))) + (cl-labels + ((update-message (message) + (slack-message-pop-reaction message reaction item-type) + (slack-message-update message team t t))) + (cond + ((string= item-type "file") + (slack-ws-handle-reaction-removed-from-file (plist-get item :file) + reaction + team)) + ((string= item-type "message") + (slack-if-let* ((room (slack-room-find (plist-get item :channel) team)) + (message (slack-room-find-message room (plist-get item :ts)))) + (progn + (update-message message) + (slack-reaction-notify payload team room)))))))) + +(defun slack-ws-handle-channel-created (payload team) + (let ((channel (slack-room-create (plist-get payload :channel) + team 'slack-channel))) + (push channel (oref team channels)) + (slack-room-info-request channel team) + (slack-log (format "Created channel %s" + (slack-room-display-name channel team)) + team :level 'info))) + +(defun slack-ws-handle-room-archive (payload team) + (let* ((id (plist-get payload :channel)) + (room (slack-room-find id team))) + (oset room is-archived t) + (slack-log (format "Channel: %s is archived" + (slack-room-display-name room team)) + team :level 'info))) + +(defun slack-ws-handle-room-unarchive (payload team) + (let* ((id (plist-get payload :channel)) + (room (slack-room-find id team))) + (oset room is-archived nil) + (slack-log (format "Channel: %s is unarchived" + (slack-room-display-name room team)) + team :level 'info))) + +(defun slack-ws-handle-channel-deleted (payload team) + (let ((id (plist-get payload :channel))) + (slack-room-deleted id team))) + +(defun slack-ws-handle-room-rename (payload team) + (let* ((c (plist-get payload :channel)) + (room (slack-room-find (plist-get c :id) team)) + (old-name (slack-room-name room team)) + (new-name (plist-get c :name))) + (oset room name new-name) + (slack-log (format "Renamed channel from %s to %s" + old-name + new-name) + team :level 'info))) +(defun slack-ws-handle-group-joined (payload team) + (let ((group (slack-room-create (plist-get payload :channel) team 'slack-group))) + (push group (oref team groups)) + (slack-room-info-request group team) + (slack-log (format "Joined group %s" + (slack-room-display-name group team)) + team :level 'info))) + +(defun slack-ws-handle-channel-joined (payload team) + (let ((channel (slack-room-find (plist-get (plist-get payload :channel) :id) team))) + (slack-room-info-request channel team) + (slack-log (format "Joined channel %s" + (slack-room-display-name channel team)) + team :level 'info))) + +(defun slack-ws-handle-presence-change (payload team) + (let* ((id (plist-get payload :user)) + (user (slack-user--find id team)) + (presence (plist-get payload :presence))) + (plist-put user :presence presence))) + +(defun slack-ws-handle-bot (payload team) + (let ((bot (plist-get payload :bot))) + (with-slots (bots) team + (push bot bots)))) + +(defun slack-ws-handle-file-created (payload team) + (slack-if-let* ((file-id (plist-get (plist-get payload :file) :id)) + (room (slack-file-room-obj team)) + (buffer (slack-buffer-find 'slack-file-list-buffer + room + team))) + (slack-file-request-info file-id 1 team + #'(lambda (file _team) + (slack-buffer-update buffer file))))) + +(defun slack-ws-handle-file-deleted (payload team) + (let ((file-id (plist-get payload :file_id)) + (room (slack-file-room-obj team))) + (with-slots (messages) room + (setq messages (cl-remove-if #'(lambda (f) + (string= file-id (oref f id))) + messages))))) + +(defun slack-ws-cancel-ping-timer (team) + (with-slots (ping-timer) team + (if (timerp ping-timer) + (cancel-timer ping-timer)) + (setq ping-timer nil))) + +(defun slack-ws-set-ping-timer (team) + (slack-ws-cancel-ping-timer team) + (cl-labels ((ping () + (slack-ws-ping team))) + (oset team ping-timer (run-at-time 10 nil #'ping)))) + +(defun slack-ws-current-time-str () + (number-to-string (time-to-seconds (current-time)))) + +(defun slack-ws-ping (team) + (slack-message-inc-id team) + (with-slots (message-id) team + (let* ((time (slack-ws-current-time-str)) + (m (list :id message-id + :type "ping" + :time time))) + (slack-ws-set-check-ping-timer team time) + (slack-ws-send m team) + (slack-log (format "Send PING: %s" time) + team :level 'trace)))) + +(defun slack-ws-set-check-ping-timer (team time) + (puthash time (run-at-time (oref team check-ping-timeout-sec) + nil #'slack-ws-ping-timeout team) + (oref team ping-check-timers))) + + +(defun slack-ws-ping-timeout (team) + (slack-log "Slack Websocket PING Timeout." team :level 'warn) + (slack-ws-close team) + (slack-ws-set-reconnect-timer team)) + +(defun slack-ws-cancel-ping-check-timers (team) + (maphash #'(lambda (key value) + (if (timerp value) + (cancel-timer value))) + (oref team ping-check-timers)) + (slack-team-init-ping-check-timers team)) + +(defvar slack-disconnected-timer nil) +(defun slack-notify-abandon-reconnect (team) + (unless slack-disconnected-timer + (setq slack-disconnected-timer + (run-with-idle-timer 5 t + #'(lambda () + (slack-log + "Reconnect Count Exceeded. Manually invoke `slack-start'." + team :level 'error)))))) + +(defun slack-cancel-notify-adandon-reconnect () + (if (and slack-disconnected-timer + (timerp slack-disconnected-timer)) + (progn + (cancel-timer slack-disconnected-timer) + (setq slack-disconnected-timer nil)))) + +(defun slack-request-api-test (team &optional after-success) + (cl-labels + ((on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-request-api-test") + (if after-success + (funcall after-success))))) + (slack-request + (slack-request-create + slack-api-test-url + team + :type "POST" + :success #'on-success)))) + +(defun slack-on-authorize-for-reconnect (data team) + (let ((team-data (plist-get data :team)) + (self-data (plist-get data :self))) + (oset team ws-url (plist-get data :url)) + (oset team domain (plist-get team-data :domain)) + (oset team id (plist-get team-data :id)) + (oset team name (plist-get team-data :name)) + (oset team self self-data) + (oset team self-id (plist-get self-data :id)) + (oset team self-name (plist-get self-data :name)) + (cl-labels + ((on-open () + (slack-channel-list-update team) + (slack-group-list-update team) + (slack-im-list-update team) + (slack-bot-list-update team) + (cl-loop for buffer in (oref team slack-message-buffer) + do (slack-if-let* + ((live-p (buffer-live-p buffer)) + (slack-buffer (with-current-buffer buffer + (and (bound-and-true-p + slack-current-buffer) + slack-current-buffer)))) + (slack-buffer-load-missing-messages + slack-buffer))) + (slack-team-kill-buffers + team :except '(slack-message-buffer + slack-message-edit-buffer + slack-message-share-buffer + slack-room-message-compose-buffer)))) + (slack-ws-open team :on-open #'on-open)))) + +(defun slack-authorize-for-reconnect (team) + (cl-labels + ((on-error (&key error-thrown symbol-status &allow-other-keys) + (slack-log (format "Slack Reconnect Failed: %s, %s" + error-thrown + symbol-status) + team) + (slack-ws-set-reconnect-timer team)) + (on-success (data) + (slack-on-authorize-for-reconnect data team))) + (slack-authorize team #'on-error #'on-success))) + +(defun slack-ws-reconnect (team &optional force) + "Reconnect if `reconnect-count' is not exceed `reconnect-count-max'. +if FORCE is t, ignore `reconnect-count-max'. +TEAM is one of `slack-teams'" + (cl-labels ((abort (team) + (slack-notify-abandon-reconnect team) + (slack-ws-close team t)) + (use-reconnect-url () + (slack-log "Reconnect with reconnect-url" team) + (slack-ws-open team + :ws-url (oref team reconnect-url))) + (do-reconnect (team) + (cl-incf (oref team reconnect-count)) + (slack-ws-close team) + (if (< 0 (length (oref team reconnect-url))) + (slack-request-api-test team + #'use-reconnect-url) + (slack-authorize-for-reconnect team)))) + (with-slots + (reconnect-count (reconnect-max reconnect-count-max)) team + (if (and (not force) reconnect-max (< reconnect-max reconnect-count)) + (abort team) + (do-reconnect team) + (slack-log (format "Slack Websocket Try To Reconnect %s/%s" + reconnect-count + reconnect-max) + team + :level 'warn + ))))) + +(defun slack-ws-set-reconnect-timer (team) + (slack-ws-cancel-reconnect-timer team) + (cl-labels + ((on-timeout () + (slack-ws-reconnect team))) + (oset team reconnect-timer + (run-at-time (oref team reconnect-after-sec) + nil + #'on-timeout)))) + +(defun slack-ws-cancel-reconnect-timer (team) + (with-slots (reconnect-timer) team + (if (timerp reconnect-timer) + (cancel-timer reconnect-timer)) + (setq reconnect-timer nil))) + +(defun slack-ws-handle-pong (payload team) + (slack-ws-remove-from-resend-queue payload team) + (let* ((key (plist-get payload :time)) + (timer (gethash key (oref team ping-check-timers)))) + (slack-log (format "Receive PONG: %s" key) + team :level 'trace) + (slack-ws-set-ping-timer team) + (when timer + (cancel-timer timer) + (remhash key (oref team ping-check-timers)) + (slack-log (format "Remove PING Check Timer: %s" key) + team :level 'trace)))) + +(defun slack-ws-handle-room-marked (payload team) + (slack-if-let* ((channel (plist-get payload :channel)) + (room (slack-room-find channel team)) + (ts (plist-get payload :ts)) + (unread-count-display (plist-get payload :unread_count_display))) + (progn + (oset room unread-count-display unread-count-display) + (oset room last-read ts) + (slack-update-modeline)))) + +(defun slack-ws-handle-thread-marked (payload team) + (let* ((subscription (plist-get payload :subscription)) + (thread-ts (plist-get subscription :thread_ts)) + (channel (plist-get subscription :channel)) + (room (slack-room-find channel team)) + (parent (and room (slack-room-find-message room thread-ts)))) + (when (and parent (oref parent thread)) + (slack-thread-marked (oref parent thread) subscription)))) + +(defun slack-ws-handle-thread-subscribed (payload team) + (let* ((thread-data (plist-get payload :subscription)) + (room (slack-room-find (plist-get thread-data :channel) team)) + (message (and (slack-room-find-message room (plist-get thread-data :thread_ts)))) + (thread (and message (oref message thread)))) + (when thread + (slack-thread-marked thread thread-data)))) + +(defun slack-ws-handle-user-change (payload team) + (let* ((user (plist-get payload :user)) + (id (plist-get user :id))) + (with-slots (users) team + (setq users + (cons user + (cl-remove-if #'(lambda (u) + (string= id (plist-get u :id))) + users)))))) + +(defun slack-ws-handle-member-joined-channel (payload team) + (slack-if-let* ((user (plist-get payload :user)) + (channel (slack-room-find (plist-get payload :channel) team))) + (progn + (cl-pushnew user (oref channel members) + :test #'string=) + (slack-log (format "%s joined %s" + (slack-user-name user team) + (slack-room-name channel team)) + team + :level 'info)))) + +(defun slack-ws-handle-member-left_channel (payload team) + (slack-if-let* ((user (plist-get payload :user)) + (channel (slack-room-find (plist-get payload :channel) team))) + (progn + (oset channel members + (cl-remove-if #'(lambda (e) (string= e user)) + (oref channel members))) + (slack-log (format "%s left %s" + (slack-user-name user team) + (slack-room-name channel team)) + team + :level 'info)))) + +(defun slack-ws-handle-dnd-updated (payload team) + (let* ((user (slack-user--find (plist-get payload :user) team)) + (updated (slack-user-update-dnd-status user (plist-get payload :dnd_status)))) + (oset team users + (cons updated (cl-remove-if #'(lambda (user) (string= (plist-get user :id) + (plist-get updated :id))) + (oref team users)))))) + +;; [star_added event | Slack](https://api.slack.com/events/star_added) +(defun slack-ws-handle-star-added-to-file (file-id team) + (let ((file (slack-file-find file-id team))) + (cl-labels + ((update (&rest _args) + (slack-with-file file-id team + (slack-message-star-added file) + (slack-message-update file team)))) + (if file (update) + (slack-file-request-info file-id 1 team #'update))))) + +(defun slack-ws-handle-star-added (payload team) + (let* ((item (plist-get payload :item)) + (item-type (plist-get item :type))) + (cl-labels + ((update-message (message) + (slack-message-star-added message) + (slack-message-update message team t t))) + (cond + ((string= item-type "file") + (slack-ws-handle-star-added-to-file (plist-get (plist-get item :file) :id) + team)) + ((string= item-type "message") + (slack-if-let* ((room (slack-room-find (plist-get item :channel) team)) + (ts (plist-get (plist-get item :message) :ts)) + (message (slack-room-find-message room ts))) + (update-message message))))) + (slack-if-let* ((star (oref team star))) + (slack-star-add star item team)))) + + +;; [2018-07-25 16:30:03] (:type star_added :user U1013370U :item (:type file :file (:id FBWDT9VH8) :date_create 1532503802 :file_id FBWDT9VH8 :user_id USLACKBOT) :event_ts 1532503802.000378) +(defun slack-ws-handle-star-removed-from-file (file-id team) + (let ((file (slack-file-find file-id team))) + (cl-labels + ((update (&rest _args) + (slack-with-file file-id team + (slack-message-star-removed file) + (slack-message-update file team)))) + (if file (update) + (slack-file-request-info file-id 1 team #'update))))) + +(defun slack-ws-handle-star-removed (payload team) + (let* ((item (plist-get payload :item)) + (item-type (plist-get item :type))) + (cl-labels + ((update-message (message) + (slack-message-star-removed message) + (slack-message-update message team t t))) + (cond + ((string= item-type "file") + (slack-ws-handle-star-removed-from-file (plist-get (plist-get item :file) :id) + team)) + ((string= item-type "message") + (slack-if-let* ((room (slack-room-find (plist-get item :channel) team)) + (ts (plist-get (plist-get item :message) :ts)) + (message (slack-room-find-message room ts))) + (update-message message))))) + + (slack-if-let* ((star (oref team star))) + (slack-star-remove star item team)))) + +(defun slack-ws-handle-app-conversation-invite-request (payload team) + (let* ((app-user (plist-get payload :app_user)) + (channel-id (plist-get payload :channel_id)) + (invite-message-ts (plist-get payload :invite_message_ts)) + (scope-info (plist-get payload :scope_info)) + (room (slack-room-find channel-id team))) + (if (yes-or-no-p (format "%s\n%s\n" + (format "%s would like to do following in %s" + (slack-user-name app-user team) + (slack-room-name room team)) + (mapconcat #'(lambda (scope) + (format "* %s" + (plist-get scope + :short_description))) + scope-info + "\n"))) + (slack-app-conversation-allow-invite-request team + :channel channel-id + :app-user app-user + :invite-message-ts invite-message-ts) + (slack-app-conversation-deny-invite-request team + :channel channel-id + :app-user app-user + :invite-message-ts invite-message-ts)))) + +(cl-defun slack-app-conversation-allow-invite-request (team &key channel + app-user + invite-message-ts) + (let ((url "https://slack.com/api/apps.permissions.internal.add") + (params (list (cons "channel" channel) + (cons "app_user" app-user) + (cons "invite_message_ts" invite-message-ts) + (cons "did_confirm" "true") + (cons "send_ephemeral_error_message" "true")))) + (cl-labels + ((log-error (err) + (slack-log (format "Error: %s, URL: %s, PARAMS: %s" + err + url + params) + team :level 'error)) + (on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-app-conversation-allow-invite-request" + #'log-error) + (message "DATA: %s" data)))) + (slack-request + (slack-request-create + url + team + :type "POST" + :params params + :success #'on-success))))) + +(cl-defun slack-app-conversation-deny-invite-request (team &key channel + app-user + invite-message-ts) + (let ((url "https://slack.com/api/apps.permissions.internal.denyAdd") + (params (list (cons "channel" channel) + (cons "app_user" app-user) + (cons "invite_message_ts" invite-message-ts)))) + (cl-labels + ((log-error (err) + (slack-log (format "Error: %s, URL: %s, PARAMS: %s" + err + url + params) + team :level 'error)) + (on-success (&key data &allow-other-keys) + (slack-request-handle-error + (data "slack-app-conversation-deny-invite-request" + #'log-error) + (message "DATA: %s" data)))) + (slack-request + (slack-request-create + url + team + :type "POST" + :params params + :success #'on-success))))) + +(defun slack-ws-handle-commands-changed (payload team) + (let ((commands-updated (mapcar #'slack-command-create + (plist-get payload :commands_updated))) + (commands-removed (mapcar #'slack-command-create + (plist-get payload :commands_removed))) + (commands '())) + (cl-loop for command in (oref team commands) + if (and (not (cl-find-if #'(lambda (e) (slack-equalp command e)) + commands-removed)) + (not (cl-find-if #'(lambda (e) (slack-equalp command e)) + commands-updated))) + do (push command commands)) + (cl-loop for command in commands-updated + do (push command commands)) + (oset team commands commands))) + +(defun slack-ws-handle-dialog-opened (payload team) + (slack-if-let* + ((dialog-id (plist-get payload :dialog_id)) + (client-token (plist-get payload :client_token)) + (valid-client-tokenp (string= (slack-team-client-token team) + client-token))) + (slack-dialog-get dialog-id team))) + +(defun slack-ws-handle-room-left (payload team) + (slack-if-let* ((room (slack-room-find (plist-get payload :channel) + team))) + (progn + (when (slot-exists-p room 'is-member) + (oset room is-member nil)) + (when (and (not (slack-channel-p room)) (slack-group-p room)) + (oset team groups + (cl-remove-if #'(lambda (e) + (slack-room-equal-p e room)) + (oref team groups)))) + (slack-log (format "You left %s" (slack-room-name room team)) + team :level 'info)))) + + +(provide 'slack-websocket) +;;; slack-websocket.el ends here + diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-websocket.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-websocket.elc new file mode 100644 index 000000000000..03f7cd624564 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack-websocket.elc Binary files differdiff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack.el new file mode 100644 index 000000000000..56e821c86163 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack.el @@ -0,0 +1,229 @@ +;;; slack.el --- slack client for emacs -*- lexical-binding: t; -*- + +;; Copyright (C) 2015 yuya.minami + +;; Author: yuya.minami <yuya.minami@yuyaminami-no-MacBook-Pro.local> +;; Keywords: tools +;; Version: 0.0.2 +;; Package-Requires: ((websocket "1.8") (request "0.2.0") (oauth2 "0.10") (circe "2.3") (alert "1.2") (emojify "0.4") (emacs "24.4")) +;; 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 'cl-lib) +(require 'subr-x) +(require 'oauth2) +(require 'color) + +(require 'slack-util) +(require 'slack-team) +(require 'slack-channel) +(require 'slack-im) +(require 'slack-file) +(require 'slack-message-notification) +(require 'slack-message-sender) +(require 'slack-message-editor) +(require 'slack-message-reaction) +(require 'slack-user-message) +(require 'slack-bot-message) +(require 'slack-search) +(require 'slack-reminder) +(require 'slack-thread) +(require 'slack-attachment) +(require 'slack-emoji) +(require 'slack-star) + +(require 'slack-buffer) +(require 'slack-message-buffer) +(require 'slack-message-edit-buffer) +(require 'slack-message-share-buffer) +(require 'slack-thread-message-buffer) +(require 'slack-room-message-compose-buffer) +(require 'slack-pinned-items-buffer) +(require 'slack-user-profile-buffer) +(require 'slack-file-list-buffer) +(require 'slack-file-info-buffer) +(require 'slack-thread-message-compose-buffer) +(require 'slack-search-result-buffer) +(require 'slack-stars-buffer) +(require 'slack-dialog-buffer) +(require 'slack-dialog-edit-element-buffer) + +(require 'slack-websocket) +(require 'slack-request) +(require 'slack-request-worker) + +(when (featurep 'helm) + (require 'helm-slack)) + +(defgroup slack nil + "Emacs Slack Client" + :prefix "slack-" + :group 'tools) + +(defcustom slack-redirect-url "http://localhost:8080" + "Redirect url registered for Slack.") +(defcustom slack-buffer-function #'switch-to-buffer-other-window + "Function to print buffer.") + +(defvar slack-use-register-team-string + "use `slack-register-team' instead.") + +(defcustom slack-client-id nil + "Client ID provided by Slack.") +(make-obsolete-variable + 'slack-client-id slack-use-register-team-string + "0.0.2") +(defcustom slack-client-secret nil + "Client Secret Provided by Slack.") +(make-obsolete-variable + 'slack-client-secret slack-use-register-team-string + "0.0.2") +(defcustom slack-token nil + "Slack token provided by Slack. +set this to save request to Slack if already have.") +(make-obsolete-variable + 'slack-token slack-use-register-team-string + "0.0.2") +(defcustom slack-room-subscription '() + "Group or Channel list to subscribe notification." + :group 'slack) +(make-obsolete-variable + 'slack-room-subscription slack-use-register-team-string + "0.0.2") +(defcustom slack-typing-visibility 'frame + "When to show typing indicator. +frame means typing slack buffer is in the current frame, show typing indicator. +buffer means typing slack buffer is the current buffer, show typing indicator. +never means never show typing indicator." + :type '(choice (const frame) + (const buffer) + (const never))) + +(defcustom slack-display-team-name t + "If nil, only display channel, im, group name." + :group 'slack) + +(defcustom slack-completing-read-function #'completing-read + "Require same argument with `completing-read'." + :group 'slack) + +(defconst slack-oauth2-authorize "https://slack.com/oauth/authorize") +(defconst slack-oauth2-access "https://slack.com/api/oauth.access") +(defconst slack-authorize-url "https://slack.com/api/rtm.start") +(defconst slack-rtm-connect-url "https://slack.com/api/rtm.connect") + +(defun slack-authorize (team &optional error-callback success-callback) + (let ((authorize-request (oref team authorize-request))) + (if (and authorize-request (not (request-response-done-p authorize-request))) + (slack-log "Authorize Already Requested" team) + (cl-labels + ((on-error (&key error-thrown symbol-status response data) + (oset team authorize-request nil) + (slack-log (format "Slack Authorize Failed: %s" error-thrown) + team) + (when (functionp error-callback) + (funcall error-callback + :error-thrown error-thrown + :symbol-status symbol-status + :response response + :data data))) + (on-success (&key data &allow-other-keys) + (oset team authorize-request nil) + (if success-callback + (funcall success-callback data) + (slack-on-authorize data team)))) + (let ((request (slack-request + (slack-request-create + slack-rtm-connect-url + team + :params (list (cons "mpim_aware" "1")) + :success #'on-success + :error #'on-error)))) + (oset team authorize-request request)))))) + +(defun slack-update-team (data team) + (let ((self (plist-get data :self)) + (team-data (plist-get data :team))) + (oset team id (plist-get team-data :id)) + (oset team name (plist-get team-data :name)) + (oset team self self) + (oset team self-id (plist-get self :id)) + (oset team self-name (plist-get self :name)) + (oset team ws-url (plist-get data :url)) + (oset team domain (plist-get team-data :domain)) + team)) + +(cl-defun slack-on-authorize (data team) + (slack-request-handle-error + (data "slack-authorize") + (slack-log (format "Slack Authorization Finished" (oref team name)) team) + (let ((team (slack-update-team data team))) + (cl-labels + ((on-open () + (slack-channel-list-update team) + (slack-group-list-update team) + (slack-im-list-update team) + (slack-bot-list-update team) + (slack-request-emoji team) + (slack-command-list-update team) + (slack-update-modeline))) + (slack-ws-open team :on-open #'on-open))))) + +(defun slack-on-authorize-e + (&key error-thrown &allow-other-keys &rest_) + (error "slack-authorize: %s" error-thrown)) + +(defun slack-oauth2-auth (team) + (with-slots (client-id client-secret) team + (oauth2-auth + slack-oauth2-authorize + slack-oauth2-access + client-id + client-secret + "client" + nil + slack-redirect-url))) + +(defun slack-request-token (team) + (with-slots (token) team + (setq token + (oauth2-token-access-token + (slack-oauth2-auth team))))) + +;;;###autoload +(defun slack-start (&optional team) + (interactive) + (cl-labels ((start + (team) + (slack-team-kill-buffers team) + (slack-ws-close team) + (when (slack-team-need-token-p team) + (slack-request-token team) + (kill-new (oref team token)) + (message "Your Token is added to kill ring.")) + (slack-authorize team))) + (if team + (start team) + (if slack-teams + (cl-loop for team in slack-teams + do (start team)) + (slack-start (call-interactively #'slack-register-team)))) + (slack-enable-modeline))) + +(provide 'slack) +;;; slack.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack.elc b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack.elc new file mode 100644 index 000000000000..90fbe67ac873 --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180913.651/slack.elc Binary files differ |