Home Import Omnivore into Raindrop.io
Post
Cancel

Import Omnivore into Raindrop.io

Export your data per https://docs.omnivore.app/using/exporting.html (soon to disapear)

Here is a sample record from Omnivore export metadata:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 {
    "id": "8faf0bb4-6e6b-11ee-b3e1-5f09928ef4f6",
    "slug": "anthony-bourdain-s-boeuf-bourguignon-recipe-the-washington-post-18b4783620a",
    "title": "Anthony Bourdain's Boeuf Bourguignon Recipe - The Washington Post",
    "description": "Anthony Bourdain's take on the classic dish of beef braised in red wine requires time, but no complicated ingredients or techniques.",
    "author": null,
    "url": "https://www.washingtonpost.com/recipes/anthony-bourdains-boeuf-bourguignon/7859",
    "state": "Active",
    "readingProgress": 0,
    "thumbnail": "https://www.washingtonpost.com/wp-apps/imrs.php?src=https://arc-anglerfish-washpost-prod-washpost.s3.amazonaws.com/public/BHTIKMCVZQI6XLGFSLJIDGQ4ZM.jpg&w=1440",
    "labels": [
      "recipe"
    ],
    "savedAt": "2023-10-19T10:37:54.570Z",
    "updatedAt": "2023-10-19T10:37:54.704Z",
    "publishedAt": null
  }

From https://help.raindrop.io/import#supported-formats, we need to create a CSV file with these columns:

raindrop.io omnivore
url url
folder null
title title
note description
tags labels (joined with ‘,’)
created savedAt

The following Ruby script can be invoked to prepare a CSV file ready to import to raindrop.io. Save it to a file and use it like this after unpacking the zip file with your exported Omnivore data:

1
ruby omnivore2raindrop.rb metadata_*.json > metadata.csv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#!/usr/bin/env ruby

# Copyright 2024 Mike Carlton
#
# Released under terms of the MIT License:
#   http://www.opensource.org/licenses/mit-license.php

require 'json'
require 'csv'

# column[omnivore] = raindrop
COLUMNS = {
  "url"         => "url",
  "title"       => "title",
  "labels"      => "tags",
  "description" => "note",
  "savedAt"     => "created"
}

def quote(cell)
  cell.to_s.gsub(/\s*\n/, ' ')
end

LABELS = { }

def json_to_csv(files)
  CSV.generate do |csv|
    csv << COLUMNS.values

    # Write the data rows
    files.each do |file|
      begin
        json_data = JSON.parse(File.read(file))
        STDERR.print "\rRead #{json_data.length} record(s) from #{file}"

        json_data.each do |row|
          # coalesce and collect info on labels
          row["labels"] = row["labels"].filter { |label| label != ',' }.map do |label|
            label.gsub!('"', "'")
            LABELS[label] ||= 0
            LABELS[label] += 1
            label.include?(' ') ? '"' + label + '"' : label
          end.join(',')
          csv << row.slice(*COLUMNS.keys).values.map { |value| quote(value) }
        end
      rescue JSON::ParserError => e
        STDERR.puts "#{e} in file #{file}"
        exit 1
      end
    end
    STDERR.puts
  end
end

if ARGV.length == 0
  STDERR.puts "Usage #{$0} metadata_*.json > metadata.csv"
  exit 1
end

puts json_to_csv(ARGV)

LABELS.sort_by { |k,v| k.downcase }.each do |k,v|
  STDERR.puts "%4d: %s" % [ v, k ]
end
This post is licensed under CC BY 4.0 by the author.