#!/usr/bin/env ruby # REF: https://joplinapp.org/help/api/references/rest_api/ $:.unshift File.expand_path('../lib', __dir__) require 'joplin' require 'thor' require 'yaml' DIVIDER = %( ) class MyCLI < Thor class_option :token, type: :string # , required: true class_option :help, type: :boolean class_option :version, type: :boolean map ['-v', '--version'] => :version map ['-h', '--help'] => :help option :token option :'dry-run', desc: 'dry-run', aliases: '-n' desc :clean, 'clean unused resources' def clean Joplin.token = Joplinl.get_token || options[:token] puts 'Please wait, this can take while.' Joplin::Resource.orphaned.map do |r| r.delete unless options['dry-run'] would = 'would have ' if options['dry-run'] puts "#{would}deleted #{r.id}" end end method_options force: :boolean desc 'version', 'get version of program' def version puts Joplin::VERSION end desc 'write', 'write a note' long_desc 'This will write a note in the format of "note title/note title.md and put all resources under the folder' def write(id) note = Joplin::Note.new(id:) note.write end desc :stats, 'statistics on joplin data' long_desc 'Get some statistics on the joplin instance, the number of notebooks, notes' option :token def stats notes_total = 0 notebooks = Joplin::Notebook.all notebooks.each do |notebook| notes_count = notebook.notes.size # Get the count of notes in the notebook notes_total += notebook.notes.size end puts <<~HEREDOC Token: #{token} Notebooks: #{notebooks.size} Notes: #{notes_total} HEREDOC end desc :nb2n, 'concate all notes in a notebook to one note. Possible PDF export' long_desc 'The idea is to make a big note from all the notes in a notebook. PDF export or whatever export can happen from that. The notes are concatenated with a separator.' option :token option :type, type: :string def nb2n(query) Joplin.token = options[:token] || Joplin::Token.get results = Joplin.search(query, { type: 'folder' }) nb = results[0] abort "notebook #{query} not found" unless nb and nb['title'] == query notebook = Joplin::Notebook.new nb['id'] notes = notebook.notes new_note = Joplin::Note.new new_note.title = query new_note.body = notes.map { |n| "\# #{n.title}\n\n#{n.body}" }.join new_note.save! puts "Saved: #{new_note.title} with id: #{new_note.id}" end desc :epub, 'build a note from a note (help build), write the note, and create an epub from the result. needs pandoc installed' long_desc <<-DESC If the building note has a yaml descriptor https://pandoc.org/MANUAL.html#epubs then the epub will end up having the meta data. Below is an example note. The for the referenced note are a result from using Joplin's webclipper on https://fiachetti.gitlab.io/mastering-roda/ ---\n title: Mastering Roda\n author: Federico Iachetti\n rights: Creative Commons Attribution 4.0 International License\n language: en-US\n ... [Mastering Roda](:/ca267a317fa544f99f559040696f1cae) DESC def epub(id) build_note = Joplin::Note.new(id:) note = build(id) note.write build_note.write note.title FileUtils.cd note.title `pandoc '#{note.title}.md' -o '../#{note.title}.epub' -t epub3 -f markdown+smart --title '#{note.title}' --toc --toc-depth=3 --metadata title='#{note.title}'` note.delete! FileUtils.cd '..' # FileUtils.rm_rf note.title abort 'Omg. pandoc failed!' if $?.exitstatus != 0 puts "OK. Done. Your book is #{note.title}.epub" end desc :build, 'build a note from a note containing references' long_desc %(Takes a note and looks up all the referenced notes and makes a new note from those in the same folder. The notes are concatenated with a separator.\n\nIf you have a line with 'title: a title' then it will be used for the title of the built note.) def build(id) token note = Joplin::Note.new(id:) notes = [] note.body.each_line do |line| match = line.match %r{!?\[(.*)?\]\(:/(\w+)\)} next unless match next if match[0][0] == '!' begin notes.push Joplin::Note.new id: match[2] rescue Joplin::Note::NotFound puts "Couldn't find note with id #{id} so we skip it. Maybe an image" end end yml = extract_yaml_header_for_epub(note) new_note = Joplin::Note.new parent_id: note.parent_id new_note.title = yml ? title_from_yml(yml) : "built: #{note.title}" new_note.body = "#{Psych.dump yml}...\n" if yml new_note.body += notes.map { |n| "\# #{n.title}\n\n#{n.body}" }.join new_note.save! new_note end private # if using subtitle with pandoc it has a different format # https://pandoc.org/MANUAL.html#epubs def title_from_yml(yml) if yml['title'].is_a? Array yml['title'].each do |title| return title['text'] if title['type'] == 'main' end end yml['title'] end def extract_yaml_header_for_epub(note) yml = Psych.load note.body return nil unless yml.is_a? Hash yml end def token Joplin.token = Joplin.get_token || options[:token] return Joplin.token if Joplin.token raise "Couldn't find token in local database and it wasn't passed as an option. You better check yourself!" end end MyCLI.start(ARGV)