265 lines
10 KiB
EmacsLisp
265 lines
10 KiB
EmacsLisp
|
;;; 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-file-comment (slack-star-file)
|
||
|
((file-comment :initarg :file-comment :type slack-file-comment)))
|
||
|
|
||
|
(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-star-item-message ((this slack-star-file-comment))
|
||
|
(oref this file-comment))
|
||
|
|
||
|
(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)
|
||
|
(slack-message-to-string (oref this message) team))
|
||
|
|
||
|
(defmethod slack-to-string ((this slack-star-file-comment) team)
|
||
|
(slack-message-to-string (oref this file-comment) team))
|
||
|
|
||
|
(defmethod slack-to-string ((this slack-star-file) team)
|
||
|
(slack-message-to-string (oref this file) 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 "file_comment")
|
||
|
(make-instance 'slack-star-file-comment
|
||
|
:date-create date-create
|
||
|
:file file
|
||
|
:file-comment (slack-file-comment-create
|
||
|
(plist-get payload :comment)
|
||
|
file-id)))
|
||
|
((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
|