diff options
Diffstat (limited to 'lisp/mastodon-notifications.el')
| -rw-r--r-- | lisp/mastodon-notifications.el | 267 | 
1 files changed, 150 insertions, 117 deletions
diff --git a/lisp/mastodon-notifications.el b/lisp/mastodon-notifications.el index 2091118..b758c6f 100644 --- a/lisp/mastodon-notifications.el +++ b/lisp/mastodon-notifications.el @@ -162,40 +162,6 @@ Can be called in notifications view or in follow-requests view."    (interactive)    (mastodon-notifications--follow-request-process :reject)) -(defun mastodon-notifications--mention (note) -  "Format for a `mention' NOTE." -  (mastodon-notifications--format-note note 'mention)) - -(defun mastodon-notifications--follow (note) -  "Format for a `follow' NOTE." -  (mastodon-notifications--format-note note 'follow)) - -(defun mastodon-notifications--follow-request (note) -  "Format for a `follow-request' NOTE." -  (mastodon-notifications--format-note note 'follow-request)) - -(defun mastodon-notifications--favourite (note) -  "Format for a `favourite' NOTE." -  (mastodon-notifications--format-note note 'favourite)) - -(defun mastodon-notifications--reblog (note) -  "Format for a `boost' NOTE." -  (mastodon-notifications--format-note note 'reblog)) - -(defun mastodon-notifications--status (note) -  "Format for a `status' NOTE. -Status notifications are given when -`mastodon-tl--enable-notify-user-posts' has been set." -  (mastodon-notifications--format-note note 'status)) - -(defun mastodon-notifications--poll (note) -  "Format for a `poll' NOTE." -  (mastodon-notifications--format-note note 'poll)) - -(defun mastodon-notifications--edit (note) -  "Format for an `edit' NOTE." -  (mastodon-notifications--format-note note 'edit)) -  (defun mastodon-notifications--comment-note-text (str)    "Add comment face to all text in STR with `shr-text' face only."    (with-temp-buffer @@ -208,106 +174,173 @@ Status notifications are given when                               '(face (font-lock-comment-face shr-text)))))      (buffer-string))) +(defvar mastodon-notifications-grouped-types +  '(follow reblog favourite) +  "List of notification types for which grouping is implemented.") +  (defvar mastodon-notifications--action-alist    '((reblog . "Boosted")      (favourite . "Favourited") -    (follow-request . "Requested to follow") +    (follow_request . "Requested to follow")      (follow . "Followed")      (mention . "Mentioned")      (status . "Posted")      (poll . "Posted a poll") -    (edit . "Edited"))) - -(defun mastodon-notifications--format-note (note type) -  "Format for a NOTE of TYPE." +    (update . "Edited")) +  "Action strings keyed by notification type. +Types are those of the Mastodon API.") + +(defun mastodon-notifications--alist-by-value (str field json) +  "From JSON, return the alist whose FIELD value matches STR. +JSON is a list of alists." +  (cl-some (lambda (y) +             (when (string= str (alist-get field y)) +               y)) +           json)) + +(defun mastodon-notifications--group-accounts (ids json) +  "For IDS, return account data in JSON." +  (cl-loop +   for x in ids +   collect (mastodon-notifications--alist-by-value x 'id json))) + +(defun mastodon-notifications--format-note (group status accounts) +  "Format for a GROUP notification. +JSON is the full notifications JSON."    ;; FIXME: apply/refactor filtering as per/with `mastodon-tl--toot' -  (let* ((id (alist-get 'id note)) -         (profile-note -          (when (eq 'follow-request type) -            (let ((str (mastodon-tl--field -                        'note -                        (mastodon-tl--field 'account note)))) -              (if mastodon-notifications--profile-note-in-foll-reqs-max-length -                  (string-limit str mastodon-notifications--profile-note-in-foll-reqs-max-length) -                str)))) -         (status (mastodon-tl--field 'status note)) -         (follower (alist-get 'username (alist-get 'account note))) -         (toot (alist-get 'status note)) -         (filtered (mastodon-tl--field 'filtered toot)) -         (filters (when filtered -                    (mastodon-tl--current-filters filtered)))) -    (if (and filtered (assoc "hide" filters)) -        nil -      (mastodon-tl--insert-status -       ;; toot -       (cond ((member type '(follow follow-request)) -              ;; Using reblog with an empty id will mark this as something -              ;; non-boostable/non-favable. -              (cons '(reblog (id . nil)) note)) -             ;; reblogs/faves use 'note' to process their own json -             ;; not the toot's. this ensures following etc. work on such notifs -             ((member type '(favourite reblog)) -              note) -             (t status)) -       ;; body -       (let ((body (if-let ((match (assoc "warn" filters))) -                       (mastodon-tl--spoiler toot (cadr match)) -                     (mastodon-tl--clean-tabs-and-nl -                      (if (mastodon-tl--has-spoiler status) -                          (mastodon-tl--spoiler status) -                        (if (eq 'follow-request type) -                            (mastodon-tl--render-text profile-note) -                          (mastodon-tl--content status))))))) -         (cond ((eq type 'follow) -                (propertize "Congratulations, you have a new follower!" -                            'face 'default)) -               ((eq type 'follow-request) -                (concat -                 (propertize -                  (format "You have a follow request from... %s" -                          follower) -                  'face 'default) -                 (if mastodon-notifications--profile-note-in-foll-reqs +  (let-alist group +    ;; .sample_account_ids .status_id .notifications_count +    ;; .most_recent_notifiation_id +    (let* ((type .type) +           (type-sym (intern .type)) +           (profile-note +            (when (eq type-sym 'follow_request) +              (let ((str (mastodon-tl--field 'note (car accounts)))) +                (if mastodon-notifications--profile-note-in-foll-reqs-max-length +                    (string-limit str mastodon-notifications--profile-note-in-foll-reqs-max-length) +                  str)))) +           (follower (car .sample_account_ids)) +           (follower-name (mastodon-tl--field 'username (car accounts))) +           (filtered (mastodon-tl--field 'filtered status)) ;;toot)) +           (filters (when filtered +                      (mastodon-tl--current-filters filtered)))) +      (if (and filtered (assoc "hide" filters)) +          nil +        (mastodon-tl--insert-status +         ;; toot +         (if (member type-sym '(follow follow_request)) +             ;; Using reblog with an empty id will mark this as something +             ;; non-boostable/non-favable. +             ;; status +             (cons '(reblog (id . nil)) status) ;;note)) +           ;; reblogs/faves use 'note' to process their own json not the +           ;; toot's. this ensures following etc. work on such notifs +           status) ;; FIXME: fix following on these notifs +         ;; body +         (let ((body (if-let ((match (assoc "warn" filters))) +                         (mastodon-tl--spoiler toot (cadr match)) +                       (mastodon-tl--clean-tabs-and-nl +                        (if (mastodon-tl--has-spoiler status) +                            (mastodon-tl--spoiler status) +                          (if (eq type-sym 'follow_request) +                              (mastodon-tl--render-text profile-note) +                            (mastodon-tl--content status))))))) +           (cond ((eq type-sym 'follow) +                  (propertize "Congratulations, you have a new follower!" +                              'face 'default)) +                 ((eq type-sym 'follow_request) +                  (concat +                   (propertize +                    (format "You have a follow request from... %s" +                            follower-name) +                    'face 'default) +                   (when mastodon-notifications--profile-note-in-foll-reqs                       (concat                        ":\n" -                      (mastodon-notifications--comment-note-text body)) -                   ""))) -               ((member type '(favourite reblog)) -                (mastodon-notifications--comment-note-text body)) -               (t body))) -       ;; author-byline -       (if (member type '(follow follow-request mention)) -           'mastodon-tl--byline-author -         (lambda (_status &rest _args) ; unbreak stuff -           (mastodon-tl--byline-author note))) -       ;; action-byline -       (lambda (_status) -         (mastodon-notifications--byline-concat -          (alist-get type mastodon-notifications--action-alist))) -       id -       ;; base toot -       (when (member type '(favourite reblog)) -         status))))) - -(defun mastodon-notifications--by-type (note) +                      (mastodon-notifications--comment-note-text body))))) +                 ((member type-sym '(favourite reblog)) +                  (mastodon-notifications--comment-note-text body)) +                 (t body))) +         ;; author-byline +         (cond ((member type-sym '(favourite reblog mention)) +                (lambda (&rest _args) +                  (mastodon-notifications--byline-accounts accounts status group))) +               ((eq type-sym 'follow_request) +                (lambda (&rest _args) +                  (mastodon-tl--byline-uname-+-handle status nil (car accounts)))) +               (t #'mastodon-tl--byline-author)) +         ;; #'mastodon-tl--byline-author +         ;; action-byline +         (lambda (&rest _args) +           (mastodon-notifications--byline-concat +            (alist-get type-sym mastodon-notifications--action-alist))) +         .status_id +         ;; base toot +         (when (member type-sym '(favourite reblog)) +           status) +         nil nil nil nil +         nil group accounts))))) ;; insert status still needs our group data + +;; FIXME: REFACTOR with -tl--byline: +;; we provide account directly, rather than let-alisting toot +;; almost everything is .account.field anyway +;; but toot still needed also, for attachments, etc. +(defun mastodon-notifications--byline-accounts +    (accounts toot group &optional avatar domain) +  "Propertize author byline ACCOUNT for TOOT, the item responded to. +With arg AVATAR, include the account's avatar image. +When DOMAIN, force inclusion of user's domain in their handle." +  (let ((others-count (- (alist-get 'notifications_count group) +                         (length accounts)))) +    (concat +     (cl-loop +      for account in accounts +      concat +      (let-alist account +        (concat +         ;; avatar insertion moved up to `mastodon-tl--byline' by default to +         ;; be outside 'byline propt. +         (when (and avatar ; used by `mastodon-profile--format-user' +                    mastodon-tl--show-avatars +                    mastodon-tl--display-media-p +                    (mastodon-tl--image-trans-check)) +           (mastodon-media--get-avatar-rendering .avatar)) +         ;; username: +         (mastodon-tl--byline-username toot account) +         ;; handle: +         " (" (mastodon-tl--byline-handle toot nil account) ")" +         (if (< 1 (length accounts)) "\n" "")))) +     (if (< 0 others-count) +         (format "and %s others" others-count))))) + +(defun mastodon-notifications--by-type (groups json)    "Filter NOTE for those listed in `mastodon-notifications--types-alist'.  Call its function in that list on NOTE." -  (let* ((type (mastodon-tl--field 'type note)) -         (fun (cdr (assoc type mastodon-notifications--types-alist))) -         (start-pos (point))) -    (when fun -      (funcall fun note) -      (when mastodon-tl--display-media-p -        ;; images-in-notifs custom is handeld in -        ;; `mastodon-tl--media-attachment', not here -        (mastodon-media--inline-images start-pos (point)))))) +  (setq masto-grouped-notifs json) +  (cl-loop +   for g in groups +   for start-pos = (point) +   for accounts = (mastodon-notifications--group-accounts +                   (alist-get 'sample_account_ids g) +                   (alist-get 'accounts json)) +   for status = (mastodon-notifications--alist-by-value +                 (alist-get 'status_id g) 'id +                 (alist-get 'statuses json)) +   do (mastodon-notifications--format-note g status accounts) +   (when mastodon-tl--display-media-p +     ;; images-in-notifs custom is handeld in +     ;; `mastodon-tl--media-attachment', not here +     (mastodon-media--inline-images start-pos (point)))))  (defun mastodon-notifications--timeline (json)    "Format JSON in Emacs buffer."    (if (seq-empty-p json)        (user-error "Looks like you have no (more) notifications for now") -    (mapc #'mastodon-notifications--by-type json) -    (goto-char (point-min)))) +    (let ((groups (alist-get 'notification_groups json))) +      ;; (mapc (lambda (x) +      (mastodon-notifications--by-type groups json) +      ;; grouped) +      (goto-char (point-min)))))  (defun mastodon-notifications--get-mentions ()    "Display mention notifications in buffer."  | 
