aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.org17
-rw-r--r--lisp/mastodon-notifications.el2
-rw-r--r--lisp/mastodon-profile.el8
-rw-r--r--lisp/mastodon-tl.el62
-rw-r--r--lisp/mastodon-toot.el19
-rw-r--r--lisp/mastodon.el1
6 files changed, 80 insertions, 29 deletions
diff --git a/README.org b/README.org
index 0d28585..2455124 100644
--- a/README.org
+++ b/README.org
@@ -1,3 +1,5 @@
+#+OPTIONS: toc:nil
+
* mastodon.el fork
This is a fork of of the great but seemingly dormant https://github.com/jdenen/mastodon.el.
@@ -10,6 +12,7 @@ It adds the following features:
| | display relationship (follows you/followed by you) on profiles |
| | display toots/follows/followers counts on profiles |
| | links/tags/mentions in profile bios are active links |
+| | show a lock icon for locked accounts |
| =R=, =C-c a=, =C-c r= | view/accept/reject follow requests |
| =V= | view your favorited toots |
| =K= | view your bookmarked toots |
@@ -24,10 +27,12 @@ It adds the following features:
| =d= | delete your toot at point, and reload current timeline |
| =D= | delete and redraft toot at point, preserving reply/CW/visibility |
| =W=, =M=, =B= | (un)follow, (un)mute, (un)block author of toot at point |
+| =k= | toggle bookmark of toot at point |
| | display polls and vote on polls (pretty basic for now) |
| | images are links to the full image, can be zoomed/rotated/saved (see image keymap) |
| | images scale properly |
| | toot visibility (direct, followers only) icon appears in toot bylines |
+| | display a toot's favorites, boosts and replies count in thread view |
| Toots: | |
| | mention booster in replies by default |
| | autocompletion of mentions, via company-mode (must be installed to work) |
@@ -36,7 +41,7 @@ It adds the following features:
| =C-c C-n= | and sensitive media/nsfw flag |
| =C-c C-e= | add emoji (if =emojify= installed) |
| | replies preserve visibility status/CW of original toot |
-| | server's maximum toot length shown |
+| | server's maximum toot length shown in toot compose buffer |
| Search: | |
| =S= | search (posts, users, tags) (NB: only posts you have interacted with are searched) |
| | |
@@ -49,11 +54,13 @@ The minimum Emacs version is now 26.1. But if you are running an older version i
I did this for my own use and to learn more Elisp. Feel free to improve it.
-** live-updating timelines
+** live-updating timelines: =mastodon-async-mode=
(code taken from https://github.com/alexjgriffith/mastodon-future.el.)
-Works for federated, local, and home timelines and for notifications. It's pretty necro, sometimes it goes off the rails, so use at your own risk. Not a super high priority for me, but some people dig it. The command prefix is =mastodon-async--stream=.
+Works for federated, local, and home timelines and for notifications. It's pretty necro, sometimes it goes off the rails, so use at your own risk. Not a super high priority for me, but some people dig it.
+
+To enable, it, add =(require 'mastodon-async)= to your =init.el=. Then you can view a timeline with one of the commands that begin with =mastodon-async--stream-=.
** NB: dependency
@@ -80,9 +87,9 @@ I might add a few more features if the ones I added turn out to work ok. Possibl
- [X] display post visibility status in timelines
- [X] caching of images / avatars
- better display of polls
-- display number of boosts/faves in toot byline
+- [X] display number of boosts/faves in toot byline
- mention all thread participants in replies
-- improve (or even partially disable) async.
+- [X] improve (or even partially disable) async.
It looks like 2-factor auth was never completed in the original repo. It's not a priority for me, auth ain't my thing. If you want to hack on it, its on the develop branch in the original repo.
diff --git a/lisp/mastodon-notifications.el b/lisp/mastodon-notifications.el
index c917124..2e9aea3 100644
--- a/lisp/mastodon-notifications.el
+++ b/lisp/mastodon-notifications.el
@@ -252,7 +252,7 @@ ID is the notification's own id, which is attached as a property."
"Display NOTIFICATIONS in buffer."
(interactive)
(message "Loading your notifications...")
- (mastodon-tl--init
+ (mastodon-tl--init-sync
"notifications"
"notifications"
'mastodon-notifications--timeline))
diff --git a/lisp/mastodon-profile.el b/lisp/mastodon-profile.el
index a374061..22120fe 100644
--- a/lisp/mastodon-profile.el
+++ b/lisp/mastodon-profile.el
@@ -296,6 +296,7 @@ Returns a list of lists."
(buffer (concat "*mastodon-" acct "-" endpoint-type "*"))
(note (mastodon-profile--account-field account 'note))
(json (mastodon-http--get-json url))
+ (locked (mastodon-profile--account-field account 'locked))
(followers-count (mastodon-tl--as-string
(mastodon-profile--account-field
account 'followers_count)))
@@ -338,8 +339,13 @@ Returns a list of lists."
account 'display_name)
'face 'mastodon-display-name-face)
"\n"
- (propertize acct
+ (propertize (concat "@" acct)
'face 'default)
+ (if (equal locked t)
+ (if (fontp (char-displayable-p #10r9993))
+ " 🔒"
+ " [locked]")
+ "")
"\n ------------\n"
(mastodon-tl--render-text note account)
;; account here to enable tab-stops in profile note
diff --git a/lisp/mastodon-tl.el b/lisp/mastodon-tl.el
index 7f9538b..9bbc44f 100644
--- a/lisp/mastodon-tl.el
+++ b/lisp/mastodon-tl.el
@@ -406,11 +406,11 @@ By default it is `mastodon-tl--byline-boosted'"
(funcall author-byline toot)
(cond ((equal visibility "direct")
(if (fontp (char-displayable-p #10r128274))
- " 🔒"
+ " ✉"
" [direct]"))
((equal visibility "private")
(if (fontp (char-displayable-p #10r9993))
- " ✉"
+ " 🔒"
" [followers]")))
(funcall action-byline toot)
" "
@@ -721,6 +721,14 @@ takes a single function. By default it is
(mastodon-tl--byline toot author-byline action-byline))
'toot-id (cdr (assoc 'id toot))
'base-toot-id (mastodon-tl--toot-id toot)
+ 'help-echo (when (and mastodon-tl--buffer-spec
+ (string-match-p
+ "context"
+ (plist-get mastodon-tl--buffer-spec 'endpoint)))
+ (format "%s faves | %s boosts | %s replies"
+ (cdr (assoc 'favourites_count toot))
+ (cdr (assoc 'reblogs_count toot))
+ (cdr (assoc 'replies_count toot))))
'toot-json toot)
"\n")
(when mastodon-tl--display-media-p
@@ -907,23 +915,16 @@ webapp"
(reblog (cdr (assoc 'reblog json))))
(if reblog (cdr (assoc 'id reblog)) id)))
+
(defun mastodon-tl--thread ()
- "Open thread buffer for toot under `point' asynchronously."
+ "Open thread buffer for toot under `point'."
(interactive)
(let* ((id (mastodon-tl--as-string (mastodon-tl--toot-id
(mastodon-tl--property 'toot-json))))
- (toot (mastodon-tl--property 'toot-json))
+ (url (mastodon-http--api (format "statuses/%s/context" id)))
(buffer (format "*mastodon-thread-%s*" id))
- (url (mastodon-http--api (format "statuses/%s/context" id))))
- (mastodon-http--get-json-async url
- 'mastodon-tl--thread* id toot buffer)))
-
-(defun mastodon-tl--thread* (context id toot buffer)
- "Callback for async `mastodon-tl--thread'.
-
-Open thread buffer for TOOT with id ID under `point'asynchronously,
-in new BUFFER.
-CONTEXT is the previous and subsequent toots in the thread."
+ (toot (mastodon-tl--property 'toot-json))
+ (context (mastodon-http--get-json url)))
(when (member (cdr (assoc 'type toot)) '("reblog" "favourite"))
(setq toot (cdr (assoc 'status toot))))
(if (> (+ (length (cdr (assoc 'ancestors context)))
@@ -942,7 +943,7 @@ CONTEXT is the previous and subsequent toots in the thread."
(cdr (assoc 'ancestors context))
`(,toot)
(cdr (assoc 'descendants context))))))
- (message "No Thread!")));)
+ (message "No Thread!"))))
(defun mastodon-tl--follow-user (user-handle)
"Query for USER-HANDLE from current status and follow that user."
@@ -1314,5 +1315,36 @@ JSON is the data returned from the server."
(current-buffer)
nil)))))
+(defun mastodon-tl--init-sync (buffer-name endpoint update-function)
+ "Initialize BUFFER-NAME with timeline targeted by ENDPOINT.
+
+UPDATE-FUNCTION is used to recieve more toots.
+Runs synchronously."
+ (let* ((url (mastodon-http--api endpoint))
+ (buffer (concat "*mastodon-" buffer-name "*"))
+ (json (mastodon-http--get-json url)))
+ (with-output-to-temp-buffer buffer
+ (switch-to-buffer buffer)
+ (setq
+ ;; Initialize with a minimal interval; we re-scan at least once
+ ;; every 5 minutes to catch any timestamps we may have missed
+ mastodon-tl--timestamp-next-update (time-add (current-time)
+ (seconds-to-time 300)))
+ (funcall update-function json))
+ (mastodon-mode)
+ (with-current-buffer buffer
+ (setq mastodon-tl--buffer-spec
+ `(buffer-name ,buffer-name
+ endpoint ,endpoint update-function
+ ,update-function)
+ mastodon-tl--timestamp-update-timer
+ (when mastodon-tl--enable-relative-timestamps
+ (run-at-time mastodon-tl--timestamp-next-update
+ nil ;; don't repeat
+ #'mastodon-tl--update-timestamps-callback
+ (current-buffer)
+ nil))))
+ buffer))
+
(provide 'mastodon-tl)
;;; mastodon-tl.el ends here
diff --git a/lisp/mastodon-toot.el b/lisp/mastodon-toot.el
index 983515e..14dcc29 100644
--- a/lisp/mastodon-toot.el
+++ b/lisp/mastodon-toot.el
@@ -34,7 +34,11 @@
(declare-function emojify-insert-emoji "emojify"))
(require 'cl-lib)
-(require 'company nil :noerror)
+
+(when (require 'company nil :noerror)
+ (declare-function company-mode-on "company")
+ (declare-function company-begin-backend "company")
+ (declare-function company-grab-symbol "company"))
(defvar mastodon-instance-url)
(autoload 'mastodon-auth--user-acct "mastodon-auth")
@@ -563,7 +567,7 @@ It adds the items' ids to `mastodon-toot--media-attachment-ids', which is used t
(mapcar (lambda (attachment)
(let* ((filename (cdr (assoc :filename attachment)))
(caption (cdr (assoc :description attachment)))
- (url (concat mastodon-instance-url "/api/v1/media")))
+ (url (concat mastodon-instance-url "/api/v2/media")))
(message "Uploading %s..." (file-name-nondirectory filename))
(mastodon-http--post-media-attachment url filename caption)))
mastodon-toot--media-attachments))
@@ -727,7 +731,7 @@ REPLY-JSON is the full JSON of the toot being replied to."
(setq mastodon-toot--content-warning t)
(setq mastodon-toot--content-warning-from-reply-or-redraft reply-cw)))))
-(defun mastodon-toot--update-status-fields (&rest args)
+(defun mastodon-toot--update-status-fields (&rest _args)
"Update the status fields in the header based on the current state."
(ignore-errors ;; called from after-change-functions so let's not leak errors
(let ((inhibit-read-only t)
@@ -780,10 +784,11 @@ REPLY-JSON is the full JSON of the toot being replied to."
(mastodon-toot-mode t)
(unless mastodon-toot--max-toot-chars
(mastodon-toot--get-max-toot-chars))
- (when mastodon-toot--enable-completion-for-mentions
- (set (make-local-variable 'company-backends)
- (add-to-list 'company-backends 'mastodon-toot--mentions-completion))
- (company-mode-on))
+ (when (require 'company nil :noerror)
+ (when mastodon-toot--enable-completion-for-mentions
+ (set (make-local-variable 'company-backends)
+ (add-to-list 'company-backends 'mastodon-toot--mentions-completion))
+ (company-mode-on)))
(make-local-variable 'after-change-functions)
(push #'mastodon-toot--update-status-fields after-change-functions)
(mastodon-toot--refresh-attachments-display)
diff --git a/lisp/mastodon.el b/lisp/mastodon.el
index 7f4b773..25fb829 100644
--- a/lisp/mastodon.el
+++ b/lisp/mastodon.el
@@ -77,6 +77,7 @@
;; (autoload 'mastodon-async--stream-local "mastodon-async")
;; (autoload 'mastodon-async--stream-home "mastodon-async")
;; (autoload 'mastodon-async--stream-notifications "mastodon-async")
+;; (autoload 'mastodon-async-mode "mastodon-async")
(autoload 'mastodon-profile--update-user-profile-note "mastodon-profile")
(autoload 'mastodon-auth--user-acct "mastodon-auth")
(autoload 'mastodon-tl--poll-vote "mastodon-http")