diff options
-rw-r--r-- | lisp/mastodon-notifications.el | 281 | ||||
-rw-r--r-- | lisp/mastodon.el | 3 |
2 files changed, 164 insertions, 120 deletions
diff --git a/lisp/mastodon-notifications.el b/lisp/mastodon-notifications.el index 0c56cbb..0e27ca0 100644 --- a/lisp/mastodon-notifications.el +++ b/lisp/mastodon-notifications.el @@ -162,39 +162,39 @@ Can be called in notifications view or in follow-requests view." (interactive) (mastodon-notifications--follow-request-process :reject)) -(defun mastodon-notifications--mention (note) +(defun mastodon-notifications--mention (group json) "Format for a `mention' NOTE." - (mastodon-notifications--format-note note 'mention)) + (mastodon-notifications--format-note group json 'mention)) -(defun mastodon-notifications--follow (note) +(defun mastodon-notifications--follow (group json) "Format for a `follow' NOTE." - (mastodon-notifications--format-note note 'follow)) + (mastodon-notifications--format-note group json 'follow)) -(defun mastodon-notifications--follow-request (note) +(defun mastodon-notifications--follow-request (group json) "Format for a `follow-request' NOTE." - (mastodon-notifications--format-note note 'follow-request)) + (mastodon-notifications--format-note group json 'follow-request)) -(defun mastodon-notifications--favourite (note) +(defun mastodon-notifications--favourite (group json) "Format for a `favourite' NOTE." - (mastodon-notifications--format-note note 'favourite)) + (mastodon-notifications--format-note group json 'favourite)) -(defun mastodon-notifications--reblog (note) +(defun mastodon-notifications--reblog (group json) "Format for a `boost' NOTE." - (mastodon-notifications--format-note note 'boost)) + (mastodon-notifications--format-note group json 'reblog)) -(defun mastodon-notifications--status (note) +(defun mastodon-notifications--status (group json) "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)) + (mastodon-notifications--format-note group json 'status)) -(defun mastodon-notifications--poll (note) +(defun mastodon-notifications--poll (group json) "Format for a `poll' NOTE." - (mastodon-notifications--format-note note 'poll)) + (mastodon-notifications--format-note group json 'poll)) -(defun mastodon-notifications--edit (note) +(defun mastodon-notifications--edit (group json) "Format for an `edit' NOTE." - (mastodon-notifications--format-note note 'edit)) + (mastodon-notifications--format-note group json 'edit)) (defun mastodon-notifications--comment-note-text (str) "Add comment face to all text in STR with `shr-text' face only." @@ -208,118 +208,161 @@ Status notifications are given when '(face (font-lock-comment-face shr-text))))) (buffer-string))) -(defun mastodon-notifications--format-note (note type) +(defvar mastodon-notifications-grouped-types + '(follow boost 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 . "Followed") + (mention . "Mentioned") + (status . "Posted") + (poll . "Posted a poll") + (edit . "Edited"))) + +(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 json type) "Format for a NOTE of TYPE." ;; 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 ((or (eq type 'follow) - (eq type '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 - ((or (eq type 'favourite) - (eq type 'boost)) - 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 ((or (eq type 'follow) - (eq type 'follow-request)) - (if (eq type 'follow) - (propertize "Congratulations, you have a new follower!" - 'face 'default) - (concat - (propertize - (format "You have a follow request from... %s" - follower) - 'face 'default) - (when mastodon-notifications--profile-note-in-foll-reqs - (concat - ":\n" - (mastodon-notifications--comment-note-text body)))))) - ((or (eq type 'favourite) - (eq type 'boost)) - (mastodon-notifications--comment-note-text body)) - (t body))) - ;; author-byline - (if (or (eq type 'follow) - (eq type 'follow-request) - (eq type 'mention)) - 'mastodon-tl--byline-author - (lambda (_status &rest _args) ; unbreak stuff - (mastodon-tl--byline-author note))) - ;; action-byline - (lambda (_status) - (mastodon-notifications--byline-concat - (cond ((eq type 'boost) - "Boosted") - ((eq type 'favourite) - "Favourited") - ((eq type 'follow-request) - "Requested to follow") - ((eq type 'follow) - "Followed") - ((eq type 'mention) - "Mentioned") - ((eq type 'status) - "Posted") - ((eq type 'poll) - "Posted a poll") - ((eq type 'edit) - "Edited")))) - id - ;; base toot - (when (or (eq type 'favourite) - (eq type 'boost)) - status))))) - -(defun mastodon-notifications--by-type (note) + ;; (if (member type mastodon-notifications-grouped-types) + (let-alist group + ;; .sample_account_ids .status_id .notifications_count + ;; .most_recent_notifiation_id + (let* ((status (mastodon-notifications--alist-by-value + .status_id 'id (alist-get 'statuses json))) + (accounts (mastodon-notifications--group-accounts + .sample_account_ids (alist-get 'accounts json)))) + (insert (symbol-name type) "\n" + "accounts: " (mapconcat 'identity .sample_account_ids ", ") "\n" + (if (not (> .notifications_count (length .sample_account_ids))) + "" + (concat + "and" + (number-to-string + (- .notifications_count + (length .sample_account_ids)))) + "others \n") + ;; "count: " (number-to-string .notifications_count) + (alist-get type mastodon-notifications--action-alist) + "\n toot: " (or .status_id "") "\n" + "\n\n")) + )) + +;; non-grouped notifs: +;; (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 ((or (eq type 'follow) +;; (eq type '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 +;; ((or (eq type 'favourite) +;; (eq type 'boost)) +;; 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 ((or (eq type 'follow) +;; (eq type 'follow-request)) +;; (if (eq type 'follow) +;; (propertize "Congratulations, you have a new follower!" +;; 'face 'default) +;; (concat +;; (propertize +;; (format "You have a follow request from... %s" +;; follower) +;; 'face 'default) +;; (when mastodon-notifications--profile-note-in-foll-reqs +;; (concat +;; ":\n" +;; (mastodon-notifications--comment-note-text body)))))) +;; ((or (eq type 'favourite) +;; (eq type 'boost)) +;; (mastodon-notifications--comment-note-text body)) +;; (t body))) +;; ;; author-byline +;; (if (or (eq type 'follow) +;; (eq type 'follow-request) +;; (eq type '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 (or (eq type 'favourite) +;; (eq type 'boost)) +;; status)))))) + +(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)))))) + (cl-loop for g in groups + for type = (alist-get 'type g) + for fun = (cdr (assoc type mastodon-notifications--types-alist)) + for start-pos = (point) + do (when fun + (funcall fun g json) + (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." diff --git a/lisp/mastodon.el b/lisp/mastodon.el index a8714f3..cc02e8a 100644 --- a/lisp/mastodon.el +++ b/lisp/mastodon.el @@ -366,7 +366,8 @@ from the server and load anew." 'mastodon-notifications--timeline type (when max-id - `(("max_id" . ,(mastodon-tl--buffer-property 'max-id))))) + `(("max_id" . ,(mastodon-tl--buffer-property 'max-id)))) + nil nil nil "v2") (with-current-buffer buffer (use-local-map mastodon-notifications--map))))) |