aboutsummaryrefslogtreecommitdiff
path: root/lisp
diff options
context:
space:
mode:
Diffstat (limited to 'lisp')
-rw-r--r--lisp/mastodon-discover.el2
-rw-r--r--lisp/mastodon-http.el123
-rw-r--r--lisp/mastodon-notifications.el32
-rw-r--r--lisp/mastodon-profile.el39
-rw-r--r--lisp/mastodon-search.el11
-rw-r--r--lisp/mastodon-tl.el157
-rw-r--r--lisp/mastodon-toot.el13
-rw-r--r--lisp/mastodon.el31
8 files changed, 212 insertions, 196 deletions
diff --git a/lisp/mastodon-discover.el b/lisp/mastodon-discover.el
index 5b8141b..08df46e 100644
--- a/lisp/mastodon-discover.el
+++ b/lisp/mastodon-discover.el
@@ -75,7 +75,7 @@
("F" "Federated" mastodon-tl--get-federated-timeline)
("H" "Home" mastodon-tl--get-home-timeline)
("L" "Local" mastodon-tl--get-local-timeline)
- ("N" "Notifications" mastodon-notifications--get)
+ ("N" "Notifications" mastodon-notifications-get)
("u" "Update timeline" mastodon-tl--update)
("S" "Search" mastodon-search--search-query)
("O" "Jump to your profile" mastodon-profile--my-profile)
diff --git a/lisp/mastodon-http.el b/lisp/mastodon-http.el
index 37770ef..69a571d 100644
--- a/lisp/mastodon-http.el
+++ b/lisp/mastodon-http.el
@@ -114,19 +114,19 @@ Unless UNAUTHENTICATED-P is non-nil."
(concat "Bearer " (mastodon-auth--access-token)))))))
,body))
-(defun mastodon-http--build-query-string (args)
- "Build a request query string from ARGS."
+(defun mastodon-http--build-params-string (params)
+ "Build a request parameters string from parameters alist PARAMS."
;; (url-build-query-string args nil))
;; url-build-query-string adds 'nil' to empty params so lets stay with our
;; own:
- (mapconcat (lambda (arg)
- (concat (url-hexify-string (car arg))
+ (mapconcat (lambda (p)
+ (concat (url-hexify-string (car p))
"="
- (url-hexify-string (cdr arg))))
- args
+ (url-hexify-string (cdr p))))
+ params
"&"))
-(defun mastodon-http--build-array-args-alist (param-str array)
+(defun mastodon-http--build-array-params-alist (param-str array)
"Return parameters alist using PARAM-STR and ARRAY param values.
Used for API form data parameters that take an array."
(cl-loop for x in array
@@ -140,7 +140,7 @@ Authorization header is included by default unless UNAUTHENTICATED-P is non-nil.
"POST"
(let ((url-request-data
(when args
- (mastodon-http--build-query-string args)))
+ (mastodon-http--build-params-string args)))
(url-request-extra-headers
(append url-request-extra-headers ; auth set in macro
;; pleroma compat:
@@ -151,27 +151,34 @@ Authorization header is included by default unless UNAUTHENTICATED-P is non-nil.
(mastodon-http--url-retrieve-synchronously url)))
unauthenticated-p))
-(defun mastodon-http--get (url &optional silent)
+(defun mastodon-http--get (url &optional params silent)
"Make synchronous GET request to URL.
-Pass response buffer to CALLBACK function.
+PARAMS is an alist of any extra parameters to send with the request.
SILENT means don't message."
(mastodon-http--authorized-request
"GET"
- (mastodon-http--url-retrieve-synchronously url silent)))
+ ;; url-request-data doesn't seem to work with GET requests:
+ (let ((url (if params
+ (concat url "?"
+ (mastodon-http--build-params-string params))
+ url)))
+ (mastodon-http--url-retrieve-synchronously url silent))))
-(defun mastodon-http--get-response (url &optional no-headers silent vector)
+(defun mastodon-http--get-response (url &optional params no-headers silent vector)
"Make synchronous GET request to URL. Return JSON and response headers.
+PARAMS is an alist of any extra parameters to send with the request.
SILENT means don't message.
NO-HEADERS means don't collect http response headers.
VECTOR means return json arrays as vectors."
- (with-current-buffer (mastodon-http--get url silent)
+ (with-current-buffer (mastodon-http--get url params silent)
(mastodon-http--process-response no-headers vector)))
-(defun mastodon-http--get-json (url &optional silent vector)
+(defun mastodon-http--get-json (url &optional params silent vector)
"Return only JSON data from URL request.
+PARAMS is an alist of any extra parameters to send with the request.
SILENT means don't message.
VECTOR means return json arrays as vectors."
- (car (mastodon-http--get-response url :no-headers silent vector)))
+ (car (mastodon-http--get-response url params :no-headers silent vector)))
(defun mastodon-http--process-json ()
"Return only JSON data from async URL request.
@@ -214,71 +221,41 @@ Callback to `mastodon-http--get-response-async', usually
(cons (car list) (cadr list))))
head-list)))
-(defun mastodon-http--delete (url &optional args)
- "Make DELETE request to URL."
- (let ((url-request-data
- (when args
- (mastodon-http--build-query-string args))))
+(defun mastodon-http--delete (url &optional params)
+ "Make DELETE request to URL.
+PARAMS is an alist of any extra parameters to send with the request."
+ ;; url-request-data only works with POST requests?
+ (let ((url
+ (if params
+ (concat url "?"
+ (mastodon-http--build-params-string params))
+ url)))
(mastodon-http--authorized-request
"DELETE"
(with-temp-buffer
(mastodon-http--url-retrieve-synchronously url)))))
-(defun mastodon-http--put (url &optional args headers)
- "Make PUT request to URL."
+(defun mastodon-http--put (url &optional params headers)
+ "Make PUT request to URL.
+PARAMS is an alist of any extra parameters to send with the request."
(mastodon-http--authorized-request
"PUT"
(let ((url-request-data
- (when args
- (mastodon-http--build-query-string args)))
+ (when args (mastodon-http--build-params-string params)))
(url-request-extra-headers
(append url-request-extra-headers ; auth set in macro
;; pleroma compat:
(unless (assoc "Content-Type" headers)
'(("Content-Type" . "application/x-www-form-urlencoded")))
headers)))
- (with-temp-buffer
- (mastodon-http--url-retrieve-synchronously url)))))
+ (with-temp-buffer (mastodon-http--url-retrieve-synchronously url)))))
(defun mastodon-http--append-query-string (url params)
"Append PARAMS to URL as query strings and return it.
-
PARAMS should be an alist as required by `url-build-query-string'."
(let ((query-string (url-build-query-string params)))
(concat url "?" query-string)))
-;; search functions:
-(defun mastodon-http--process-json-search ()
- "Process JSON returned by a search query to the server."
- (goto-char (point-min))
- (re-search-forward "^$" nil 'move)
- (let ((json-string
- (decode-coding-string
- (buffer-substring-no-properties (point) (point-max))
- 'utf-8)))
- (kill-buffer)
- (json-read-from-string json-string)))
-
-(defun mastodon-http--get-search-json (url query &optional param silent)
- "Make GET request to URL, searching for QUERY and return JSON response.
-PARAM is any extra parameters to send with the request.
-SILENT means don't message."
- (let ((buffer (mastodon-http--get-search url query param silent)))
- (with-current-buffer buffer
- (mastodon-http--process-json-search))))
-
-(defun mastodon-http--get-search (base-url query &optional param silent)
- "Make GET request to BASE-URL, searching for QUERY.
-Pass response buffer to CALLBACK function.
-PARAM is a formatted request parameter, eg 'following=true'.
-SILENT means don't message."
- (mastodon-http--authorized-request
- "GET"
- (let ((url (if param
- (concat base-url "?" param "&q=" (url-hexify-string query))
- (concat base-url "?q=" (url-hexify-string query)))))
- (mastodon-http--url-retrieve-synchronously url silent))))
-
;; profile update functions
(defun mastodon-http--patch-json (url &optional params)
@@ -294,30 +271,38 @@ Optionally specify the PARAMS to send."
"PATCH"
(let ((url
(concat base-url "?"
- (mastodon-http--build-query-string params))))
+ (mastodon-http--build-params-string params))))
(mastodon-http--url-retrieve-synchronously url))))
;; Asynchronous functions
-(defun mastodon-http--get-async (url &optional callback &rest cbargs)
+(defun mastodon-http--get-async (url &optional params callback &rest cbargs)
"Make GET request to URL.
-Pass response buffer to CALLBACK function with args CBARGS."
- (mastodon-http--authorized-request
- "GET"
- (url-retrieve url callback cbargs)))
+Pass response buffer to CALLBACK function with args CBARGS.
+PARAMS is an alist of any extra parameters to send with the request."
+ (let ((url (if params
+ (concat url "?"
+ (mastodon-http--build-params-string params))
+ url)))
+ (mastodon-http--authorized-request
+ "GET"
+ (url-retrieve url callback cbargs))))
-(defun mastodon-http--get-response-async (url callback &rest args)
+(defun mastodon-http--get-response-async (url &optional params callback &rest args)
"Make GET request to URL. Call CALLBACK with http response and ARGS."
(mastodon-http--get-async
url
+ params
(lambda (status)
(when status ;; only when we actually get sth?
(apply callback (mastodon-http--process-response) args)))))
-(defun mastodon-http--get-json-async (url callback &rest args)
- "Make GET request to URL. Call CALLBACK with json-list and ARGS."
+(defun mastodon-http--get-json-async (url &optional params callback &rest args)
+ "Make GET request to URL. Call CALLBACK with json-list and ARGS.
+PARAMS is an alist of any extra parameters to send with the request."
(mastodon-http--get-async
url
+ params
(lambda (status)
(when status ;; only when we actually get sth?
(apply callback (mastodon-http--process-json) args)))))
@@ -331,7 +316,7 @@ Authorization header is included by default unless UNAUTHENTICED-P is non-nil."
(let ((request-timeout 5)
(url-request-data
(when args
- (mastodon-http--build-query-string args))))
+ (mastodon-http--build-params-string args))))
(with-temp-buffer
(url-retrieve url callback cbargs)))))
diff --git a/lisp/mastodon-notifications.el b/lisp/mastodon-notifications.el
index f9e2fe5..f5ddea3 100644
--- a/lisp/mastodon-notifications.el
+++ b/lisp/mastodon-notifications.el
@@ -51,6 +51,7 @@
(autoload 'mastodon-profile--view-follow-requests "mastodon-profile.el")
(autoload 'mastodon-tl--reload-timeline-or-profile "mastodon-tl")
(autoload 'mastodon-tl--update "mastodon-tl")
+(autoload 'mastodon-notifications-get "mastodon")
(defvar mastodon-tl--buffer-spec)
(defvar mastodon-tl--display-media-p)
(defvar mastodon-mode-map)
@@ -124,7 +125,7 @@ follow-requests view."
(lambda ()
(if f-reqs-view-p
(mastodon-profile--view-follow-requests)
- (mastodon-notifications--get))
+ (mastodon-notifications-get))
(message "Follow request of %s (@%s) %s!"
name handle (if reject
"rejected"
@@ -276,51 +277,32 @@ of the toot responded to."
(mapc #'mastodon-notifications--by-type json)
(goto-char (point-min))))
-;;;###autoload
-(defun mastodon-notifications--get (&optional type buffer-name)
- "Display NOTIFICATIONS in buffer.
-Optionally only print notifications of type TYPE, a string.
-BUFFER-NAME is added to \"*mastodon-\" to create the buffer name."
- (interactive)
- (let ((buffer (or (concat "*mastodon-" buffer-name "*")
- "*mastodon-notifications*")))
- (if (get-buffer buffer)
- (progn (switch-to-buffer buffer)
- (mastodon-tl--update))
- (message "Loading your notifications...")
- (mastodon-tl--init-sync
- (or buffer-name "notifications")
- "notifications"
- 'mastodon-notifications--timeline
- type)
- (use-local-map mastodon-notifications--map))))
-
(defun mastodon-notifications--get-mentions ()
"Display mention notifications in buffer."
(interactive)
- (mastodon-notifications--get "mention" "mentions"))
+ (mastodon-notifications-get "mention" "mentions"))
(defun mastodon-notifications--get-favourites ()
"Display favourite notifications in buffer."
(interactive)
- (mastodon-notifications--get "favourite" "favourites"))
+ (mastodon-notifications-get "favourite" "favourites"))
(defun mastodon-notifications--get-boosts ()
"Display boost notifications in buffer."
(interactive)
- (mastodon-notifications--get "reblog" "boosts"))
+ (mastodon-notifications-get "reblog" "boosts"))
(defun mastodon-notifications--get-polls ()
"Display poll notifications in buffer."
(interactive)
- (mastodon-notifications--get "poll" "polls"))
+ (mastodon-notifications-get "poll" "polls"))
(defun mastodon-notifications--get-statuses ()
"Display status notifications in buffer.
Status notifications are created when you call
`mastodon-tl--enable-notify-user-posts'."
(interactive)
- (mastodon-notifications--get "status" "statuses"))
+ (mastodon-notifications-get "status" "statuses"))
(defun mastodon-notifications--filter-types-list (type)
"Return a list of notification types with TYPE removed."
diff --git a/lisp/mastodon-profile.el b/lisp/mastodon-profile.el
index 3a869ed..69cd65d 100644
--- a/lisp/mastodon-profile.el
+++ b/lisp/mastodon-profile.el
@@ -36,6 +36,7 @@
(require 'seq)
(require 'cl-lib)
(require 'persist)
+(require 'ts)
(autoload 'mastodon-http--api "mastodon-http.el")
(autoload 'mastodon-http--get-json "mastodon-http.el")
@@ -69,6 +70,8 @@
(autoload 'mastodon-search--insert-users-propertized "mastodon-search")
(autoload 'mastodon-tl--get-endpoint "mastodon-tl.el")
(autoload 'mastodon-toot--get-max-toot-chars "mastodon-toot")
+(autoload 'mastodon-tl--add-account-to-list "mastodon-tl")
+
(defvar mastodon-instance-url)
(defvar mastodon-tl--buffer-spec)
(defvar mastodon-tl--update-point)
@@ -243,6 +246,15 @@ JSON is the data returned by the server."
(mastodon-search--insert-users-propertized json :note)))
;; (mastodon-profile--add-author-bylines json)))
+(defun mastodon-profile--add-account-to-list ()
+ "Add account of current profile buffer to a list."
+ (interactive)
+ (when mastodon-profile--account
+ (let* ((profile mastodon-profile--account)
+ (id (alist-get 'id profile))
+ (handle (alist-get 'acct profile)))
+ (mastodon-tl--add-account-to-list nil id handle))))
+
;;; ACCOUNT PREFERENCES
(defun mastodon-profile--get-json-value (val)
@@ -492,11 +504,10 @@ This endpoint only holds a few preferences. For others, see
(defun mastodon-profile--relationships-get (id)
"Fetch info about logged-in user's relationship to user with id ID."
(let* ((their-id id)
- (url (mastodon-http--api (format
- "accounts/relationships?id[]=%s"
- their-id))))
+ (args `(("id[]" . ,their-id)))
+ (url (mastodon-http--api "accounts/relationships")))
;; FIXME: not sure why we need to do this for relationships only!
- (car (mastodon-http--get-json url))))
+ (car (mastodon-http--get-json url args))))
(defun mastodon-profile--fields-get (&optional account fields)
"Fetch the fields vector (aka profile metadata) from profile of ACCOUNT.
@@ -527,8 +538,9 @@ FIELDS means provide a fields vector fetched by other means."
(defun mastodon-profile--get-statuses-pinned (account)
"Fetch the pinned toots for ACCOUNT."
(let* ((id (mastodon-profile--account-field account 'id))
- (url (mastodon-http--api (format "accounts/%s/statuses?pinned=true" id))))
- (mastodon-http--get-json url)))
+ (args `(("pinned" . "true")))
+ (url (mastodon-http--api (format "accounts/%s/statuses" id))))
+ (mastodon-http--get-json url args)))
(defun mastodon-profile--insert-statuses-pinned (pinned-statuses)
"Insert each of the PINNED-STATUSES for a given account."
@@ -538,18 +550,17 @@ FIELDS means provide a fields vector fetched by other means."
(mastodon-tl--toot pinned-status))
pinned-statuses))
-(defun mastodon-profile--make-profile-buffer-for (account endpoint-type update-function &optional no-reblogs)
+(defun mastodon-profile--make-profile-buffer-for (account endpoint-type
+ update-function
+ &optional no-reblogs)
"Display profile of ACCOUNT, using ENDPOINT-TYPE and UPDATE-FUNCTION."
(let* ((id (mastodon-profile--account-field account 'id))
(args (when no-reblogs '(("exclude_reblogs" . "t"))))
- (base-url (mastodon-http--api (format "accounts/%s/%s" id endpoint-type)))
- (url (if no-reblogs
- (concat base-url "?" (mastodon-http--build-query-string args))
- base-url))
+ (url (mastodon-http--api (format "accounts/%s/%s" id endpoint-type)))
(acct (mastodon-profile--account-field account 'acct))
(buffer (concat "*mastodon-" acct "-" endpoint-type "*"))
(note (mastodon-profile--account-field account 'note))
- (json (mastodon-http--get-json url))
+ (json (mastodon-http--get-json url args))
(locked (mastodon-profile--account-field account 'locked))
(followers-count (mastodon-tl--as-string
(mastodon-profile--account-field
@@ -754,12 +765,14 @@ If the handle does not match a search return then retun NIL."
(let* ((handle (if (string= "@" (substring handle 0 1))
(substring handle 1 (length handle))
handle))
+ (args `(("q" . ,handle)))
(matching-account
(seq-remove
(lambda (x)
(not (string= (alist-get 'acct x) handle)))
(mastodon-http--get-json
- (mastodon-http--api (format "accounts/search?q=%s" handle))))))
+ (mastodon-http--api "accounts/search")
+ args))))
(when (equal 1 (length matching-account))
(elt matching-account 0))))
diff --git a/lisp/mastodon-search.el b/lisp/mastodon-search.el
index 8530b5c..7ff8b07 100644
--- a/lisp/mastodon-search.el
+++ b/lisp/mastodon-search.el
@@ -67,8 +67,8 @@ Returns a nested list containing user handle, display name, and URL."
(interactive "sSearch mastodon for: ")
(let* ((url (mastodon-http--api "accounts/search"))
(response (if (equal mastodon-toot--completion-style-for-mentions "following")
- (mastodon-http--get-search-json url query "following=true" :silent)
- (mastodon-http--get-search-json url query nil :silent))))
+ (mastodon-http--get-json url `(("q" . ,query) ("following" . "true")) :silent)
+ (mastodon-http--get-json url `(("q" . ,query)) :silent))))
(if capf
(mapcar #'mastodon-search--get-user-info-@-capf response)
(mapcar #'mastodon-search--get-user-info-@ response))))
@@ -80,8 +80,9 @@ Returns a nested list containing user handle, display name, and URL."
QUERY is the string to search."
(interactive "sSearch for hashtag: ")
(let* ((url (format "%s/api/v2/search" mastodon-instance-url))
- (type-param (concat "type=hashtags"))
- (response (mastodon-http--get-search-json url query type-param :silent))
+ (params `(("q" . ,query)
+ ("type" . "hashtags")))
+ (response (mastodon-http--get-json url params :silent))
(tags (alist-get 'hashtags response)))
(mapcar #'mastodon-search--get-hashtag-info tags)))
@@ -120,7 +121,7 @@ QUERY is the string to search."
(interactive "sSearch mastodon for: ")
(let* ((url (format "%s/api/v2/search" mastodon-instance-url))
(buffer (format "*mastodon-search-%s*" query))
- (response (mastodon-http--get-search-json url query))
+ (response (mastodon-http--get-json url `(("q" . ,query))))
(accts (alist-get 'accounts response))
(tags (alist-get 'hashtags response))
(statuses (alist-get 'statuses response))
diff --git a/lisp/mastodon-tl.el b/lisp/mastodon-tl.el
index 027b7e8..e65d3a5 100644
--- a/lisp/mastodon-tl.el
+++ b/lisp/mastodon-tl.el
@@ -61,7 +61,7 @@
(autoload 'mastodon-profile--lookup-account-in-status "mastodon-profile")
(autoload 'mastodon-profile-mode "mastodon-profile")
;; make notifications--get available via M-x and outside our keymap:
-(autoload 'mastodon-notifications--get "mastodon-notifications"
+(autoload 'mastodon-notifications-get "mastodon-notifications"
"Display NOTIFICATIONS in buffer." t) ; interactive
(autoload 'mastodon-search--propertize-user "mastodon-search")
(autoload 'mastodon-search--insert-users-propertized "mastodon-search")
@@ -74,9 +74,10 @@
(autoload 'mastodon-auth--get-account-id "mastodon-auth")
(autoload 'mastodon-http--put "mastodon-http")
(autoload 'mastodon-http--process-json "mastodon-http")
-(autoload 'mastodon-http--build-array-args-alist "mastodon-http")
-(autoload 'mastodon-http--build-query-string "mastodon-http")
+(autoload 'mastodon-http--build-array-params-alist "mastodon-http")
+(autoload 'mastodon-http--build-params-string "mastodon-http")
(autoload 'mastodon-notifications--filter-types-list "mastodon-notifications")
+(autoload 'mastodon-toot--get-toot-edits "mastodon-toot")
(when (require 'mpv nil :no-error)
(declare-function mpv-start "mpv"))
@@ -498,7 +499,7 @@ The result is added as an attachments property to author-byline."
(let ((reblog (alist-get 'reblog toot)))
(when reblog
(concat
- "\n "
+ "\n "
(propertize "Boosted" 'face 'mastodon-boosted-face)
" "
(mastodon-tl--byline-author reblog)))))
@@ -599,9 +600,6 @@ this just means displaying toot client."
(faved (equal 't (mastodon-tl--field 'favourited toot)))
(boosted (equal 't (mastodon-tl--field 'reblogged toot)))
(bookmarked (equal 't (mastodon-tl--field 'bookmarked toot)))
- (bookmark-str (if (fontp (char-displayable-p #10r128278))
- "🔖"
- "K"))
(visibility (mastodon-tl--field 'visibility toot))
(account (alist-get 'account toot))
(avatar-url (alist-get 'avatar account))
@@ -616,11 +614,14 @@ this just means displaying toot client."
;; displayed for an already boosted/favourited toot or as the result of
;; the toot having just been favourited/boosted.
(concat (when boosted
- (mastodon-tl--format-faved-or-boosted-byline "B"))
+ (mastodon-tl--format-faved-or-boosted-byline
+ (mastodon-tl--return-boost-char)))
(when faved
- (mastodon-tl--format-faved-or-boosted-byline "F"))
+ (mastodon-tl--format-faved-or-boosted-byline
+ (mastodon-tl--return-fave-char)))
(when bookmarked
- (mastodon-tl--format-faved-or-boosted-byline bookmark-str)))
+ (mastodon-tl--format-faved-or-boosted-byline
+ (mastodon-tl--return-bookmark-char))))
;; we remove avatars from the byline also, so that they also do not mess
;; with `mastodon-tl--goto-next-toot':
(when (and mastodon-tl--show-avatars
@@ -669,20 +670,21 @@ this just means displaying toot client."
'shr-url app-url
'help-echo app-url
'keymap mastodon-tl--shr-map-replacement)))))
- (when edited-time
- (concat
- (if (fontp (char-displayable-p #10r128274))
- " ✍ "
- " [edited] ")
- (propertize
- (format-time-string mastodon-toot-timestamp-format
- edited-parsed)
- 'face 'font-lock-comment-face
- 'timestamp edited-parsed
- 'display (if mastodon-tl--enable-relative-timestamps
- (mastodon-tl--relative-time-description edited-parsed)
- edited-parsed))))
- (propertize "\n ------------\n" 'face 'default))
+ (if edited-time
+ (concat
+ (if (fontp (char-displayable-p #10r128274))
+ " ✍ "
+ " [edited] ")
+ (propertize
+ (format-time-string mastodon-toot-timestamp-format
+ edited-parsed)
+ 'face 'font-lock-comment-face
+ 'timestamp edited-parsed
+ 'display (if mastodon-tl--enable-relative-timestamps
+ (mastodon-tl--relative-time-description edited-parsed)
+ edited-parsed)))
+ "")
+ (propertize "\n ------------\n " 'face 'default))
'favourited-p faved
'boosted-p boosted
'bookmarked-p bookmarked
@@ -691,6 +693,30 @@ this just means displaying toot client."
(mastodon-toot--get-toot-edits (alist-get 'id toot)))
'byline t))))
+(defun mastodon-tl--return-boost-char ()
+ ""
+ (cond
+ ((fontp (char-displayable-p #10r128257))
+ "🔁")
+ (t
+ "B")))
+
+(defun mastodon-tl--return-fave-char ()
+ ""
+ (cond
+ ((fontp (char-displayable-p #10r11088))
+ "⭐")
+ ((fontp (char-displayable-p #10r9733))
+ "★")
+ (t
+ "F")))
+
+(defun mastodon-tl--return-bookmark-char ()
+ ""
+ (if (fontp (char-displayable-p #10r128278))
+ "🔖"
+ "K"))
+
(defun mastodon-tl--format-edit-timestamp (timestamp)
"Convert edit TIMESTAMP into a descriptive string."
(let ((parsed (ts-human-duration
@@ -1305,39 +1331,24 @@ LINK-HEADER is the http Link header if present."
(defun mastodon-tl--more-json (endpoint id)
"Return JSON for timeline ENDPOINT before ID."
- (let* ((url (mastodon-http--api (concat
- endpoint
- (if (string-match-p "?" endpoint)
- "&"
- "?")
- "max_id="
- (mastodon-tl--as-string id)))))
- (mastodon-http--get-json url)))
+ (let* ((args `(("max_id" . ,(mastodon-tl--as-string id))))
+ (url (mastodon-http--api endpoint)))
+ (mastodon-http--get-json url args)))
(defun mastodon-tl--more-json-async (endpoint id callback &rest cbargs)
"Return JSON for timeline ENDPOINT before ID.
Then run CALLBACK with arguments CBARGS."
- (let* ((url (mastodon-http--api (concat
- endpoint
- (if (string-match-p "?" endpoint)
- "&"
- "?")
- "max_id="
- (mastodon-tl--as-string id)))))
- (apply 'mastodon-http--get-json-async url callback cbargs)))
+ (let* ((args `(("max_id" . ,(mastodon-tl--as-string id))))
+ (url (mastodon-http--api endpoint)))
+ (apply 'mastodon-http--get-json-async url args callback cbargs)))
;; TODO
;; Look into the JSON returned here by Local
(defun mastodon-tl--updated-json (endpoint id)
"Return JSON for timeline ENDPOINT since ID."
- (let ((url (mastodon-http--api (concat
- endpoint
- (if (string-match-p "?" endpoint)
- "&"
- "?")
- "since_id="
- (mastodon-tl--as-string id)))))
- (mastodon-http--get-json url)))
+ (let* ((args `(("since_id" . ,(mastodon-tl--as-string id))))
+ (url (mastodon-http--api endpoint)))
+ (mastodon-http--get-json url args)))
(defun mastodon-tl--property (prop &optional backward)
"Get property PROP for toot at point.
@@ -1417,8 +1428,9 @@ ID is that of the toot to view."
;; refetch current toot in case we just faved/boosted:
(mastodon-http--get-json
(mastodon-http--api (concat "statuses/" id))
+ nil
:silent))
- (context (mastodon-http--get-json url :silent))
+ (context (mastodon-http--get-json url nil :silent))
(marker (make-marker)))
(if (equal (caar toot) 'error)
(message "Error: %s" (cdar toot))
@@ -1643,9 +1655,10 @@ a: add account to this list, r: remove account from this list"
(let ((id (get-text-property (point) 'list-id)))
(mastodon-tl--add-account-to-list id)))
-(defun mastodon-tl--add-account-to-list (&optional id)
+(defun mastodon-tl--add-account-to-list (&optional id account-id handle)
"Prompt for a list and for an account, add account to list.
-If ID is provided, use that list."
+If ID is provided, use that list.
+If ACCOUNT-ID and HANDLE are provided use them rather than prompting."
(interactive)
(let* ((list-name (if id
(get-text-property (point) 'list-name)
@@ -1657,9 +1670,9 @@ If ID is provided, use that list."
(cons (alist-get 'acct x)
(alist-get 'id x)))
followings))
- (account (completing-read "Account to add: "
- handles nil t))
- (account-id (alist-get account handles nil nil 'equal))
+ (account (or handle (completing-read "Account to add: "
+ handles nil t)))
+ (account-id (or account-id (alist-get account handles nil nil 'equal)))
(url (mastodon-http--api (format "lists/%s/accounts" list-id)))
(response (mastodon-http--post url
`(("account_ids[]" . ,account-id)))))
@@ -1690,13 +1703,9 @@ If ID is provided, use that list."
(account (completing-read "Account to remove: "
handles nil t))
(account-id (alist-get account handles nil nil 'equal))
- ;; letting --delete handle the params doesn't work
- ;; so we do it here for now:
- (base-url (mastodon-http--api (format "lists/%s/accounts" list-id)))
- (args (mastodon-http--build-array-args-alist "account_ids[]" `(,account-id)))
- (query-str (mastodon-http--build-query-string args))
- (url (concat base-url "?" query-str))
- (response (mastodon-http--delete url)))
+ (url (mastodon-http--api (format "lists/%s/accounts" list-id)))
+ (args (mastodon-http--build-array-params-alist "account_ids[]" `(,account-id)))
+ (response (mastodon-http--delete url args)))
(mastodon-tl--list-action-triage
response
(message "%s removed from list %s!" account list-name))))
@@ -1890,9 +1899,9 @@ INSTANCE is an instance domain name."
(response (mastodon-http--get-json
(if user
(mastodon-http--api "instance")
- (concat instance
- "/api/v1/instance"))
- nil
+ (concat instance "/api/v1/instance"))
+ nil ; params
+ nil ; silent
:vector)))
(when response
(let ((buf (get-buffer-create "*mastodon-instance*")))
@@ -2250,7 +2259,7 @@ For use after e.g. deleting a toot."
((equal (mastodon-tl--get-endpoint) "timelines/public?local=true")
(mastodon-tl--get-local-timeline))
((equal (mastodon-tl--get-endpoint) "notifications")
- (mastodon-notifications--get))
+ (mastodon-notifications-get))
((equal (mastodon-tl--buffer-name)
(concat "*mastodon-" (mastodon-auth--get-account-name) "-statuses*"))
(mastodon-profile--my-profile))
@@ -2275,9 +2284,9 @@ For use after e.g. deleting a toot."
(if (member (buffer-name (current-buffer)) mastodon-tl--link-header-buffers)
;; link-header: can't build a URL with --more-json-async, endpoint/id:
(let* ((next (car (mastodon-tl--link-header)))
- ;(prev (cadr (mastodon-tl--link-header)))
+ ;;(prev (cadr (mastodon-tl--link-header)))
(url (mastodon-tl--build-link-header-url next)))
- (mastodon-http--get-response-async url 'mastodon-tl--more* (current-buffer)
+ (mastodon-http--get-response-async url nil 'mastodon-tl--more* (current-buffer)
(point) :headers))
(mastodon-tl--more-json-async (mastodon-tl--get-endpoint) (mastodon-tl--oldest-id)
'mastodon-tl--more* (current-buffer) (point))))
@@ -2478,9 +2487,9 @@ favourites."
(buffer (concat "*mastodon-" buffer-name "*")))
(if headers
(mastodon-http--get-response-async
- url 'mastodon-tl--init* buffer endpoint update-function headers)
+ url nil 'mastodon-tl--init* buffer endpoint update-function headers)
(mastodon-http--get-json-async
- url 'mastodon-tl--init* buffer endpoint update-function))))
+ url nil 'mastodon-tl--init* buffer endpoint update-function))))
(defun mastodon-tl--init* (response buffer endpoint update-function &optional headers)
"Initialize BUFFER with timeline targeted by ENDPOINT.
@@ -2534,16 +2543,16 @@ Runs synchronously.
Optional arg NOTE-TYPE means only get that type of note."
(let* ((exclude-types (when note-type
(mastodon-notifications--filter-types-list note-type)))
- (args (when note-type (mastodon-http--build-array-args-alist
+ (args (when note-type (mastodon-http--build-array-params-alist
"exclude_types[]" exclude-types)))
- (query-string (when note-type
- (mastodon-http--build-query-string args)))
+ ;; (query-string (when note-type
+ ;; (mastodon-http--build-params-string args)))
;; add note-type exclusions to endpoint so it works in `mastodon-tl--buffer-spec'
;; that way `mastodon-tl--more' works seamlessly too:
- (endpoint (if note-type (concat endpoint "?" query-string) endpoint))
+ ;; (endpoint (if note-type (concat endpoint "?" query-string) endpoint))
(url (mastodon-http--api endpoint))
(buffer (concat "*mastodon-" buffer-name "*"))
- (json (mastodon-http--get-json url)))
+ (json (mastodon-http--get-json url args)))
(with-output-to-temp-buffer buffer
(switch-to-buffer buffer)
;; mastodon-mode wipes buffer-spec, so order must unforch be:
diff --git a/lisp/mastodon-toot.el b/lisp/mastodon-toot.el
index 6855280..8e6f4df 100644
--- a/lisp/mastodon-toot.el
+++ b/lisp/mastodon-toot.el
@@ -81,7 +81,7 @@
(autoload 'mastodon-profile--fetch-server-account-settings "mastodon-profile")
(autoload 'mastodon-tl--render-text "mastodon-tl")
(autoload 'mastodon-profile--fetch-server-account-settings-maybe "mastodon-profile")
-(autoload 'mastodon-http--build-array-args-alist "mastodon-http")
+(autoload 'mastodon-http--build-array-params-alist "mastodon-http")
(autoload 'mastodon-tl--get-endpoint "mastodon-tl")
(autoload 'mastodon-http--put "mastodon-http")
@@ -253,6 +253,7 @@ send.")
NO-TOOT means we are not calling from a toot buffer."
(mastodon-http--get-json-async
(mastodon-http--api "instance")
+ nil
'mastodon-toot--get-max-toot-chars-callback no-toot))
(defun mastodon-toot--get-max-toot-chars-callback (json-response
@@ -352,7 +353,9 @@ TYPE is a symbol, either 'favourite or 'boost."
(list 'boosted-p (not boosted))
(list 'favourited-p (not faved))))
(mastodon-toot--action-success
- (if boost-p "B" "F")
+ (if boost-p
+ (mastodon-tl--return-boost-char)
+ (mastodon-tl--return-fave-char))
byline-region remove))
(message (format "%s #%s" (if boost-p msg action) id))))))
(message (format "Nothing to %s here?!?" action-string)))))
@@ -662,7 +665,7 @@ to `emojify-user-emojis', and the emoji data is updated."
(defun mastodon-toot--build-poll-params ()
"Return an alist of parameters for POSTing a poll status."
(append
- (mastodon-http--build-array-args-alist
+ (mastodon-http--build-array-params-alist
"poll[options][]"
(plist-get mastodon-toot-poll :options))
`(("poll[expires_in]" . ,(plist-get mastodon-toot-poll :expiry)))
@@ -696,7 +699,7 @@ instance to edit a toot."
("spoiler_text" . ,spoiler)
("language" . ,mastodon-toot--language)))
(args-media (when mastodon-toot--media-attachments
- (mastodon-http--build-array-args-alist
+ (mastodon-http--build-array-params-alist
"media_ids[]"
mastodon-toot--media-attachment-ids)))
(args-poll (when mastodon-toot-poll
@@ -761,7 +764,7 @@ instance to edit a toot."
(defun mastodon-toot--get-toot-source (id)
"Fetch the source JSON of toot with ID."
(let ((url (mastodon-http--api (format "/statuses/%s/source" id))))
- (mastodon-http--get-json url :silent)))
+ (mastodon-http--get-json url nil :silent)))
(defun mastodon-toot--get-toot-edits (id)
"Return the edit history of toot with ID."
diff --git a/lisp/mastodon.el b/lisp/mastodon.el
index d8591e1..921e3af 100644
--- a/lisp/mastodon.el
+++ b/lisp/mastodon.el
@@ -57,7 +57,6 @@
(autoload 'mastodon-tl--thread "mastodon-tl")
(autoload 'mastodon-tl--toggle-spoiler-text-in-toot "mastodon-tl")
(autoload 'mastodon-tl--update "mastodon-tl")
-(autoload 'mastodon-notifications--get "mastodon-notifications")
(autoload 'mastodon-profile--get-toot-author "mastodon-profile")
(autoload 'mastodon-profile--make-author-buffer "mastodon-profile")
(autoload 'mastodon-profile--show-user "mastodon-profile")
@@ -96,6 +95,10 @@
(autoload 'mastodon-tl--view-lists "mastodon-tl")
(autoload 'mastodon-toot--edit-toot-at-point "mastodon-toot")
(autoload 'mastodon-toot--view-toot-history "mastodon-tl")
+(autoload 'mastodon-tl--init-sync "mastodon-tl")
+(autoload 'mastodon-notifications--timeline "mastodon-notifications")
+
+(defvar mastodon-notifications--map)
(defgroup mastodon nil
"Interface with Mastodon."
@@ -160,7 +163,7 @@ Use. e.g. \"%c\" for your locale's date and time format."
(define-key map (kbd "F") #'mastodon-tl--get-federated-timeline)
(define-key map (kbd "H") #'mastodon-tl--get-home-timeline)
(define-key map (kbd "L") #'mastodon-tl--get-local-timeline)
- (define-key map (kbd "N") #'mastodon-notifications--get)
+ (define-key map (kbd "N") #'mastodon-notifications-get)
(define-key map (kbd "P") #'mastodon-profile--show-user)
(define-key map (kbd "T") #'mastodon-tl--thread)
;; navigation out of mastodon
@@ -268,6 +271,25 @@ If REPLY-JSON is the json of the toot being replied to."
(interactive)
(mastodon-toot--compose-buffer user reply-to-id reply-json))
+;;;###autoload
+(defun mastodon-notifications-get (&optional type buffer-name)
+ "Display NOTIFICATIONS in buffer.
+Optionally only print notifications of type TYPE, a string.
+BUFFER-NAME is added to \"*mastodon-\" to create the buffer name."
+ (interactive)
+ (let ((buffer (or (concat "*mastodon-" buffer-name "*")
+ "*mastodon-notifications*")))
+ (if (get-buffer buffer)
+ (progn (switch-to-buffer buffer)
+ (mastodon-tl--update))
+ (message "Loading your notifications...")
+ (mastodon-tl--init-sync
+ (or buffer-name "notifications")
+ "notifications"
+ 'mastodon-notifications--timeline
+ type)
+ (use-local-map mastodon-notifications--map))))
+
;; URL lookup: should be available even if `mastodon.el' not loaded:
;;;###autoload
@@ -291,8 +313,9 @@ not, just browse the URL in the normal fashion."
(browse-url query)
(message "Performing lookup...")
(let* ((url (format "%s/api/v2/search" mastodon-instance-url))
- (param (concat "resolve=t")) ; webfinger
- (response (mastodon-http--get-search-json url query param :silent)))
+ (params `(("q" . ,query)
+ ("resolve" . "t"))) ; webfinger
+ (response (mastodon-http--get-json url params :silent)))
(cond ((not (seq-empty-p
(alist-get 'statuses response)))
(let* ((statuses (assoc 'statuses response))