memot 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 95e71f2387ebc7f6326acb02c05bbfadf255f58f
4
+ data.tar.gz: 90bf03bda2664167424ae2d583cb672fa14eb0c7
5
+ SHA512:
6
+ metadata.gz: 6db31da79d2ba95f4b0cb165f8cc79f2053d3221fcfe145f7357fb02b69b1836103c15c3b84f5219d676873dec6636ffb8bbe1e53008bd3fd10db77c4c5591e7
7
+ data.tar.gz: 3953eff5818dbde19f0e8ddadb8a448511e1875c00a46276f09d577a2ae7de0ad51b22e32b3d333306b7c73281fd1ace01104ef5b9725bb2fc8851a97f579291
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
@@ -0,0 +1,9 @@
1
+ auth:
2
+ evernote:
3
+ token:
4
+ sandbox:
5
+ dropbox:
6
+ app_key:
7
+ app_secret:
8
+ access_token:
9
+ notes:
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
@@ -0,0 +1,8 @@
1
+ FROM ruby:2.2.0
2
+
3
+ RUN mkdir /app
4
+ COPY . /app
5
+ WORKDIR /app
6
+ RUN bundle install --without development --system
7
+
8
+ CMD ["bundle", "exec", "bin/memot", "-i", "15"]
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in memot.gemspec
4
+ gemspec
@@ -0,0 +1,8 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 dtan4
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,84 @@
1
+ # Memot
2
+
3
+ Synchronize Evernote and Markdown in Dropbox
4
+
5
+ (TODO: Add image)
6
+
7
+ ## Installation
8
+
9
+ ```shell
10
+ $ gem install memot
11
+ $ memot
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ ## Configure
17
+
18
+ You can choose configuration style:
19
+
20
+ - `~/.memot.yml`
21
+ - Environment variables
22
+
23
+ ### `~/.memot.yml`
24
+
25
+ Create `~/.memot.yml` and fill this.
26
+
27
+ ```yaml
28
+ auth:
29
+ evernote:
30
+ token:
31
+ sandbox: false
32
+ dropbox:
33
+ app_key:
34
+ app_secret:
35
+ access_token:
36
+ notes:
37
+ <evernote_notebook>: <dropbox_path>
38
+ # example
39
+ daily: /memo/daily
40
+ reading: /memo/reading
41
+ ```
42
+
43
+ ### Environment variables
44
+
45
+ key | type | example
46
+ ----|------|-----
47
+ MEMOT_DROPBOX_APP_KEY | string |
48
+ MEMOT_DROPBOX_APP_SECRET | string |
49
+ MEMOT_DROPBOX_ACCESS_TOKEN | string |
50
+ MEMOT_EVERNOTE_TOKEN | string |
51
+ MEMOT_EVERNOTE_SANDBOX | boolean | `false`
52
+ MEMOT_NOTES | string | `daily:/memo/daily,reading:/memo/reading`
53
+
54
+ MEMOT_NOTES: `<evernote_notebook1>:<dropbox_path1>[,<evernote_notebook2>:<dropbox_path2> ...]`
55
+
56
+ ## Docker image
57
+
58
+ Memot Docker image is available at [quay.io/dtan4/memot](https://quay.io/repository/dtan4/memot).
59
+
60
+ [![Docker Repository on Quay.io](https://quay.io/repository/dtan4/memot/status "Docker Repository on Quay.io")](https://quay.io/repository/dtan4/memot)
61
+
62
+ ```shell
63
+ $ docker run -e MEMOT_DROPBOX_APP_KEY=... quay.io/dtan4/memot
64
+ ```
65
+
66
+ This image runs `memot` every 15 minutes.
67
+ If you'd like to configure interval, specify command explicitly.
68
+
69
+ ```shell
70
+ # Run every 30 minutes
71
+ $ docker run -e MEMOT_DROPBOX_APP_KEY=... quay.io/dtan4/memot bundle exec bin/memot -i 30
72
+ ```
73
+
74
+ ## Contributing
75
+
76
+ 1. Fork it
77
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
78
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
79
+ 4. Push to the branch (`git push origin my-new-feature`)
80
+ 5. Create new Pull Request
81
+
82
+ ## License
83
+
84
+ MIT
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "memot"
4
+ require "optparse"
5
+
6
+ @options = {
7
+ auth: false,
8
+ interval: 0,
9
+ }
10
+
11
+ OptionParser.new do |opts|
12
+ opts.on("--auth", "Authenticate Dropbox") { |val| @options[:auth] = true }
13
+ opts.on("-i", "--interval=INTERVAL", "Sync interval") { |val| @options[:interval] = val.to_i }
14
+ end.parse!(ARGV)
15
+
16
+ config_dir = ENV["MEMOT_CONFIG_DIR"] || ENV["HOME"]
17
+ config_path = File.join(config_dir, ".memot.yml")
18
+ config = File.exists?(config_path) ? Memot::Config.load_yaml(config_path) : Memot::Config.load_env
19
+
20
+ if @options[:auth]
21
+ access_token = Memot::Dropbox.auth(config.auth[:dropbox][:app_key], config.auth[:dropbox][:app_secret])
22
+ puts access_token
23
+ exit 0
24
+ end
25
+
26
+ redis_host = ENV["REDIS_HOST"] || ENV["REDIS_PORT_6379_TCP_ADDR"] || "127.0.0.1"
27
+ redis_port = (ENV["REDIS_PORT"] || ENV["REDIS_PORT_6379_TCP_PORT"] || "6379").to_i
28
+
29
+ redis = Redis.new(host: redis_host, port: redis_port, driver: :hiredis)
30
+ logger = Logger.new($stdout)
31
+ $stdout.sync = true
32
+
33
+ dropbox = Memot::Dropbox.new(config.auth[:dropbox][:access_token].to_s, redis)
34
+ evernote = Memot::Evernote.new(config.auth[:evernote][:token], config.auth[:evernote][:sandbox])
35
+ cli = Memot::Client.new(dropbox, evernote, logger)
36
+
37
+ if @options[:interval] < 1
38
+ # One-time execution
39
+ cli.update(config.notes)
40
+ exit 0
41
+ end
42
+
43
+ # Continuous execution
44
+
45
+ trap("INT") do
46
+ puts "\rExiting..."
47
+ exit 0
48
+ end
49
+
50
+ loop do
51
+ cli.update(config.notes)
52
+
53
+ interval = @options[:interval] * 60 - Time.now.subsec + 0.001
54
+ sleep(interval) if interval > 0
55
+ end
@@ -0,0 +1,13 @@
1
+ require "logger"
2
+ require "redis"
3
+ require "yaml"
4
+
5
+ require "memot/version"
6
+ require "memot/config"
7
+ require "memot/dropbox"
8
+ require "memot/evernote"
9
+ require "memot/markdown"
10
+ require "memot/client"
11
+
12
+ module Memot
13
+ end
@@ -0,0 +1,61 @@
1
+ module Memot
2
+ class Client
3
+ def initialize(dropbox, evernote, logger)
4
+ @dropbox = dropbox
5
+ @evernote = evernote
6
+ @logger = logger
7
+ end
8
+
9
+ def update(notes)
10
+ logger.info("Updating...")
11
+
12
+ need_update = []
13
+
14
+ notes.each_pair do |notebook, dropbox_path|
15
+ need_update << { notebook: notebook, updates: dropbox.parse_dir_tree!(dropbox_path) }
16
+ end
17
+
18
+ need_update.each do |update|
19
+ notebook = update[:notebook].to_s
20
+ update[:updates].each { |u| save_to_evernote(u[:dropbox_path], notebook, u[:revision]) }
21
+ end
22
+
23
+ logger.info("Finish")
24
+ end
25
+
26
+ def save_to_evernote(dropbox_path, notebook, revision)
27
+ note_body = Memot::Markdown.parse_markdown(dropbox.file_body_of(dropbox_path))
28
+ note_title = File.basename(dropbox_path)
29
+
30
+ begin
31
+ if (note_guid = evernote.get_note_guid(note_title, notebook)) == ""
32
+ evernote.create_note(note_title, note_body, notebook)
33
+ logger.info "Created: #{notebook}/#{note_title} (rev. #{revision})"
34
+ else
35
+ evernote.update_note(note_title, note_body, notebook, note_guid)
36
+ logger.info "Updated: #{notebook}/#{note_title} (rev. #{revision})"
37
+ end
38
+
39
+ rescue Memot::EvernoteRateLimitReachedError => e
40
+ sleep_interval = e.message.to_i + 60
41
+ logger.warn "Evernote rate limit exceeded, retry after #{sleep_interval} seconds."
42
+ sleep sleep_interval
43
+ retry
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def dropbox
50
+ @dropbox
51
+ end
52
+
53
+ def evernote
54
+ @evernote
55
+ end
56
+
57
+ def logger
58
+ @logger
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,73 @@
1
+ module Memot
2
+ class Config
3
+ class << self
4
+ def load_yaml(yaml_path)
5
+ yaml = symbolize_keys(YAML.load_file(yaml_path))
6
+ auth = yaml[:auth] || {}
7
+ notes = yaml[:notes] || {}
8
+
9
+ self.new(auth, notes)
10
+ end
11
+
12
+ def load_env
13
+ auth = {
14
+ dropbox: {
15
+ app_key: ENV["MEMOT_DROPBOX_APP_KEY"],
16
+ app_secret: ENV["MEMOT_DROPBOX_APP_SECRET"],
17
+ access_token: ENV["MEMOT_DROPBOX_ACCESS_TOKEN"],
18
+ },
19
+ evernote: {
20
+ token: ENV["MEMOT_EVERNOTE_TOKEN"],
21
+ sandbox: ENV["MEMOT_EVERNOTE_SANDBOX"].downcase == "true",
22
+ },
23
+ }
24
+
25
+ if ENV["MEMOT_NOTES"]
26
+ #
27
+ # daily:/memo/daily,reading:/memo/reading
28
+ # -> { daily: "/memo/daily", reading: "/memo/reading" }
29
+ #
30
+ notes = ENV["MEMOT_NOTES"].split(",").map { |pair| pair.split(":") }.inject({}) do |nts, kv|
31
+ nts[kv[0]] = kv[1]
32
+ nts
33
+ end
34
+ else
35
+ notes = {}
36
+ end
37
+
38
+ self.new(auth, notes)
39
+ end
40
+
41
+ private
42
+
43
+ def symbolize_keys(hash)
44
+ result = {}
45
+
46
+ hash.each_pair do |key, value|
47
+ result[key.to_sym] = if value.is_a? Array
48
+ value.each { |element| symbolize_keys(element) }
49
+ elsif value.is_a? Hash
50
+ symbolize_keys(value)
51
+ else
52
+ value
53
+ end
54
+ end
55
+
56
+ result
57
+ end
58
+ end
59
+
60
+ def initialize(auth, notes)
61
+ @auth = auth
62
+ @notes = notes
63
+ end
64
+
65
+ def auth
66
+ @auth
67
+ end
68
+
69
+ def notes
70
+ @notes
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,81 @@
1
+ require "dropbox_sdk"
2
+
3
+ module Memot
4
+ class Dropbox
5
+ class << self
6
+ def auth(app_key, app_secret)
7
+ flow = DropboxOAuth2FlowNoRedirect.new(app_key, app_secret)
8
+ puts "Access to this URL: #{flow.start}"
9
+ print "PIN code: "
10
+ code = gets.strip
11
+ flow.finish(code)
12
+ end
13
+ end
14
+
15
+ def initialize(access_token, redis)
16
+ @client = DropboxClient.new(access_token)
17
+ @redis = redis
18
+ end
19
+
20
+ def parse_dir_tree!(path)
21
+ latest_revision = get_revision(path)
22
+ updated_revision = latest_revision
23
+
24
+ need_update = []
25
+
26
+ client.metadata(path)["contents"].sort_by { |cont| cont["revision"] }.each do |cont|
27
+ cont_path = cont["path"]
28
+ cont_revision = cont["revision"]
29
+
30
+ unless cont["is_dir"]
31
+ if (cont_revision > latest_revision) && markdown?(cont_path)
32
+ need_update << { dropbox_path: cont_path, revision: cont_revision }
33
+ updated_revision = cont_revision
34
+ end
35
+ end
36
+ end
37
+
38
+ set_revision(path, updated_revision) if updated_revision > latest_revision
39
+
40
+ need_update
41
+ end
42
+
43
+ def file_body_of(path)
44
+ client.get_file(path)
45
+ end
46
+
47
+ private
48
+
49
+ def client
50
+ @client
51
+ end
52
+
53
+ def redis
54
+ @redis
55
+ end
56
+
57
+ def markdown?(path)
58
+ %w{.md .markdown}.include?(File.extname(path).downcase)
59
+ end
60
+
61
+ def dir_key_of(dir)
62
+ "memot:#{dir}"
63
+ end
64
+
65
+ def get_revision(dir)
66
+ key = dir_key_of(dir)
67
+
68
+ if redis.exists(key)
69
+ redis.get(key).to_i
70
+ else
71
+ set_revision(key, 0)
72
+ 0
73
+ end
74
+ end
75
+
76
+ def set_revision(dir, revision)
77
+ key = dir_key_of(dir)
78
+ redis.set(key, revision)
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,104 @@
1
+ require "evernote_oauth"
2
+
3
+ module Memot
4
+ class EvernoteError < StandardError; end
5
+ class EvernoteRateLimitReachedError < StandardError; end
6
+
7
+ class Evernote
8
+ def initialize(token, sandbox)
9
+ @token = token
10
+ @client = EvernoteOAuth::Client.new(token: token, sandbox: sandbox)
11
+ end
12
+
13
+ def create_note(title, body, notebook)
14
+ note = ::Evernote::EDAM::Type::Note.new
15
+ note.title = title.force_encoding("UTF-8")
16
+ note.content = create_note_content(body).force_encoding("UTF-8")
17
+ note.notebookGuid = get_notebook_guid(notebook)
18
+ note_store.createNote(token, note)
19
+
20
+ rescue ::Evernote::EDAM::Error::EDAMUserException, ::Evernote::EDAM::Error::EDAMSystemException => e
21
+ raise_error e
22
+ end
23
+
24
+ def update_note(title, body, notebook, note_guid)
25
+ note = note_store.getNote(token, note_guid, true, true, true, true)
26
+ note.title = title.force_encoding("UTF-8")
27
+ note.content = create_note_content(body).force_encoding("UTF-8")
28
+ note.notebookGuid = get_notebook_guid(notebook, false)
29
+ note_store.updateNote(token, note)
30
+
31
+ rescue ::Evernote::EDAM::Error::EDAMUserException, ::Evernote::EDAM::Error::EDAMSystemException => e
32
+ raise_error e
33
+ end
34
+
35
+ def get_note_guid(title, notebook)
36
+ notebook_guid = get_notebook_guid(notebook, false)
37
+ return "" if notebook_guid == ""
38
+
39
+ filter = ::Evernote::EDAM::NoteStore::NoteFilter.new
40
+ filter.notebookGuid = notebook_guid
41
+ spec = ::Evernote::EDAM::NoteStore::NotesMetadataResultSpec.new
42
+ spec.includeTitle = true
43
+ results = note_store.findNotesMetadata(token, filter, 0, 10000, spec).notes.select { |nt| nt.title == title }
44
+ results.length > 0 ? results.first.guid : ""
45
+
46
+ rescue ::Evernote::EDAM::Error::EDAMSystemException => e
47
+ raise_error e
48
+ end
49
+
50
+ def create_notebook(name, stack = "")
51
+ notebook = ::Evernote::EDAM::Type::Notebook.new
52
+ notebook.name = name
53
+ notebook.stack = stack unless stack == ""
54
+ note_store.createNotebook(token, notebook)
55
+
56
+ rescue ::Evernote::EDAM::Error::EDAMUserException, ::Evernote::EDAM::Error::EDAMSystemException => e
57
+ raise_error e
58
+ end
59
+
60
+ def get_notebook_guid(notebook, create = true)
61
+ results = note_store.listNotebooks.select { |nb| nb.name == notebook }
62
+
63
+ if results.length > 0
64
+ results.first.guid
65
+ else
66
+ create ? create_notebook(notebook).guid : ""
67
+ end
68
+ rescue ::Evernote::EDAM::Error::EDAMSystemException => e
69
+ raise_error e
70
+ end
71
+
72
+ private
73
+
74
+ def client
75
+ @client
76
+ end
77
+
78
+ def note_store
79
+ @note_store ||= client.note_store
80
+ end
81
+
82
+ def token
83
+ @token
84
+ end
85
+
86
+ def create_note_content(body)
87
+ content = <<EOS
88
+ <?xml version="1.0" encoding="UTF-8"?>
89
+ <!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">
90
+ <en-note>
91
+ #{body}
92
+ </en-note>
93
+ EOS
94
+ content
95
+ end
96
+
97
+ def raise_error(e)
98
+ raise EvernoteRateLimitReachedError, e.rateLimitDuration if e.errorCode == ::Evernote::EDAM::Error::EDAMErrorCode::RATE_LIMIT_REACHED
99
+
100
+ error_text = ::Evernote::EDAM::Error::EDAMErrorCode::VALUE_MAP[e.errorCode]
101
+ raise EvernoteError, "Exception raised (errorText: #{error_text})"
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,12 @@
1
+ require "redcarpet"
2
+
3
+ module Memot
4
+ class Markdown
5
+ def self.parse_markdown(markdown)
6
+ markdown = markdown.gsub("<", "&lt;").gsub(">", "&gt;")
7
+ renderer = Redcarpet::Markdown.new(Redcarpet::Render::XHTML, autolink: true)
8
+
9
+ renderer.render(markdown) rescue markdown
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module Memot
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'memot/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "memot"
8
+ spec.version = Memot::VERSION
9
+ spec.authors = ["dtan4"]
10
+ spec.email = ["dtanshi45@gmail.com"]
11
+ spec.description = %q{Markdown Memo Management Library}
12
+ spec.summary = %q{Markdown Memo Management Library}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "dropbox-sdk"
22
+ spec.add_dependency "evernote_oauth"
23
+ spec.add_dependency "redcarpet"
24
+
25
+ spec.add_dependency "redis"
26
+ spec.add_dependency "hiredis"
27
+
28
+ spec.add_development_dependency "bundler", "~> 1.3"
29
+ spec.add_development_dependency "rake"
30
+ spec.add_development_dependency "rspec"
31
+ spec.add_development_dependency "guard-rspec"
32
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Memot do
4
+ it 'should have a version number' do
5
+ Memot::VERSION.should_not be_nil
6
+ end
7
+
8
+ it 'should do something useful' do
9
+ false.should be_true
10
+ end
11
+ end
@@ -0,0 +1,2 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'memot'
metadata ADDED
@@ -0,0 +1,194 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: memot
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - dtan4
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-10-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dropbox-sdk
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: evernote_oauth
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: redcarpet
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: redis
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: hiredis
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.3'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.3'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: guard-rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: Markdown Memo Management Library
140
+ email:
141
+ - dtanshi45@gmail.com
142
+ executables:
143
+ - memot
144
+ extensions: []
145
+ extra_rdoc_files: []
146
+ files:
147
+ - ".gitignore"
148
+ - ".memot.yml.sample"
149
+ - ".rspec"
150
+ - ".travis.yml"
151
+ - Dockerfile
152
+ - Gemfile
153
+ - Guardfile
154
+ - LICENSE.txt
155
+ - README.md
156
+ - Rakefile
157
+ - bin/memot
158
+ - lib/memot.rb
159
+ - lib/memot/client.rb
160
+ - lib/memot/config.rb
161
+ - lib/memot/dropbox.rb
162
+ - lib/memot/evernote.rb
163
+ - lib/memot/markdown.rb
164
+ - lib/memot/version.rb
165
+ - memot.gemspec
166
+ - spec/memot_spec.rb
167
+ - spec/spec_helper.rb
168
+ homepage: ''
169
+ licenses:
170
+ - MIT
171
+ metadata: {}
172
+ post_install_message:
173
+ rdoc_options: []
174
+ require_paths:
175
+ - lib
176
+ required_ruby_version: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ required_rubygems_version: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: '0'
186
+ requirements: []
187
+ rubyforge_project:
188
+ rubygems_version: 2.4.5.1
189
+ signing_key:
190
+ specification_version: 4
191
+ summary: Markdown Memo Management Library
192
+ test_files:
193
+ - spec/memot_spec.rb
194
+ - spec/spec_helper.rb