From 3618a7b8ca3b093b2c49fd4db60e021f7aa3359d Mon Sep 17 00:00:00 2001 From: Zajcev Evgeny Date: Mon, 3 Feb 2025 00:19:55 +0300 Subject: [PATCH] Initial support for TDLib 1.8.44 - [fix] Use `custom-face-get-current-spec` instead of `custom-face-get-current-spec-unfiltered` to be more compatible with older Emacs, fixes https://t.me/emacs_telega/47611 - [enh] Improvements for `telega-msg-save`, start downloading file while user enters filename to save file to. Version -> 0.8.440 --- etc/Dockerfile | 4 +- etc/langs/en.plist | 2 + telega-chat.el | 3 +- telega-core.el | 2 +- telega-customize.el | 3 +- telega-emoji.el | 105 +++++++++++++++++++++++--------------------- telega-msg.el | 65 +++++++++++++++------------ telega-root.el | 6 ++- telega-tdlib.el | 12 ++--- telega-user.el | 3 +- telega.el | 6 +-- 11 files changed, 115 insertions(+), 96 deletions(-) diff --git a/etc/Dockerfile b/etc/Dockerfile index 97d441d..f96f030 100644 --- a/etc/Dockerfile +++ b/etc/Dockerfile @@ -16,8 +16,8 @@ # This comment is to trigger ARM64 build FROM alpine:latest AS builder -ARG tdlib_version=v1.8.42 -ARG tdlib_branch=2be9e799a +ARG tdlib_version=v1.8.44 +ARG tdlib_branch=28c6f2e9c ARG telega_branch=master RUN set +x && apk update && apk upgrade && \ diff --git a/etc/langs/en.plist b/etc/langs/en.plist index 75ecd83..a61314a 100644 --- a/etc/langs/en.plist +++ b/etc/langs/en.plist @@ -1928,4 +1928,6 @@ You can send them an invite link as message instead.") ("lng_stats_overview_message_views" :value "Views") + ("lng_save_file" + :value "Save File") ) diff --git a/telega-chat.el b/telega-chat.el index 8b2c82e..3d9f893 100644 --- a/telega-chat.el +++ b/telega-chat.el @@ -386,7 +386,8 @@ end of the title." ;; Premium Badge (cond ((plist-get chat :emoji_status) (telega-ins--as-string - (telega-ins--chat-emoji-status chat))) + (telega-ins--emoji-status + (plist-get chat :emoji_status)))) ((plist-get info :is_premium) (telega-symbol 'premium))) diff --git a/telega-core.el b/telega-core.el index 4137953..2635c12 100644 --- a/telega-core.el +++ b/telega-core.el @@ -539,7 +539,7 @@ to make `:outline' be a `:foreground'." (declare (indent 2)) (let ((new-face (cond ((facep face) (face-spec-choose - (custom-face-get-current-spec-unfiltered face))) + (custom-face-get-current-spec face))) (t (cl-assert (listp face)) face))) diff --git a/telega-customize.el b/telega-customize.el index 10dc065..471a9df 100644 --- a/telega-customize.el +++ b/telega-customize.el @@ -1899,8 +1899,7 @@ So different messages could have different aux heading formatting." :group 'telega-msg) (defcustom telega-msg-save-dir nil - "*Directory for `telega-msg-save' without asking. -If nil, the saved path is always asked." + "*Directory to save files with `telega-msg-save' to." :type '(choice (const :tag "Always ask for a directory to save to" nil) string) :group 'telega-msg) diff --git a/telega-emoji.el b/telega-emoji.el index 86fe836..23cbd7c 100644 --- a/telega-emoji.el +++ b/telega-emoji.el @@ -29,6 +29,7 @@ (declare-function telega-root-view--update "telega-root" (on-update-prop &rest args)) (declare-function telega-msg-redisplay "telega-chat" (msg &optional node)) (declare-function telega-chat--update "telega-tdlib-events" (chat &rest events)) +(declare-function telega-match-p "telega-match-p" (object temex)) (defvar telega-emoji-alist nil) (defvar telega-emoji-candidates nil) @@ -398,9 +399,11 @@ Do not fetch custom emojis for ignored messages." (let ((known-stickers nil) (unknown-ids nil)) (seq-doseq (es tl-emoji-statuses) - (let* ((ce-id (plist-get es :custom_emoji_id)) - (ce-sticker (telega-custom-emoji-get ce-id))) - (if ce-sticker + (when-let* ((es-type (plist-get es :type)) + (ce-id (when (telega-match-p es-type + '(tl-type emojiStatusTypeCustomEmoji)) + (plist-get es-type :custom_emoji_id)))) + (if-let ((ce-sticker (telega-custom-emoji-get ce-id))) (setq known-stickers (cons ce-sticker known-stickers)) (setq unknown-ids (cons ce-id unknown-ids))))) @@ -411,6 +414,7 @@ Do not fetch custom emojis for ignored messages." (mapcar #'telega-custom-emoji--ensure (telega--getCustomEmojiStickers unknown-ids)))) (t + (cl-assert callback) (telega--getCustomEmojiStickers unknown-ids (lambda (stickers) (funcall callback @@ -421,22 +425,23 @@ Do not fetch custom emojis for ignored messages." (defun telega-emoji-status--image (emoji-status &optional _ignoredfile) "Return image for the user's EMOJI-STATUS." - (let* ((custom-emoji-id (plist-get emoji-status :custom_emoji_id)) - (sticker (telega-custom-emoji-get custom-emoji-id)) - image) - (if sticker - (setq image (telega-sticker--image sticker)) - - ;; Use Premium Logo as emoji status while downloading actual sticker - (setq image (telega-etc-file-create-image "symbols/premium.svg" 2)) - (telega--getCustomEmojiStickers (list custom-emoji-id) - (lambda (stickers) - (cl-assert (= 1 (length stickers))) - (let ((custom-emoji (car stickers))) - (telega-custom-emoji--ensure custom-emoji) - ;; NOTE: image could be nil if `telega-use-images' is nil - (setq image (telega-sticker--image custom-emoji))))) - image))) + (let ((es-type (plist-get emoji-status :type))) + (cl-ecase (telega--tl-type es-type) + (emojiStatusTypeCustomEmoji + (let* ((custom-emoji-id (plist-get es-type :custom_emoji_id)) + (sticker (telega-custom-emoji-get custom-emoji-id))) + (if sticker + (telega-sticker--image sticker) + + (telega--getCustomEmojiStickers (list custom-emoji-id) + (lambda (stickers) + (seq-doseq (custom-emoji stickers) + (telega-custom-emoji--ensure custom-emoji)))) + (telega-etc-file-create-image "symbols/premium.svg" 2)))) + + (emojiStatusTypeUpgradedGift + ;; TODO + )))) (defun telega-ins--emoji-status (emoji-status) "Inserter for the EMOJI-STATUS." @@ -444,14 +449,6 @@ Do not fetch custom emojis for ignored messages." (telega-ins--image (telega-emoji-status--image emoji-status) nil))) -(defun telega-ins--user-emoji-status (user) - "Inserter USER's emoji status." - (telega-ins--emoji-status (plist-get user :emoji_status))) - -(defun telega-ins--chat-emoji-status (chat) - "Inserter CHAT's emoji status." - (telega-ins--emoji-status (plist-get chat :emoji_status))) - (defun telega-emoji-status--animate (emoji-status) "Animate EMOJI-STATUS." (let* ((custom-emoji-id (plist-get emoji-status :custom_emoji_id)) @@ -460,12 +457,6 @@ Do not fetch custom emojis for ignored messages." (not (telega-sticker-static-p sticker))) (telega-sticker--animate sticker)))) -(defun telega-emoji-status-from-sticker (sticker) - "Create emoji status from given STICKER." - (cl-assert (telega-custom-emoji-sticker-p sticker)) - (list :@type "emojiStatus" - :custom_emoji_id (telega-custom-emoji-id sticker))) - (defun telega-emoji-status-list--gen-ins-callback (custom-action) (let ((stickers-callback (telega--gen-ins-continuation-callback 'loading (lambda (stickers) @@ -480,28 +471,42 @@ Do not fetch custom emojis for ignored messages." (let ((help-window-select t)) (with-telega-help-win "*Telegram Emoji Status*" ;; NOTE: use callbacks for async emoji statuses loading - (telega-ins "Themed:\n") - (telega--getThemedEmojiStatuses - (telega-emoji-status-list--gen-ins-callback custom-action)) - - (telega-ins "\nRecent:\n") - (telega--getRecentEmojiStatuses - (telega-emoji-status-list--gen-ins-callback custom-action)) + (telega-ins--with-face 'telega-describe-item-title + (telega-ins "Themed:\n")) + (telega-ins--line-wrap-prefix " " + (telega--getThemedEmojiStatuses + (telega-emoji-status-list--gen-ins-callback custom-action))) + + (telega-ins "\n") + (telega-ins--with-face 'telega-describe-item-title + (telega-ins "Recent:\n")) + (telega-ins--line-wrap-prefix " " + (telega--getRecentEmojiStatuses + (telega-emoji-status-list--gen-ins-callback custom-action))) + + (telega-ins "\n") + (telega-ins--with-face 'telega-describe-item-title + (telega-ins "Default:\n")) + (telega-ins--line-wrap-prefix " " + (telega--getDefaultEmojiStatuses + (telega-emoji-status-list--gen-ins-callback custom-action))) ;; Sticker sets with custom emojis + (telega-ins "\n") (dolist (sset-info telega--stickersets-custom-emojis) (cl-assert (eq (telega--tl-type (plist-get sset-info :sticker_type)) 'stickerTypeCustomEmoji)) - (telega-ins "\n" (telega-stickerset-title sset-info 'raw) ":\n") - (let ((cb (telega-emoji-status-list--gen-ins-callback custom-action))) - (telega--getStickerSet (plist-get sset-info :id) - (lambda (sset) - (funcall cb (mapcar #'telega-emoji-status-from-sticker - (plist-get sset :stickers))))))) - - (telega-ins "\nDefault:\n") - (telega--getDefaultEmojiStatuses - (telega-emoji-status-list--gen-ins-callback custom-action)) + (telega-ins "\n") + (telega-ins--with-face 'telega-describe-item-title + (telega-ins (telega-stickerset-title sset-info 'raw) ":\n")) + (telega-ins--line-wrap-prefix " " + (let ((cb (telega-emoji-status-list--gen-ins-callback custom-action))) + (telega--getStickerSet (plist-get sset-info :id) + (lambda (sset) + (funcall cb (mapcar + #'telega--custom-emoji-id-wrap-into-emoji-status + (mapcar #'telega-custom-emoji-id + (plist-get sset :stickers))))))))) ))) diff --git a/telega-msg.el b/telega-msg.el index cf03c99..f46225e 100644 --- a/telega-msg.el +++ b/telega-msg.el @@ -1290,7 +1290,7 @@ If WITH-PREFIX-P is non-nil, then prefix username with \"@\" char." (telega-custom-emoji-get v-custom-emoji-id)))) (if v-sticker (telega-ins--as-string - (telega-ins--image (telega-sticker--image sticker))) + (telega-ins--image (telega-sticker--image v-sticker))) (telega-symbol 'verified))))))) (defun telega-msg-sender-title (msg-sender &rest args) @@ -1647,34 +1647,41 @@ Saved Messages." (list :@type "inputFileId" :id (plist-get file :id)))) (t - (message "Downloading file...") - (telega-file--download file - :priority 32 - :update-callback - (lambda (dfile) - (telega-msg-redisplay msg) - (when (telega-file--downloaded-p dfile) - ;; TODO: This might be executed in process filter, so - ;; pressing C-g will trigger "error in process filter: Quit" - ;; Need to execute this outside of process filter - (let* ((fpath (telega--tl-get dfile :local :path)) - (fname (file-name-nondirectory fpath)) - (new-fpath (if telega-msg-save-dir - (expand-file-name fname telega-msg-save-dir) - (read-file-name "Save to file: " default-directory - nil nil fname nil)))) - ;; NOTE: Ensure corresponding directory exists - (let ((fdir (file-name-directory new-fpath))) - (unless (file-exists-p fdir) - (if (y-or-n-p - (format-message - "Directory `%s' does not exist; create? " fdir)) - (make-directory fdir t) - (error "Canceled")))) - - ;; See https://github.com/tdlib/td/issues/379 - (copy-file fpath new-fpath 1) - (message (format "Wrote %s" new-fpath)))))))))) + ;; NOTE: Start downloading file in the background while reading + ;; filename + (unless (telega-file--downloaded-p file) + (telega-file--download file + :priority 32 + :update-callback + (lambda (_dfile) + (telega-msg-redisplay msg)))) + + (let* ((fpath (telega--tl-get file :local :path)) + (fname (when fpath (file-name-nondirectory fpath))) + (new-fpath + (if (and fname telega-msg-save-dir) + (expand-file-name fname telega-msg-save-dir) + (read-file-name (concat (telega-i18n "lng_save_file") ": ") + (or telega-msg-save-dir default-directory) + nil nil fname)))) + ;; NOTE: Ensure corresponding directory exists + (let ((fdir (file-name-directory new-fpath))) + (unless (file-exists-p fdir) + (if (y-or-n-p + (format-message + "Directory `%s' does not exist; create? " fdir)) + (make-directory fdir t) + (error "Canceled")))) + + ;; See https://github.com/tdlib/td/issues/379 + (telega-file--download file + :priority 32 + :update-callback + (lambda (dfile) + (when (telega-file--downloaded-p dfile) + (copy-file (telega--tl-get dfile :local :path) new-fpath 1) + (message (format "Wrote %s" new-fpath))))) + ))))) (defun telega-msg-copy-link (msg &optional for-thread-p) "Copy link to message to kill ring. diff --git a/telega-root.el b/telega-root.el index 2bdca11..8349387 100644 --- a/telega-root.el +++ b/telega-root.el @@ -825,7 +825,8 @@ Status values are hold in the `telega--status' and (call-interactively #'telega-account-switch)) 'help "Switch to another account") (when user-me - (telega-ins--user-emoji-status user-me)) + (when-let ((emoji-status (plist-get user-me :emoji_status))) + (telega-ins--emoji-status emoji-status))) (telega-ins ")"))) (unless (eq 'other telega-network-type) (telega-ins-fmt " [%S]" telega-network-type)) @@ -1682,7 +1683,8 @@ If `\\[universal-argument]' is given, then view missed calls only." ;; Emoji status (when (telega-user-match-p me-user 'is-premium) (telega-ins-describe-item "Emoji Status" - (telega-ins--user-emoji-status me-user) + (when-let ((emoji-status (plist-get me-user :emoji_status))) + (telega-ins--emoji-status emoji-status)) (telega-ins " ") (telega-ins--box-button "Set Emoji Status" 'action (lambda (_button) diff --git a/telega-tdlib.el b/telega-tdlib.el index b125e39..b36a2a5 100644 --- a/telega-tdlib.el +++ b/telega-tdlib.el @@ -138,7 +138,7 @@ Non-nil EXACT-MATCH-P to return only emojis that exactly matches TEXT." "Returns list of custom emoji stickers by their identifiers." (declare (indent 1)) (with-telega-server-reply (reply) - (append (plist-get reply :stickers) nil) + (plist-get reply :stickers) (list :@type "getCustomEmojiStickers" :custom_emoji_ids (apply #'vector custom-emoji-ids)) @@ -2645,10 +2645,13 @@ Pass non-nil UPDATE-RECENT-REACTIONS-P to update recent reactions." ;; instead of `:emoji_statuses', so we wrap them into emoji status ;; alike structure (defun telega--custom-emoji-id-wrap-into-emoji-status (custom-emoji-id) - (list :custom_emoji_id custom-emoji-id)) + (list :@type "emojiStatus" + :type (list :@type "emojiStatusTypeCustomEmoji" + :custom_emoji_id custom-emoji-id) + :expiration_date 0)) (defun telega--getThemedEmojiStatuses (&optional callback) - "Returns up to 8 themed emoji statuses." + "Returns up to 8 themed custom emoji ids." (with-telega-server-reply (reply) (mapcar #'telega--custom-emoji-id-wrap-into-emoji-status (plist-get reply :custom_emoji_ids)) @@ -2658,8 +2661,7 @@ Pass non-nil UPDATE-RECENT-REACTIONS-P to update recent reactions." (defun telega--getRecentEmojiStatuses (&optional callback) "Return recent emoji statuses." (with-telega-server-reply (reply) - (mapcar #'telega--custom-emoji-id-wrap-into-emoji-status - (plist-get reply :custom_emoji_ids)) + (plist-get reply :emoji_statuses) (list :@type "getRecentEmojiStatuses") callback)) diff --git a/telega-user.el b/telega-user.el index 7ca1e6e..4cbe7c8 100644 --- a/telega-user.el +++ b/telega-user.el @@ -170,7 +170,8 @@ Return nil if given FMT-TYPE is not available." ;; Premium Badge (cond ((plist-get user :emoji_status) (telega-ins--as-string - (telega-ins--user-emoji-status user))) + (telega-ins--emoji-status + (plist-get user :emoji_status)))) ((plist-get user :is_premium) (telega-symbol 'premium))) diff --git a/telega.el b/telega.el index 64efc04..241bbfa 100644 --- a/telega.el +++ b/telega.el @@ -8,10 +8,10 @@ ;; Keywords: comm ;; Package-Requires: ((emacs "27.1") (visual-fill-column "1.9") (transient "0.3.0")) ;; URL: https://github.com/zevlg/telega.el -;; Version: 0.8.420 -(defconst telega-version "0.8.420") +;; Version: 0.8.440 +(defconst telega-version "0.8.440") (defconst telega-server-min-version "0.7.7") -(defconst telega-tdlib-min-version "1.8.42") +(defconst telega-tdlib-min-version "1.8.44") (defconst telega-tdlib-max-version nil) (defconst telega-tdlib-releases '("1.8.0" . "1.9.0")