;;; slack-message-formatter.el --- format message text -*- 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 . ;;; Commentary: ;; ;;; Code: (require 'eieio) (require 'slack-user) (require 'slack-room) (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 (:overline t))) "Face used to reactions." :group 'slack) (defface slack-message-deleted-face '((t (:strike-through t))) "Face used to deleted message." :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-reactions-property (text) (if text (propertize text 'face 'slack-message-output-reaction))) (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))) (defmethod slack-message-propertize ((m slack-message) text) text) (defun slack-message-time-to-string (ts) (if ts (format-time-string "%Y-%m-%d %H:%M:%S" (seconds-to-time (string-to-number ts))))) (defun slack-message-reactions-to-string (reactions) (if reactions (concat "\n" (mapconcat #'slack-reaction-to-string reactions " ")))) (defmethod slack-message-header ((m slack-message) team) (slack-message-sender-name m team)) (defun slack-format-message (header body attachment-body reactions) (let ((messages (list header body attachment-body reactions))) (concat (mapconcat #'identity (cl-remove-if #'(lambda (e) (< (length e) 1)) messages) "\n") "\n"))) (defmethod slack-message-to-string ((m slack-message) team) (let ((text (if (slot-boundp m 'text) (oref m text)))) (let* ((header (slack-message-put-header-property (slack-message-header m team))) (row-body (slack-message-body m team)) (attachment-body (slack-message-attachment-body m team)) (body (if (oref m deleted-at) (slack-message-put-deleted-property row-body) (slack-message-put-text-property row-body))) (reactions-str (slack-message-put-reactions-property (slack-message-reactions-to-string (oref m reactions))))) (slack-message-propertize m (slack-format-message header body attachment-body reactions-str))))) (defmethod slack-message-body ((m slack-message) team) (with-slots (text) m (slack-message-unescape-string text team))) (defmethod slack-message-attachment-body ((m slack-message) team) (with-slots (attachments) m (let ((body (mapconcat #'slack-attachment-to-string attachments "\n"))) (if (< 0 (length body)) (slack-message-unescape-string body team))))) (defmethod slack-message-to-alert ((m slack-message) team) (with-slots (text) m (slack-message-unescape-string 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-command (slack-message-unescape-user-id (slack-message-unescape-channel gt-unescaped) 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) (slack-user-name (match-string 1 text) team) (match-string 1 text))))) (replace-regexp-in-string user-regexp #'unescape-user-id text 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))))) (defun slack-message-unescape-command (text) (let ((command-regexp "")) (cl-labels ((unescape-command (text) (concat "@" (match-string 1 text)))) (replace-regexp-in-string command-regexp #'unescape-command text)))) (defun slack-message-unescape-channel (text) (let ((channel-regexp "<#\\(C.*?\\)|\\(.*?\\)>")) (cl-labels ((unescape-channel (text) (concat "#" (or (match-string 2 text) (slack-room-find (match-string 1 text)) (match-string 1 text))))) (replace-regexp-in-string channel-regexp #'unescape-channel text t)))) (provide 'slack-message-formatter) ;;; slack-message-formatter.el ends here