require "synclenote" require "yaml" require "pathname" require "logger" require "tempfile" require "thor" require "evernote_oauth" require "redcarpet" class Synclenote::Command < Thor attr_accessor :logger def initialize(*args, &block) super self.logger = Logger.new(STDOUT) end desc "init", "Create profile directory" def init if profile_path.exist? $stderr.puts(< e logger.error(e.inspect) raise end # remove note removed = Pathname.glob(sync_statuses_path + c.local.pattern) - processed removed.each do |note_sync_status_path| remove_remote_note(token, note_store, note_sync_status_path) end end private YAML_HEADER = < EOS FOOTER = < EOS def profile_path return @profile_path ||= Pathname("~/.synclenote").expand_path end def config_path return @config_path ||= profile_path + "config" end def sync_statuses_path return @sync_statuses_path ||= profile_path + "sync_statuses" end def last_sync_path return @last_sync_path ||= profile_path + "last_sync" end def min_sync_interval # return 15 * 60 # 15 min for production return 4 # 4 sec for sandbox end def build_html(markdown_text) @formatter ||= Redcarpet::Markdown.new( Redcarpet::Render::HTML.new( filter_html: true, hard_wrap: true, ), underline: true, lax_spacing: true, footnotes: true, no_intra_emphasis: true, superscript: true, strikethrough: true, tables: true, space_after_headers: true, fenced_code_blocks: true, # autolink: true, ) html = @formatter.render(markdown_text) return html end def create_note(note_path, options = {}) title = nil tags = ["syncle"] body = nil note_path.open do |f| title = f.gets.chomp.sub(/\A#\s*/, "") if md = /\A(?(?:\[.*?\])+)(?:\s|\z)/.match(title) tags += md[:tags].scan(/\[(.*?)\]/).flatten title = md.post_match end body = f.read end html = build_html(body) content = HEADER + html.gsub(/ class=\".*?\"/, "").gsub(/<(br|hr|img).*?>/, "\\&") + FOOTER o = options.merge(title: title, content: content, tagNames: tags) return Evernote::EDAM::Type::Note.new(o) end def target_note?(note) c = Synclenote::Configuration.data if c.local.whitelist_tags return note.tagNames.any? { |name| c.local.whitelist_tags.include?(name) } elsif c.local.blacklist_tags return !note.tagNames.any? { |name| c.local.blacklist_tags.include?(name) } end return true end def create_note_sync_status_file(path, note, sync_datetime) Tempfile.open("synclenote") do |tmp_file| tmp_file.puts(YAML_HEADER) tmp_file.puts({ last_sync_datetime: sync_datetime, guid: note.guid, }.to_yaml) tmp_file.close path.parent.mkpath FileUtils.mv(tmp_file.path, path) end end def create_remote_note(token, note_store, note_path, note_sync_status_path) c = Synclenote::Configuration.data new_note = create_note(note_path) if !target_note?(new_note) logger.info("skip creating: %s" % note_path) return end logger.debug("doing createNote: %s" % note_path) created_note = note_store.createNote(token, new_note) logger.debug("done createNote.") create_note_sync_status_file(note_sync_status_path, created_note, Time.now) logger.debug("created: %s" % note_sync_status_path) end def update_remote_note(token, note_store, note_path, note_sync_status_path, guid) new_note = create_note(note_path, guid: guid) if !target_note?(new_note) logger.info("skip updating: %s" % note_path) remove_remote_note(token, note_store, note_sync_status_path) return end logger.debug("doing updateNote: %s %s" % [note_path, guid]) updated_note = note_store.updateNote(token, new_note) logger.debug("done updateNote.") create_note_sync_status_file(note_sync_status_path, updated_note, Time.now) logger.debug("created: %s" % note_sync_status_path) end def remove_remote_note(token, note_store, note_sync_status_path) note_sync_status = YAML.load_file(note_sync_status_path) guid = note_sync_status[:guid] logger.debug("doing deleteNote: %s" % guid) note_store.deleteNote(token, guid) logger.debug("done deleteNote.") note_sync_status_path.delete logger.debug("removed: %s" % note_sync_status_path) end end