aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.org133
-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
-rw-r--r--test/mastodon-notifications-tests.el8
-rw-r--r--test/mastodon-profile-tests.el11
-rw-r--r--test/mastodon-tl-tests.el45
12 files changed, 321 insertions, 284 deletions
diff --git a/README.org b/README.org
index 97e2f4f..bacab59 100644
--- a/README.org
+++ b/README.org
@@ -6,7 +6,7 @@
* README
-=mastodon.el= is an Emacs client for the Mastodon and Pleroma social networks. For info see https://joinmastodon.org/.
+=mastodon.el= is an Emacs client for the AcitivityPub social networks that implement the Mastodon API. For info see https://joinmastodon.org/.
** Installation
@@ -107,65 +107,69 @@ take place if your =mastodon-token-file= does not contain =:client_id= and
**** Keybindings
-|---------------+-----------------------------------------------------------------------|
-| Key | Action |
-|---------------+-----------------------------------------------------------------------|
-| | *Help* |
-| =?= | Open context menu if =discover= is available |
-|---------------+-----------------------------------------------------------------------|
-| | *Timeline actions* |
-| =n= | Go to next item (toot, notification) |
-| =p= | Go to previous item (toot, notification) |
-| =M-n=/=<tab>= | Go to the next interesting thing that has an action |
-| =M-p=/=<S-tab>= | Go to the previous interesting thing that has an action |
-| =F= | Open federated timeline |
-| =H= | Open home timeline |
-| =L= | Open local timeline |
-| =N= | Open notifications timeline |
-| =@= | Open mentions-only notifications timeline |
-| =u= | Update current timeline |
-| =T= | Open thread for toot under =point= |
-| =#= | Prompt for tag and open its timeline |
-| =A= | Open author profile of toot under =point= |
-| =P= | Open profile of user attached to toot under =point= |
-| =O= | View own profile |
-| =U= | update your profile bio note |
-|---------------+-----------------------------------------------------------------------|
-| | *Other views* |
-| =S= | search (posts, users, tags) (NB: only posts you have interacted with) |
-| =I=, =c=, =d= | view, create, and delete filters |
-| =R=, =a=, =j= | view/accept/reject follow requests |
-| =G= | view follow suggestions |
-| =V= | view your favourited toots |
-| =K= | view bookmarked toots |
-| =X= | view/edit/create/delete lists |
-|---------------+-----------------------------------------------------------------------|
-| | *Toot actions* |
-| =t= | Compose a new toot |
-| =c= | Toggle content warning content |
-| =b= | Boost toot under =point= |
-| =f= | Favourite toot under =point= |
-| =k= | toggle bookmark of toot at point |
-| =r= | Reply to toot under =point= |
-| =v= | Vote on poll at point |
-| =C= | copy url of toot at point |
-| =C-RET= | play video/gif at point (requires =mpv=) |
-| =e= | edit your toot at point |
-| =E= | view edits of toot at point |
-| =i= | (un)pin your toot at point |
-| =d= | delete your toot at point, and reload current timeline |
-| =D= | delete and redraft toot at point, preserving reply/CW/visibility |
+|----------------+-----------------------------------------------------------------------|
+| Key | Action |
+|----------------+-----------------------------------------------------------------------|
+| | *Help* |
+| =?= | Open context menu if =discover= is available |
+|----------------+-----------------------------------------------------------------------|
+| | *Timeline actions* |
+| =n= | Go to next item (toot, notification) |
+| =p= | Go to previous item (toot, notification) |
+| =M-n=/=<tab>= | Go to the next interesting thing that has an action |
+| =M-p=/=<S-tab>= | Go to the previous interesting thing that has an action |
+| =F= | Open federated timeline |
+| =H= | Open home timeline |
+| =L= | Open local timeline |
+| =N= | Open notifications timeline |
+| =@= | Open mentions-only notifications timeline |
+| =u= | Update current timeline |
+| =T= | Open thread for toot under =point= |
+| =#= | Prompt for tag and open its timeline |
+| =A= | Open author profile of toot under =point= |
+| =P= | Open profile of user attached to toot under =point= |
+| =O= | View own profile |
+| =U= | update your profile bio note |
+|----------------+-----------------------------------------------------------------------|
+| | *Other views* |
+| =S= | search (posts, users, tags) (NB: only posts you have interacted with) |
+| =I=, =c=, =d= | view, create, and delete filters |
+| =R=, =a=, =j= | view/accept/reject follow requests |
+| =G= | view follow suggestions |
+| =V= | view your favourited toots |
+| =K= | view bookmarked toots |
+| =X= | view/edit/create/delete lists |
+|----------------+-----------------------------------------------------------------------|
+| | *Toot actions* |
+| =t= | Compose a new toot |
+| =c= | Toggle content warning content |
+| =b= | Boost toot under =point= |
+| =f= | Favourite toot under =point= |
+| =k= | toggle bookmark of toot at point |
+| =r= | Reply to toot under =point= |
+| =v= | Vote on poll at point |
+| =C= | copy url of toot at point |
+| =C-RET= | play video/gif at point (requires =mpv=) |
+| =e= | edit your toot at point |
+| =E= | view edits of toot at point |
+| =i= | (un)pin your toot at point |
+| =d= | delete your toot at point, and reload current timeline |
+| =D= | delete and redraft toot at point, preserving reply/CW/visibility |
| (=S-C-=) =W=, =M=, =B= | (un)follow, (un)mute, (un)block author of toot at point |
-|---------------+-----------------------------------------------------------------------|
-| | Notifications view |
-| =a=, =j= | accept/reject follow request |
-| =c= | clear notification at point |
-| | see =mastodon-notifications--get-*= functions for filtered views |
-|---------------+-----------------------------------------------------------------------|
-| | *Quitting* |
-| =q= | Quit mastodon buffer, leave window open |
-| =Q= | Quit mastodon buffer and kill window |
-|---------------+-----------------------------------------------------------------------|
+|----------------+-----------------------------------------------------------------------|
+| | *Profile view* |
+| =C-c C-c= | cycle between statuses, followers, following, and statuses without boosts |
+| | =mastodon-profile--account-account-to-list= (see lists view) |
+|----------------+-----------------------------------------------------------------------|
+| | *Notifications view* |
+| =a=, =j= | accept/reject follow request |
+| =c= | clear notification at point |
+| | see =mastodon-notifications--get-*= functions for filtered views |
+|----------------+-----------------------------------------------------------------------|
+| | *Quitting* |
+| =q= | Quit mastodon buffer, leave window open |
+| =Q= | Quit mastodon buffer and kill window |
+|----------------+-----------------------------------------------------------------------|
**** Toot byline legend
@@ -222,7 +226,10 @@ You can download and use your instance's custom emoji
*** Other commands and account settings:
-- =mastodon-url-lookup=: Attempt to load URL in =mastodon.el=. URL may be the one at point or provided in the minibuffer. Should also work if =mastodon.el= is not yet loaded.
+In addition to =mastodon=, the following functions are autoloaded and should work without first loading =mastodon.el=:
+- =mastodon-toot=: Compose new toot
+- =mastodon-notifications-get=: View all notifications
+- =mastodon-url-lookup=: Attempt to load a URL in =mastodon.el=. URL may be at point or provided in the minibuffer.
- =mastodon-tl--view-instance-description=: View information about the instance that the author of the toot at point is on.
@@ -310,6 +317,12 @@ Optional dependencies:
- =mpv= and =mpv.el= for viewing videos and gifs
- =lingva.el= for translating toots
+** Network compatibility.
+
+=mastodon.el= should work with ActivityPub servers that implement the Mastodon API.
+
+Apart from Mastodon itself, it is currently known to work with Pleroma and Gotosocial. If you attempt to use =mastodon.el= with another server that implements the Mastodon API and run into problems, feel free to open an issue.
+
** Contributing
PRs, issues, feature requests, and general feedback are very welcome!
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))
diff --git a/test/mastodon-notifications-tests.el b/test/mastodon-notifications-tests.el
index bc70e49..942a7cb 100644
--- a/test/mastodon-notifications-tests.el
+++ b/test/mastodon-notifications-tests.el
@@ -187,11 +187,11 @@
"Ensure get request format for notifictions is accurate."
(let ((mastodon-instance-url "https://instance.url"))
(with-mock
- (mock (mastodon-http--get-json "https://instance.url/api/v1/notifications"))
- (mock (mastodon-profile--fetch-server-account-settings)
- => '(max_toot_chars 1312 privacy "public" display_name "Eugen" discoverable t locked :json-false bot :json-false sensitive :json-false language ""))
+ (mock (mastodon-http--get-json "https://instance.url/api/v1/notifications" nil))
+ (mock (mastodon-profile--fetch-server-account-settings)
+ => '(max_toot_chars 1312 privacy "public" display_name "Eugen" discoverable t locked :json-false bot :json-false sensitive :json-false language ""))
- (mastodon-notifications--get))))
+ (mastodon-notifications-get))))
(defun mastodon-notifications--test-type (fun sample)
"Test notification draw functions.
diff --git a/test/mastodon-profile-tests.el b/test/mastodon-profile-tests.el
index 704f2ce..7478aaf 100644
--- a/test/mastodon-profile-tests.el
+++ b/test/mastodon-profile-tests.el
@@ -172,7 +172,8 @@ The search will happen as if called without the \"@\"."
(with-mock
(mock (mastodon-http--get-json
- "https://instance.url/api/v1/accounts/search?q=gargron"))
+ "https://instance.url/api/v1/accounts/search"
+ '(("q" . "gargron"))))
(let ((mastodon-instance-url "https://instance.url"))
;; We don't check anything from the return value. We only care
@@ -182,7 +183,9 @@ The search will happen as if called without the \"@\"."
(ert-deftest mastodon-profile--search-account-by-handle--filters-out-false-results ()
"Should ignore results that don't match the searched handle."
(with-mock
- (mock (mastodon-http--get-json *)
+ (mock (mastodon-http--get-json
+ "https://instance.url/api/v1/accounts/search"
+ '(("q" . "Gargron")))
=>
(vector ccc-profile-json gargron-profile-json))
@@ -197,7 +200,9 @@ The search will happen as if called without the \"@\"."
TODO: We need to decide if this is actually desired or not."
(with-mock
- (mock (mastodon-http--get-json *) => (vector gargron-profile-json))
+ (mock (mastodon-http--get-json *
+ '(("q" . "gargron")))
+ => (vector gargron-profile-json))
(let ((mastodon-instance-url "https://instance.url"))
(should
diff --git a/test/mastodon-tl-tests.el b/test/mastodon-tl-tests.el
index 19934dd..0ac5caf 100644
--- a/test/mastodon-tl-tests.el
+++ b/test/mastodon-tl-tests.el
@@ -175,27 +175,30 @@ Strict-Transport-Security: max-age=31536000
"Should request toots older than max_id."
(let ((mastodon-instance-url "https://instance.url"))
(with-mock
- (mock (mastodon-http--get-json "https://instance.url/api/v1/timelines/foo?max_id=12345"))
- (mastodon-tl--more-json "timelines/foo" 12345))))
+ (mock (mastodon-http--get-json "https://instance.url/api/v1/timelines/foo"
+ '(("max_id" . "12345"))))
+ (mastodon-tl--more-json "timelines/foo" "12345"))))
(ert-deftest mastodon-tl--more-json-id-string ()
"Should request toots older than max_id.
-`mastodon-tl--more-json' should accept and id that is either
-a string or a numeric."
+ `mastodon-tl--more-json' should accept and id that is either
+ a string or a numeric."
(let ((mastodon-instance-url "https://instance.url"))
(with-mock
- (mock (mastodon-http--get-json "https://instance.url/api/v1/timelines/foo?max_id=12345"))
+ (mock (mastodon-http--get-json "https://instance.url/api/v1/timelines/foo"
+ '(("max_id" . "12345"))))
(mastodon-tl--more-json "timelines/foo" "12345"))))
(ert-deftest mastodon-tl--update-json-id-string ()
"Should request toots more recent than since_id.
-`mastodon-tl--updated-json' should accept and id that is either
-a string or a numeric."
+ `mastodon-tl--updated-json' should accept and id that is either
+ a string or a numeric."
(let ((mastodon-instance-url "https://instance.url"))
(with-mock
- (mock (mastodon-http--get-json "https://instance.url/api/v1/timelines/foo?since_id=12345"))
+ (mock (mastodon-http--get-json "https://instance.url/api/v1/timelines/foo"
+ '(("since_id" . "12345"))))
(mastodon-tl--updated-json "timelines/foo" "12345"))))
(ert-deftest mastodon-tl--relative-time-description ()
@@ -314,7 +317,7 @@ a string or a numeric."
byline)
"Account 42 (@acct42@example.space) 2999-99-99 00:11:22
------------
-"))
+ "))
(should (eq (get-text-property handle-location 'mastodon-tab-stop byline)
'user-handle))
(should (string= (get-text-property handle-location 'mastodon-handle byline)
@@ -337,7 +340,7 @@ a string or a numeric."
'mastodon-tl--byline-boosted))
"Account 42 (@acct42@example.space) 2999-99-99 00:11:22
------------
-")))))
+ ")))))
(ert-deftest mastodon-tl--byline-boosted ()
"Should format the boosted toot correctly."
@@ -354,7 +357,7 @@ a string or a numeric."
'mastodon-tl--byline-boosted))
"(B) Account 42 (@acct42@example.space) 2999-99-99 00:11:22
------------
-")))))
+ ")))))
(ert-deftest mastodon-tl--byline-favorited ()
"Should format the favourited toot correctly."
@@ -371,7 +374,7 @@ a string or a numeric."
'mastodon-tl--byline-boosted))
"(F) Account 42 (@acct42@example.space) 2999-99-99 00:11:22
------------
-")))))
+ ")))))
(ert-deftest mastodon-tl--byline-boosted/favorited ()
@@ -389,7 +392,7 @@ a string or a numeric."
'mastodon-tl--byline-boosted))
"(B) (F) Account 42 (@acct42@example.space) 2999-99-99 00:11:22
------------
-")))))
+ ")))))
(ert-deftest mastodon-tl--byline-reblogged ()
"Should format the reblogged toot correctly."
@@ -413,9 +416,9 @@ a string or a numeric."
(handle2-location 65))
(should (string= (substring-no-properties byline)
"Account 42 (@acct42@example.space)
- Boosted Account 43 (@acct43@example.space) original time
+ Boosted Account 43 (@acct43@example.space) original time
------------
-"))
+ "))
(should (eq (get-text-property handle1-location 'mastodon-tab-stop byline)
'user-handle))
(should (equal (get-text-property handle1-location 'help-echo byline)
@@ -446,9 +449,9 @@ a string or a numeric."
'mastodon-tl--byline-author
'mastodon-tl--byline-boosted))
"Account 42 (@acct42@example.space)
- Boosted Account 43 (@acct43@example.space) original time
+ Boosted Account 43 (@acct43@example.space) original time
------------
-")))))
+ ")))))
(ert-deftest mastodon-tl--byline-reblogged-boosted/favorited ()
"Should format the reblogged toot that was also boosted & favoritedcorrectly."
@@ -470,9 +473,9 @@ a string or a numeric."
'mastodon-tl--byline-author
'mastodon-tl--byline-boosted))
"(B) (F) Account 42 (@acct42@example.space)
- Boosted Account 43 (@acct43@example.space) original time
+ Boosted Account 43 (@acct43@example.space) original time
------------
-")))))
+ ")))))
(ert-deftest mastodon-tl--byline-timestamp-has-relative-display ()
"Should display the timestamp with a relative time."
@@ -808,8 +811,8 @@ a string or a numeric."
(defun tl-tests--property-values-at (property ranges)
"Returns a list with property values at the given ranges.
-The property value for PROPERTY within a region is assumed to be
-constant."
+ The property value for PROPERTY within a region is assumed to be
+ constant."
(let (result)
(dolist (range ranges (nreverse result))
(push (get-text-property (car range) property) result))))