Skip to content

Instantly share code, notes, and snippets.

@tombarys
Last active May 20, 2023 09:21
Show Gist options
  • Save tombarys/220e8d5c3e1c72b2c0333ca5c61d0444 to your computer and use it in GitHub Desktop.
Save tombarys/220e8d5c3e1c72b2c0333ca5c61d0444 to your computer and use it in GitHub Desktop.
Send block from Roam to Readwise using context menu
(ns my-custom-roam-01072022
(:require [roam.datascript :as rd]
[promesa.core :as p]
[clojure.string :as s]))
;; SETUP SECTION
;; 1) Open or create page [[roam/cljs]] in your Roam
;; 2) Create a parent block with {{[[roam/cljs]]}}
;; 3) Create a children block of the above block
;; 4) Put all this code into Clojure code block (start writing /Clojure, and paste it)
;; 5) Set-up the options below – especially the Readwise Token
;; 6) Confirm "Yes" to run the code on every page of your graph (restart Roam)
;; Note: the script converts Roam markdown markup to Readwise markup – but Readwise API somehow fails to apply the markup immediatelly.
;; Options:
(def readwise-token "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
;; your Readwise API token; get it here: https://readwise.io/access_token
(def book-name "My Roam Quote Book")
;; name of the „book” in your Readwise under which quotes will
;; be aggregated
(def author-name "John Doe") ;; this will be your Readwise author for the book
(def add-tags? true) ;; set to `false` if you want to stop converting all #tags to .tags
;; (the text with the tags is actually left untouched but .tags are added to Note section)
;; Important: one-word only #tags are converted to .tags
(def desktop-links? true) ;; format of backlink to the Roam block FROM Readwise
;; `true` for roam:// backlinks which work well with desktop Roam but not from a mobile Readwise
;; `false` for http:// backlinks that work everywhere but always open a new browser tab
;; END OF SETUP SECTION
(defn readwisize [text]
(-> text
(s/replace "__" "*")
(s/replace "[[>]]" ">")
(s/replace "^^" "__")))
(defn extrags [text]
(s/replace (->> (re-seq #"#[^\[].+?\s" (str text " "))
(reduce #(str %1 "\n" %2)))
"#" "."))
(defn prefix []
(if desktop-links? "roam://" "http://roamresearch.com/"))
(defn graph-name []
(str js/window.roamAlphaAPI.graph.name))
(defn send->readwise [uid text]
(p/do!
(-> (js/fetch "https://readwise.io/api/v2/highlights/"
(clj->js
{:method "POST"
:headers {"Content-Type" "application/json; charset=utf-8",
"Authorization" (str "Token " readwise-token)}
:body (.stringify js/JSON
(clj->js {:highlights
[{:title book-name
:author author-name
:text (readwisize text)
:note (if add-tags? (extrags text) "")
:source_type "Roam"
:highlight_url (str (prefix desktop-links?)"#/app/" (graph-name) "/page/" uid)}]}))}))
(.then #(js/console.log "Fetch: ok"))
(.catch #(js/console.log "Fetch error:" %)))))
(defn get-block-content [uid]
(rd/q '[:find ?text .
:in $ ?uid
:where [?e :block/uid ?uid]
[?e :block/string ?text]]
uid))
(defn main []
(js/window.roamAlphaAPI.ui.blockContextMenu.addCommand
(clj->js {:label "Send to Readwise"
:callback
(fn [ctx]
(let [uid (:block-uid (js->clj ctx :keywordize-keys true))]
(->> uid
(get-block-content)
(send->readwise uid))))})))
(main)
@tombarys
Copy link
Author

tombarys commented Jul 3, 2022

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment