Last active
February 28, 2025 22:51
-
-
Save kevinjalbert/1d77add23d9bdaa615a5bd5c05328678 to your computer and use it in GitHub Desktop.
Import Raindrop.io Highlights into Readwise
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require "httparty" | |
require "nokogiri" | |
require "open-uri" | |
require "uri" | |
RAINDROP_AUTH_TOKEN="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" | |
READWISE_AUTH_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" | |
LAST_SAVED_HIGHLIGHT=000000000 # <- Keeps track of import position (Updates automatically) | |
def title_from_url(url) | |
URI.open(url) do |f| | |
doc = Nokogiri::HTML(f) | |
title = doc.at_css("title").text | |
return title | |
end | |
end | |
def domain_from_url(url) | |
URI.parse(url).host.gsub(/^www\./i, "") | |
end | |
def request_raindrop_highlights(page) | |
HTTParty.get("https://api.raindrop.io/rest/v1/highlights?page=#{page}&perpage=50", | |
headers: { | |
"Authorization" => "Bearer #{RAINDROP_AUTH_TOKEN}", | |
"Content-Type" => "application/json" | |
}, | |
) | |
end | |
def save_highlight_to_readwise(highlight) | |
HTTParty.post("https://readwise.io/api/v2/highlights/", | |
headers: { | |
"Authorization" => "Token #{READWISE_AUTH_TOKEN}", | |
"Content-Type" => "application/json" | |
}, | |
body: { | |
highlights: [ | |
{ | |
text: highlight["text"], | |
title: title_from_url(highlight["link"]), | |
author: domain_from_url(highlight["link"]), | |
source_url: highlight["link"], | |
category: "articles", | |
highlighted_at: DateTime.parse(highlight["created"]).iso8601 | |
} | |
] | |
}.to_json | |
) | |
end | |
def update_last_saved_highlight_value(last_highlight_value) | |
puts "Updating last saved highlight value to #{last_highlight_value}" | |
content = File.read(__FILE__) | |
updated_content = content.sub(/LAST_SAVED_HIGHLIGHT=\d+/, "LAST_SAVED_HIGHLIGHT=#{last_highlight_value}") | |
File.write(__FILE__, updated_content) | |
end | |
first_highlight_id = nil | |
page = 0 | |
while true | |
puts "Processing Raindrop.io highlights from page #{page + 1}" | |
raindrop_highlights = request_raindrop_highlights(page)["items"] | |
if raindrop_highlights.empty? | |
puts "No more highlights to process" | |
update_last_saved_highlight_value(first_highlight_id) | |
exit | |
end | |
raindrop_highlights.map do |highlight| | |
puts "-> Importing highlight into Readwise (#{[highlight['link'], highlight['created']].join(', ')})" | |
saved_highlight = save_highlight_to_readwise(highlight).first | |
saved_highlight_id = saved_highlight["modified_highlights"].first | |
first_highlight_id = saved_highlight_id if first_highlight_id.nil? | |
if saved_highlight_id == LAST_SAVED_HIGHLIGHT | |
puts "Reached last saved highlight" | |
update_last_saved_highlight_value(first_highlight_id) | |
exit | |
end | |
end | |
page += 1 | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment