untrusted comment: verify with st.pub
RWQTleDnDrmVqVdvd3FyfBzCpuHDQsj+wkAgx9X3fb1VzuwjFvMa1LqnrsgKorzL0SVcu3yas8TtbHGrTPJIfyZuy8npVC9dEQ0=
(require :asdf)
(require :alexandria)
(require :tooter)
;; Do first:
;; Make a tooter client instance and make-load-form it into
;; client.sexp. super easy. Check tooter's doc/
(defvar *client* (with-open-file (in #p"client.sexp") (read in)))
(defvar *ht* (make-hash-table :test 'equal))
(defun save-threads (&optional (filename #p"threads.sexp")) "
Saves alist of *ht* to #p\"threads.sexp\"
"
(with-open-file (out filename :direction :output :if-exists :supersede)
(let ((*print-pretty* t))
(prin1 (alexandria:hash-table-alist *ht*) out))))
(Defun load-threads (&optional (filename #p"threads.sexp"))
(setq *ht*
(alexandria:alist-hash-table
(with-open-file (in filename) (read in))
:test 'equal)))
(defun 2key.alist (status)
(cons (tooter:id status)
(list
(cons 'utime (tooter:created-at status))
(multiple-value-bind (sec min hou day mon yea)
(decode-universal-time (tooter:created-at status))
(cons 'd-time (format nil "~d of ~d ~d:~d"
day mon hou min)))
(cons 'account-name
(tooter:account-name (tooter:account status)))
(cons 'content (tooter:plain-format-html
(tooter:content status)))
(cons 'attachments
(mapcar (lambda (x) (tooter:remote-url x))
(tooter:media-attachments status))))))
(defun sew-thread (status)
(let* ((progenitor
(or (car (tooter:ancestors
(tooter:context *client* status)))
status))
(orig-context (tooter:context *client* progenitor))
(protid (tooter:id progenitor)))
(symbol-macrolet ((it (gethash protid *ht*)))
(loop initially (setf it
(or it (list (2key.alist progenitor))))
for d in (tooter:descendants orig-context)
for key.alist = (2key.alist d)
do (unless (assoc (car key.alist) it :test 'equal)
(push key.alist (cdr it)))
finally (setf it (sort it '< :key 'cdadr))
(return-from sew-thread it)))))