aboutsummaryrefslogtreecommitdiff
path: root/lisp/mastodon-tl.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/mastodon-tl.el')
-rw-r--r--lisp/mastodon-tl.el256
1 files changed, 130 insertions, 126 deletions
diff --git a/lisp/mastodon-tl.el b/lisp/mastodon-tl.el
index 112b59f..1cb9863 100644
--- a/lisp/mastodon-tl.el
+++ b/lisp/mastodon-tl.el
@@ -287,13 +287,13 @@ Optionally start from POS."
(propertize (concat "@" handle)
'face 'mastodon-handle-face
'mouse-face 'highlight
- ;; TODO: Replace url browsing with native profile viewing
- 'mastodon-tab-stop 'user-handle
+ ;; TODO: Replace url browsing with native profile viewing
+ 'mastodon-tab-stop 'user-handle
'account account
- 'shr-url profile-url
- 'keymap mastodon-tl--link-keymap
+ 'shr-url profile-url
+ 'keymap mastodon-tl--link-keymap
'mastodon-handle (concat "@" handle)
- 'help-echo (concat "Browse user profile of @" handle))
+ 'help-echo (concat "Browse user profile of @" handle))
")")))
(defun mastodon-tl--byline-boosted (toot)
@@ -676,10 +676,11 @@ message is a link which unhides/hides the main body."
(if (alist-get 'remote_url media-attachement)
(alist-get 'remote_url media-attachement)
;; fallback b/c notifications don't have remote_url
- (alist-get 'url media-attachement))))
+ (alist-get 'url media-attachement)))
+ (type (alist-get 'type media-attachement)))
(if mastodon-tl--display-media-p
(mastodon-media--get-media-link-rendering
- preview-url remote-url) ; 2nd arg for shr-browse-url
+ preview-url remote-url type) ; 2nd arg for shr-browse-url
(concat "Media::" preview-url "\n"))))
media-attachements "")))
(if (not (and mastodon-tl--display-media-p
@@ -695,9 +696,9 @@ message is a link which unhides/hides the main body."
(alist-get 'poll reblog)
(alist-get 'poll toot))))
(concat
+ (mastodon-tl--render-text content toot)
(when poll-p
(mastodon-tl--get-poll toot))
- (mastodon-tl--render-text content toot)
(mastodon-tl--media toot))))
(defun mastodon-tl--insert-status (toot body author-byline action-byline)
@@ -740,16 +741,30 @@ takes a single function. By default it is
"If post TOOT is a poll, return a formatted string of poll."
(let* ((poll (mastodon-tl--field 'poll toot))
(options (mastodon-tl--field 'options poll))
+ (option-titles (mapcar (lambda (x)
+ (alist-get 'title x))
+ options))
+ (longest-option (car (sort option-titles
+ (lambda (x y)
+ (> (length x)
+ (length y))))))
(option-counter 0))
- (concat "Poll: \n\n"
+ (concat "\nPoll: \n\n"
(mapconcat (lambda (option)
(progn
- (format "Option %s: %s, %s votes.\n"
+ (format "Option %s: %s%s [%s votes].\n"
(setq option-counter (1+ option-counter))
(alist-get 'title option)
+ (make-string
+ (1+
+ (- (length longest-option)
+ (length (alist-get 'title
+ option))))
+ ?\ )
(alist-get 'votes_count option))))
options
- "\n") "\n")))
+ "\n")
+ "\n")))
(defun mastodon-tl--poll-vote (option)
"If there is a poll at point, prompt user for OPTION to vote on it."
@@ -947,149 +962,138 @@ webapp"
(alist-get 'descendants context)))))
(message "No Thread!"))))
-(defun mastodon-tl--follow-user (user-handle)
- "Query for USER-HANDLE from current status and follow that user."
+(defun mastodon-tl--follow-user (user-handle &optional notify)
+ "Query for USER-HANDLE from current status and follow that user.
+If NOTIFY is \"true\", enable notifications when that user posts.
+If NOTIFY is \"false\", disable notifications when that user posts.
+This can be called to toggle NOTIFY on users already being followed."
(interactive
(list
- (let ((user-handles (mastodon-profile--extract-users-handles
- (mastodon-profile--toot-json))))
- (completing-read "Handle of user to follow: "
- user-handles
- nil ; predicate
- 'confirm))))
- (let* ((account (mastodon-profile--lookup-account-in-status
- user-handle (mastodon-profile--toot-json)))
- (user-id (mastodon-profile--account-field account 'id))
- (name (mastodon-profile--account-field account 'display_name))
- (url (mastodon-http--api (format "accounts/%s/follow" user-id))))
- (if account
- (let ((response (mastodon-http--post url nil nil)))
- (mastodon-http--triage response
- (lambda ()
- (message "User %s (@%s) followed!" name user-handle))))
- (message "Cannot find a user with handle %S" user-handle))))
+ (mastodon-tl--interactive-user-handles-get "follow")))
+ (mastodon-tl--do-user-action-and-response user-handle "follow" nil notify))
-(defun mastodon-tl--unfollow-user (user-handle)
- "Query for USER-HANDLE from current status and unfollow that user."
+(defun mastodon-tl--enable-notify-user-posts (user-handle)
+ "Query for USER-HANDLE and enable notifications when they post."
(interactive
(list
- (let ((user-handles (mastodon-profile--extract-users-handles
- (mastodon-profile--toot-json))))
- (completing-read "Handle of user to unfollow: "
- user-handles
- nil ; predicate
- 'confirm))))
- (let* ((account (mastodon-profile--lookup-account-in-status
- user-handle (mastodon-profile--toot-json)))
- (user-id (mastodon-profile--account-field account 'id))
- (name (mastodon-profile--account-field account 'display_name))
- (url (mastodon-http--api (format "accounts/%s/unfollow" user-id))))
- (if account
- (when (y-or-n-p (format "Unfollow user %s? " name))
- (let ((response (mastodon-http--post url nil nil)))
- (mastodon-http--triage response
- (lambda ()
- (message "User %s (@%s) unfollowed!" name user-handle)))))
- (message "Cannot find a user with handle %S" user-handle))))
+ (mastodon-tl--interactive-user-handles-get "enable")))
+ (mastodon-tl--follow-user user-handle "true"))
-(defun mastodon-tl--mute-user (user-handle)
- "Query for USER-HANDLE from current status and mute that user."
+(defun mastodon-tl--disable-notify-user-posts (user-handle)
+ "Query for USER-HANDLE and disable notifications when they post."
(interactive
(list
- (let ((user-handles (mastodon-profile--extract-users-handles
- (mastodon-profile--toot-json))))
- (completing-read "Handle of user to mute: "
- user-handles
- nil ; predicate
- 'confirm))))
- (let* ((account (mastodon-profile--lookup-account-in-status
- user-handle (mastodon-profile--toot-json)))
- (user-id (mastodon-profile--account-field account 'id))
- (name (mastodon-profile--account-field account 'display_name))
- (url (mastodon-http--api (format "accounts/%s/mute" user-id))))
- (if account
- (when (y-or-n-p (format "Mute user %s? " name))
- (let ((response (mastodon-http--post url nil nil)))
- (mastodon-http--triage response
- (lambda ()
- (message "User %s (@%s) muted!" name user-handle)))))
- (message "Cannot find a user with handle %S" user-handle))))
+ (mastodon-tl--interactive-user-handles-get "disable")))
+ (mastodon-tl--follow-user user-handle "false"))
-(defun mastodon-tl--unmute-user (user-handle)
- "Query for USER-HANDLE from list of muted users and unmute that user."
+(defun mastodon-tl--unfollow-user (user-handle)
+ "Query for USER-HANDLE from current status and unfollow that user."
(interactive
(list
- (let* ((mutes-url (mastodon-http--api (format "mutes")))
- (mutes-json (mastodon-http--get-json mutes-url))
- (muted-accts (mapcar (lambda (muted)
- (alist-get 'acct muted))
- mutes-json)))
- (completing-read "Handle of user to unmute: "
- muted-accts
- nil ; predicate
- t))))
- (let* ((account (mastodon-profile--search-account-by-handle
- user-handle))
- (user-id (mastodon-profile--account-field account 'id))
- (name (mastodon-profile--account-field account 'display_name))
- (url (mastodon-http--api (format "accounts/%s/unmute" user-id))))
- (if account
- (when (y-or-n-p (format "Unmute user %s? " name))
- (let ((response (mastodon-http--post url nil nil)))
- (mastodon-http--triage response
- (lambda ()
- (message "User %s (@%s) unmuted!" name user-handle)))))
- (message "Cannot find a user with handle %S" user-handle))))
+ (mastodon-tl--interactive-user-handles-get "unfollow")))
+ (mastodon-tl--do-user-action-and-response user-handle "unfollow" t))
(defun mastodon-tl--block-user (user-handle)
"Query for USER-HANDLE from current status and block that user."
(interactive
(list
- (let ((user-handles (mastodon-profile--extract-users-handles
- (mastodon-profile--toot-json))))
- (completing-read "Handle of user to block: "
- user-handles
- nil ; predicate
- 'confirm))))
- (let* ((account (mastodon-profile--lookup-account-in-status
- user-handle (mastodon-profile--toot-json)))
- (user-id (mastodon-profile--account-field account 'id))
- (name (mastodon-profile--account-field account 'display_name))
- (url (mastodon-http--api (format "accounts/%s/block" user-id))))
- (if account
- (when (y-or-n-p (format "Block user %s? " name))
- (let ((response (mastodon-http--post url nil nil)))
- (mastodon-http--triage response
- (lambda ()
- (message "User %s (@%s) blocked!" name user-handle)))))
- (message "Cannot find a user with handle %S" user-handle))))
+ (mastodon-tl--interactive-user-handles-get "block")))
+ (mastodon-tl--do-user-action-and-response user-handle "block"))
(defun mastodon-tl--unblock-user (user-handle)
"Query for USER-HANDLE from list of blocked users and unblock that user."
(interactive
(list
- (let* ((blocks-url (mastodon-http--api (format "blocks")))
- (blocks-json (mastodon-http--get-json blocks-url))
- (blocked-accts (mapcar (lambda (blocked)
- (alist-get 'acct blocked))
- blocks-json)))
- (completing-read "Handle of user to unblock: "
- blocked-accts
+ (mastodon-tl--interactive-blocks-or-mutes-list-get "unblock")))
+ (if (not user-handle)
+ (message "Looks like you have no blocks to unblock!")
+ (mastodon-tl--do-user-action-and-response user-handle "unblock" t)))
+
+(defun mastodon-tl--mute-user (user-handle)
+ "Query for USER-HANDLE from current status and mute that user."
+ (interactive
+ (list
+ (mastodon-tl--interactive-user-handles-get "mute")))
+ (mastodon-tl--do-user-action-and-response user-handle "mute"))
+
+(defun mastodon-tl--unmute-user (user-handle)
+ "Query for USER-HANDLE from list of muted users and unmute that user."
+ (interactive
+ (list
+ (mastodon-tl--interactive-blocks-or-mutes-list-get "unmute")))
+ (if (not user-handle)
+ (message "Looks like you have no mutes to unmute!")
+ (mastodon-tl--do-user-action-and-response user-handle "unmute" t)))
+
+(defun mastodon-tl--interactive-user-handles-get (action)
+ "Get the list of user-handles for ACTION from the current toot."
+ (let ((user-handles (mastodon-profile--extract-users-handles
+ (mastodon-profile--toot-json))))
+ (completing-read (if (or (equal action "disable")
+ (equal action "enable"))
+ (format "%s notifications when user posts: " action)
+ (format "Handle of user to %s: " action))
+ user-handles
+ nil ; predicate
+ 'confirm)))
+
+(defun mastodon-tl--interactive-blocks-or-mutes-list-get (action)
+ "Fetch the list of accounts for ACTION from the server.
+Action must be either \"unblock\" or \"mute\"."
+ (let* ((endpoint (cond ((equal action "unblock")
+ "blocks")
+ ((equal action "unmute")
+ "mutes")))
+ (url (mastodon-http--api endpoint))
+ (json (mastodon-http--get-json url))
+ (accts (mapcar (lambda (user)
+ (alist-get 'acct user))
+ json)))
+ (when accts
+ (completing-read (format "Handle of user to %s: " action)
+ accts
nil ; predicate
t))))
- (let* ((account (mastodon-profile--search-account-by-handle
- user-handle))
+
+(defun mastodon-tl--do-user-action-and-response (user-handle action &optional negp notify)
+ "Do ACTION on user NAME/USER-HANDLE.
+NEGP is whether the action involves un-doing something.
+If NOTIFY is \"true\", enable notifications when that user posts.
+If NOTIFY is \"false\", disable notifications when that user posts.
+NOTIFY is only non-nil when called by `mastodon-tl--follow-user'."
+ (let* ((account (if negp
+ ;; TODO check if both are actually needed
+ (mastodon-profile--search-account-by-handle
+ user-handle)
+ (mastodon-profile--lookup-account-in-status
+ user-handle (mastodon-profile--toot-json))))
(user-id (mastodon-profile--account-field account 'id))
(name (mastodon-profile--account-field account 'display_name))
- (url (mastodon-http--api (format "accounts/%s/unblock" user-id))))
+ (url (mastodon-http--api
+ (if notify
+ (format "accounts/%s/%s?notify=%s" user-id action notify)
+ (format "accounts/%s/%s" user-id action)))))
(if account
- (when (y-or-n-p (format "Unblock user %s? " name))
- (let ((response (mastodon-http--post url nil nil)))
- (mastodon-http--triage response
- (lambda ()
- (message "User %s (@%s) unblocked!" name user-handle)))))
+ (if (equal action "follow") ; y-or-n for all but follow
+ (mastodon-tl--do-user-action-function url name user-handle action notify)
+ (when (y-or-n-p (format "%s user %s? " action name))
+ (mastodon-tl--do-user-action-function url name user-handle action)))
(message "Cannot find a user with handle %S" user-handle))))
+(defun mastodon-tl--do-user-action-function (url name user-handle action &optional notify)
+ "Post ACTION on user NAME/USER-HANDLE to URL."
+ (let ((response (mastodon-http--post url nil nil)))
+ (mastodon-http--triage response
+ (lambda ()
+ (cond ((string-equal notify "true")
+ (message "Receiving notifications for user %s (@%s)!"
+ name user-handle))
+ ((string-equal notify "false")
+ (message "Not receiving notifications for user %s (@%s)!"
+ name user-handle))
+ ((eq notify nil)
+ (message "User %s (@%s) %sed!" name user-handle action)))))))
+
;; TODO: add this to new posts in some cases, e.g. in thread view.
(defun mastodon-tl--reload-timeline-or-profile ()
"Reload the current timeline or profile page.