Telega bridge bot, 替换 IM 转发机器人的用户名和头像

Telegram 群组里经常能见到转发来自别的 IM 比如 IRC、 Matrix 消息的机器人。
但是这些机器人发来的消息不太好辨认,所以我写了一个简单的 telega.el 补丁来替换用户名和头像。

效果如下,还不太完美,比如转发的消息可能合并在一起显示了,应该根据实际的用户名进行合并,分隔用户名和正文的逻辑是硬编码的,等等问题。各位可以根据需要自行修改。

使用方法

(require 'telega-bridge-bot)
;; 这两个 id 是 emacs cn 频道和 archlinux 频道的转发机器人,可以自行补充
(setq telega-bridge-bot-id-list '(5296957089 420415423))
(telega-bridge-bot-replace-user)
;;; package --- Replace bridge bot username
;;; Commentary:
;; Replace the bridge bot's username with the sender's username.
;;; Code:
(require 'telega)

(defvar telega-bridge-bot-id-list '(5296957089 420415423))

(defun telega-user-color! (user cache-id)
  "Return color list associated with USER.
It will use CACHE-ID as the plist key to cache the result."
  (or (plist-get user cache-id)
      (let* ((chat (telega-chat-get (plist-get user :id) 'offline))
             (colors (if chat
                         (telega-chat-color chat)
                       (let ((user-title (telega-user-title user 'name)))
                         (list (funcall telega-rainbow-color-function
                                        user-title 'light)
                               (funcall telega-rainbow-color-function
                                        user-title 'dark))))))
        (plist-put user cache-id colors)
        colors)))

(defun telega-ins--message0! (orig-fun &rest args)
  "Advice function for `telega-ins--message0'."
  (if-let* ((msg (car args)) ; get the orig msg
            (bot-id (telega--tl-get msg :sender_id :user_id))
            (_ (memql bot-id telega-bridge-bot-id-list)) ; check if it is a bridge bot
            (content (telega--tl-get msg :content))
            (_ (eq (telega--tl-type content) 'messageText))
            (content-text (telega--tl-get content :text))
            (_ (eq (telega--tl-type content-text) 'formattedText))
            (content-text-text (telega--tl-get content-text :text)) ; get the msg body
            (name-and-body (split-string content-text-text ": "))
            (name (car name-and-body))
            (body (cadr name-and-body))
            (cache-id (concat (number-to-string bot-id) name))
            (cache-id-color (intern (concat "color" cache-id)))
            (cache-id-image (intern (concat "image" cache-id)))
            ;; TODO: delete usename in msg body
            )
      ;; change user title and avatar
      (cl-letf* (((symbol-function 'telega-user-title) (lambda (&rest _) name)) ; replace user title
                 ((symbol-function 'telega-user-color)
                  (lambda (user) (telega-user-color! user cache-id-color))) ; cache username color
                 (orig-telega-avatar--create-image (symbol-function 'telega-avatar--create-image))
                 ((symbol-function 'telega-avatar--create-image)
                  (lambda (sender _ &optional cheight addon-function)
                    ;; Set file as nil
                    ;; So telega will think that the user does not have an avatar,
                    ;; and use the first character of the user name to generate an avatar
                    (funcall orig-telega-avatar--create-image sender nil cheight addon-function)))
                 (orig-telega-media--image (symbol-function 'telega-media--image))
                 ((symbol-function 'telega-media--image)
                  (lambda (obj-spec file-spec &optional force-update _)
                    ;; Set cache key
                    (funcall orig-telega-media--image obj-spec file-spec force-update cache-id-image))))
        (apply orig-fun args))
    ;; Otherwise return the orig msg
    (apply orig-fun args)))

(defun telega-bridge-bot-replace-user ()
  "Replace bridge bot's username and avatar."
  (advice-add 'telega-ins--message0 :around #'telega-ins--message0!))

(provide 'telega-bridge-bot)
;;; telega-bridge-bot.el ends here

如果有更新会同步在这里:

1 个赞

telega-bridge-bot-id-listdefcustom 是不是更好点

是的,只是我比较懒哈哈哈