paperless 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +30 -0
- data/bin/CocoaDialog.app/Contents/Info.plist +28 -0
- data/bin/CocoaDialog.app/Contents/MacOS/CocoaDialog +0 -0
- data/bin/CocoaDialog.app/Contents/PkgInfo +1 -0
- data/bin/CocoaDialog.app/Contents/Resources/COPYING +281 -0
- data/bin/CocoaDialog.app/Contents/Resources/Changelog +73 -0
- data/bin/CocoaDialog.app/Contents/Resources/Info.plist +28 -0
- data/bin/CocoaDialog.app/Contents/Resources/InfoPlist.strings +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/Inputbox.nib/classes.nib +51 -0
- data/bin/CocoaDialog.app/Contents/Resources/Inputbox.nib/info.nib +16 -0
- data/bin/CocoaDialog.app/Contents/Resources/Inputbox.nib/keyedobjects.nib +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/MainMenu.nib/classes.nib +7 -0
- data/bin/CocoaDialog.app/Contents/Resources/MainMenu.nib/info.nib +21 -0
- data/bin/CocoaDialog.app/Contents/Resources/MainMenu.nib/info.nib.orig +21 -0
- data/bin/CocoaDialog.app/Contents/Resources/MainMenu.nib/objects.nib +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/MainMenu.nib/objects.nib.orig +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/Msgbox.nib/classes.nib +27 -0
- data/bin/CocoaDialog.app/Contents/Resources/Msgbox.nib/info.nib +16 -0
- data/bin/CocoaDialog.app/Contents/Resources/Msgbox.nib/keyedobjects.nib +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/PopUpButton.nib/classes.nib +55 -0
- data/bin/CocoaDialog.app/Contents/Resources/PopUpButton.nib/info.nib +16 -0
- data/bin/CocoaDialog.app/Contents/Resources/PopUpButton.nib/keyedobjects.nib +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/Progressbar.nib/classes.nib +13 -0
- data/bin/CocoaDialog.app/Contents/Resources/Progressbar.nib/info.nib +16 -0
- data/bin/CocoaDialog.app/Contents/Resources/Progressbar.nib/keyedobjects.nib +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/SecureInputbox.nib/classes.nib +40 -0
- data/bin/CocoaDialog.app/Contents/Resources/SecureInputbox.nib/info.nib +16 -0
- data/bin/CocoaDialog.app/Contents/Resources/SecureInputbox.nib/keyedobjects.nib +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/Textbox.nib/classes.nib +26 -0
- data/bin/CocoaDialog.app/Contents/Resources/Textbox.nib/info.nib +16 -0
- data/bin/CocoaDialog.app/Contents/Resources/Textbox.nib/keyedobjects.nib +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/atom.icns +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/cocoadialog.icns +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/computer.icns +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/document.icns +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/find.icns +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/finder.icns +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/firewire.icns +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/folder.icns +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/gear.icns +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/globe.icns +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/hazard.icns +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/heart.icns +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/hourglass.icns +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/info.icns +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/ipod.icns +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/person.icns +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/sound.icns +0 -0
- data/bin/CocoaDialog.app/Contents/Resources/x.icns +0 -0
- data/bin/openmeta +0 -0
- data/bin/paperless +234 -0
- data/lib/paperless/date_search.rb +96 -0
- data/lib/paperless/engine.rb +220 -0
- data/lib/paperless/ocr_engines/acrobat.rb +51 -0
- data/lib/paperless/ocr_engines/devonthinkpro.rb +26 -0
- data/lib/paperless/ocr_engines/pdfpen.rb +32 -0
- data/lib/paperless/ocr_engines/pdfpenpro.rb +32 -0
- data/lib/paperless/rule.rb +82 -0
- data/lib/paperless/services/devonthinkpro.rb +54 -0
- data/lib/paperless/services/evernote.rb +55 -0
- data/lib/paperless/services/finder.rb +47 -0
- data/lib/paperless/version.rb +3 -0
- data/lib/paperless.rb +14 -0
- data/paperless.rdoc +5 -0
- metadata +233 -0
@@ -0,0 +1,220 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'pdf/reader'
|
3
|
+
require 'paperless/date_search'
|
4
|
+
include DateSearch
|
5
|
+
|
6
|
+
module Paperless
|
7
|
+
|
8
|
+
PDF_EXT = 'pdf'
|
9
|
+
DATE_VAR = '<date>'
|
10
|
+
MATCH_VAR = '<match>'
|
11
|
+
FILEDATE = 'filedate'
|
12
|
+
TODAY = 'today'
|
13
|
+
|
14
|
+
class Engine
|
15
|
+
|
16
|
+
PDFPEN_ENGINE = 'pdfpen'
|
17
|
+
PDFPENPRO_ENGINE = 'pdfpenpro'
|
18
|
+
ACROBAT_ENGINE = 'acrobat'
|
19
|
+
DEVONTHINKPRO_ENGINE = 'devonthinkpro'
|
20
|
+
DEVONTHINKPRO_SERVICE = 'devonthinkpro'
|
21
|
+
FINDER_SERVICE = 'finder'
|
22
|
+
EVERNOTE_SERVICE = 'evernote'
|
23
|
+
|
24
|
+
attr_reader :service
|
25
|
+
|
26
|
+
def initialize(options)
|
27
|
+
@destination = nil
|
28
|
+
@service = nil
|
29
|
+
@title = nil
|
30
|
+
@date = DateTime.now
|
31
|
+
@tags = Array.new()
|
32
|
+
|
33
|
+
@file = options[:file]
|
34
|
+
@text_ext = options[:text_ext]
|
35
|
+
@pdf_ext = [Paperless::PDF_EXT]
|
36
|
+
@default_service = options[:default_service]
|
37
|
+
@date_format = options[:date_format]
|
38
|
+
@date_locale = options[:date_locale]
|
39
|
+
@date_default = options[:date_default]
|
40
|
+
@default_destination = options[:default_destination]
|
41
|
+
@rules = Array.new()
|
42
|
+
|
43
|
+
options[:rules].each do |rule|
|
44
|
+
@rules.push Paperless::Rule.new(rule)
|
45
|
+
end
|
46
|
+
|
47
|
+
@ocr_engine = options[:ocr_engine]||false
|
48
|
+
end
|
49
|
+
|
50
|
+
def process_rules
|
51
|
+
markdown_ext = ['md','mmd']
|
52
|
+
text_ext = @text_ext + markdown_ext
|
53
|
+
file_ext = File.extname(@file).gsub(/\./,'')
|
54
|
+
|
55
|
+
if file_ext == Paperless::PDF_EXT
|
56
|
+
|
57
|
+
self.process_pdf
|
58
|
+
|
59
|
+
elsif text_ext.index file_ext
|
60
|
+
|
61
|
+
self.process_text
|
62
|
+
|
63
|
+
else
|
64
|
+
puts "Unknown file type. No rules were processed."
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def add_tags(tags)
|
69
|
+
if tags.length > 0
|
70
|
+
@tags = (@tags + tags).collect {|x| x = x.downcase }
|
71
|
+
@tags.uniq!
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def set_destination(destination)
|
76
|
+
@destination = destination if destination && @destination.nil?
|
77
|
+
end
|
78
|
+
|
79
|
+
def set_title(title)
|
80
|
+
@title = title if title && @title.nil?
|
81
|
+
end
|
82
|
+
|
83
|
+
def set_service(service)
|
84
|
+
@service = service if service && @service.nil?
|
85
|
+
end
|
86
|
+
|
87
|
+
def set_date_default()
|
88
|
+
puts "Using default date..."
|
89
|
+
# Set the default date to the date of the file or else to now
|
90
|
+
if @date_default == Paperless::FILEDATE
|
91
|
+
t = File.stat(@file).mtime
|
92
|
+
@date = Date.new(t.year,t.month,t.day)
|
93
|
+
else
|
94
|
+
@date = DateTime.now
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def process_rules_engine(text)
|
99
|
+
self.set_date_default if @date.nil?
|
100
|
+
# Process each page and pass it through the rules engine
|
101
|
+
@rules.each do |rule|
|
102
|
+
rule.set_date(@date,@date_format)
|
103
|
+
if !rule.matched && rule.match(@file, text)
|
104
|
+
self.add_tags(rule.tags)
|
105
|
+
self.set_destination(rule.destination)
|
106
|
+
self.set_title(rule.title)
|
107
|
+
self.set_service(rule.service)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def process_text
|
113
|
+
puts "Processing Text file..."
|
114
|
+
|
115
|
+
text = File.open(@file, "rb") {|io| io.read}
|
116
|
+
|
117
|
+
# Verify that we need to search for date or just set to today
|
118
|
+
# Need to prcess file for date in case the rules need to use it.
|
119
|
+
# First check if there are actually any date rules
|
120
|
+
@rules.each do |rule|
|
121
|
+
if rule.condition == Paperless::DATE_VAR
|
122
|
+
@date = date_search(text,@date_locale)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Process each page and pass it through the rules engine
|
127
|
+
process_rules_engine(text)
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
def process_pdf
|
132
|
+
puts "Processing PDF pages..."
|
133
|
+
|
134
|
+
reader = PDF::Reader.new(@file)
|
135
|
+
|
136
|
+
# Verify that we need to search for date or just set to today
|
137
|
+
# Need to prcess file for date in case the rules need to use it.
|
138
|
+
# First check if there are actually any date rules
|
139
|
+
@rules.each do |rule|
|
140
|
+
if rule.condition == Paperless::DATE_VAR
|
141
|
+
reader.pages.each do |page|
|
142
|
+
break if @date = date_search(page.text,@date_locale)
|
143
|
+
end
|
144
|
+
break
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Process each page and pass it through the rules engine
|
149
|
+
reader.pages.each do |page|
|
150
|
+
process_rules_engine(page.text)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def ocr
|
155
|
+
puts "Running OCR on file with #{@ocr_engine}"
|
156
|
+
ocr_engine = case @ocr_engine
|
157
|
+
when /^#{PDFPENPRO_ENGINE}$/i then PaperlessOCR::PDFpenPro.new
|
158
|
+
when /^#{PDFPEN_ENGINE}$/i then PaperlessOCR::PDFpen.new
|
159
|
+
when /^#{ACROBAT_ENGINE}$/i then PaperlessOCR::Acrobat.new
|
160
|
+
when /^#{DEVONTHINKPRO_ENGINE}$/i then PaperlessOCR::DevonThinkPro.new
|
161
|
+
else false
|
162
|
+
end
|
163
|
+
|
164
|
+
if ocr_engine
|
165
|
+
ocr_engine.ocr({:file => @file})
|
166
|
+
else
|
167
|
+
puts "WARNING: No valid OCR engine was defined."
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def create(options)
|
172
|
+
# May need to externalize this so other methods can access it.
|
173
|
+
service = case @service.nil? ? @default_service : @service
|
174
|
+
when /^#{EVERNOTE_SERVICE}$/i then PaperlessService::Evernote.new
|
175
|
+
when /^#{FINDER_SERVICE}$/i then PaperlessService::Finder.new
|
176
|
+
when /^#{DEVONTHINKPRO_SERVICE}$/i then PaperlessService::DevonThinkPro.new
|
177
|
+
else false
|
178
|
+
end
|
179
|
+
|
180
|
+
if service
|
181
|
+
self.print
|
182
|
+
|
183
|
+
destination = @destination.nil? ? @default_destination : @destination
|
184
|
+
# :created => @date
|
185
|
+
service.create({
|
186
|
+
:delete => options[:delete],
|
187
|
+
:destination => destination,
|
188
|
+
:text_ext => @text_ext,
|
189
|
+
:file => @file,
|
190
|
+
:date => @date,
|
191
|
+
:title => @title,
|
192
|
+
:tags => @tags
|
193
|
+
})
|
194
|
+
else
|
195
|
+
puts "WARNING: No valid Service was defined."
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def print
|
200
|
+
service = @service.nil? ? @default_service : @service
|
201
|
+
title = @title.nil? ? File.basename(@file) : @title
|
202
|
+
|
203
|
+
destination = @destination.nil? ? @default_destination : @destination
|
204
|
+
if destination == PaperlessService::Finder::NO_MOVE && service == PaperlessService::FINDER.downcase
|
205
|
+
destination = File.dirname(@file)
|
206
|
+
end
|
207
|
+
|
208
|
+
puts "* ---------------------------------------------"
|
209
|
+
puts "* File: #{@file}"
|
210
|
+
puts "* Service: #{service}"
|
211
|
+
puts "* Destination: #{destination}"
|
212
|
+
puts "* Title: #{title}"
|
213
|
+
puts "* Date: #{@date.strftime('%Y-%m-%d')}"
|
214
|
+
puts "* Tags: #{@tags.join(', ')}"
|
215
|
+
puts "* ---------------------------------------------"
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'appscript'
|
2
|
+
include Appscript
|
3
|
+
|
4
|
+
module PaperlessOCR
|
5
|
+
|
6
|
+
ACROBAT = 'Adobe Acrobat Pro'
|
7
|
+
|
8
|
+
class PDFpen
|
9
|
+
def initialize
|
10
|
+
@engine = PaperlessOCR::ACROBAT
|
11
|
+
@app = app(@engine)
|
12
|
+
@app.activate
|
13
|
+
end
|
14
|
+
|
15
|
+
def ocr(options)
|
16
|
+
|
17
|
+
begin
|
18
|
+
|
19
|
+
rescue
|
20
|
+
puts "WARNING: There was an error OCRing the document with #{@engine}: #{$!}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
__END__
|
28
|
+
|
29
|
+
The Following does not work with Acrobat X
|
30
|
+
|
31
|
+
tell application "Adobe Acrobat Professional"
|
32
|
+
activate
|
33
|
+
open theFile
|
34
|
+
tell application "System Events"
|
35
|
+
tell process "Acrobat"
|
36
|
+
tell menu bar 1
|
37
|
+
tell menu "Document"
|
38
|
+
tell menu item "OCR Text Recognition"
|
39
|
+
tell menu 1
|
40
|
+
click menu item "Recognize Text Using OCR..."
|
41
|
+
end tell
|
42
|
+
end tell
|
43
|
+
end tell
|
44
|
+
|
45
|
+
end tell
|
46
|
+
keystroke return
|
47
|
+
end tell
|
48
|
+
end tell
|
49
|
+
save the front document
|
50
|
+
close the front document
|
51
|
+
end tell
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'appscript'
|
2
|
+
include Appscript
|
3
|
+
|
4
|
+
module PaperlessOCR
|
5
|
+
|
6
|
+
DEVONTHINKPRO = 'DEVONthink Pro'
|
7
|
+
|
8
|
+
class DevonThinkPro
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@engine = PaperlessOCR::DEVONTHINKPRO
|
12
|
+
@app = app(@engine)
|
13
|
+
@app.activate
|
14
|
+
end
|
15
|
+
|
16
|
+
def ocr(options)
|
17
|
+
begin
|
18
|
+
app("System Events").processes[@engine].visible.set(false)
|
19
|
+
@app.ocr(:file => options[:file])
|
20
|
+
rescue
|
21
|
+
puts "WARNING: There was an error OCRing the document with #{@engine}: #{$!}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'appscript'
|
2
|
+
include Appscript
|
3
|
+
|
4
|
+
module PaperlessOCR
|
5
|
+
|
6
|
+
PDFPEN = 'PDFpen'
|
7
|
+
|
8
|
+
class PDFpen
|
9
|
+
def initialize
|
10
|
+
@engine = PaperlessOCR::PDFPEN
|
11
|
+
@app = app(@engine)
|
12
|
+
@app.activate
|
13
|
+
end
|
14
|
+
|
15
|
+
def ocr(options)
|
16
|
+
begin
|
17
|
+
doc = @app.open MacTypes::Alias.path(options[:file])
|
18
|
+
doc.ocr
|
19
|
+
|
20
|
+
app("System Events").processes[@engine].visible.set(false)
|
21
|
+
|
22
|
+
while doc.performing_ocr.get
|
23
|
+
sleep 1
|
24
|
+
end
|
25
|
+
doc.close(:saving => :yes)
|
26
|
+
rescue
|
27
|
+
puts "WARNING: There was an error OCRing the document with #{@engine}: #{$!}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'appscript'
|
2
|
+
include Appscript
|
3
|
+
|
4
|
+
module PaperlessOCR
|
5
|
+
|
6
|
+
PDFPENPRO = 'PDFpenPro'
|
7
|
+
|
8
|
+
class PDFpenPro
|
9
|
+
def initialize
|
10
|
+
@engine = PaperlessOCR::PDFPENPRO
|
11
|
+
@app = app(@engine)
|
12
|
+
@app.activate
|
13
|
+
end
|
14
|
+
|
15
|
+
def ocr(options)
|
16
|
+
begin
|
17
|
+
doc = @app.open MacTypes::Alias.path(options[:file])
|
18
|
+
doc.ocr
|
19
|
+
|
20
|
+
app("System Events").processes[@engine].visible.set(false)
|
21
|
+
|
22
|
+
while doc.performing_ocr.get
|
23
|
+
sleep 1
|
24
|
+
end
|
25
|
+
doc.close(:saving => :yes)
|
26
|
+
rescue
|
27
|
+
puts "WARNING: There was an error OCRing the document with #{@engine}: #{$!}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Paperless
|
2
|
+
|
3
|
+
class Rule
|
4
|
+
|
5
|
+
def initialize(options)
|
6
|
+
# @todo: Add logic to validate rule has proper settings
|
7
|
+
|
8
|
+
@scope = options['scope'].split
|
9
|
+
@condition = options['condition']
|
10
|
+
@destination = options['destination']
|
11
|
+
@service = options['service']
|
12
|
+
@title = options['title']
|
13
|
+
@date = options['date']
|
14
|
+
@description = options['description']
|
15
|
+
@tags = options['tags'].nil? ? Array.new : options['tags'].split
|
16
|
+
@date_stamp = DateTime.now
|
17
|
+
@date_default_format = '%Y-%m-%d'
|
18
|
+
@matched = false
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :matched, :tags, :destination, :condition, :title, :date, :service
|
22
|
+
|
23
|
+
def set_date(date,format)
|
24
|
+
@date_stamp = date
|
25
|
+
@date_default_format = format
|
26
|
+
end
|
27
|
+
|
28
|
+
def match(file,text)
|
29
|
+
return @matched if @matched
|
30
|
+
|
31
|
+
if @condition == Paperless::DATE_VAR
|
32
|
+
@date = date
|
33
|
+
@matched = true
|
34
|
+
else
|
35
|
+
@scope.each do |type|
|
36
|
+
case type
|
37
|
+
when 'content' then
|
38
|
+
self.match_text(text)
|
39
|
+
when 'filename' then
|
40
|
+
self.match_text(file)
|
41
|
+
else
|
42
|
+
puts "WARNING: Unknown scope defined - #{type}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
return @matched
|
47
|
+
end
|
48
|
+
|
49
|
+
def match_text(text)
|
50
|
+
match = text.match(/#{@condition}/i) {|md| md[0]}
|
51
|
+
unless match.nil?
|
52
|
+
puts "Rule Matched: #{@description}"
|
53
|
+
self.sub_vars(match.gsub(/\s*$/,'')) # chomp! was not working... had to do this
|
54
|
+
@matched = true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def sub_var(attribute, value)
|
59
|
+
unless attribute.nil?
|
60
|
+
attribute.gsub!(/#{Paperless::MATCH_VAR}/, value)
|
61
|
+
attribute.gsub!(/#{Paperless::DATE_VAR}/, @date_stamp.strftime(@date_default_format))
|
62
|
+
|
63
|
+
# Custom date formats set at the rule level
|
64
|
+
custom_date_regex = "#{Paperless::DATE_VAR.chop}=([a-zA-Z\%\-]+)>"
|
65
|
+
if match = attribute.match(/#{custom_date_regex}/)
|
66
|
+
attribute.gsub!(/#{custom_date_regex}/, @date_stamp.strftime(match[1]))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
attribute
|
70
|
+
end
|
71
|
+
|
72
|
+
def sub_vars(value)
|
73
|
+
# Need to do substituation for supported variables
|
74
|
+
@destination = self.sub_var(@destination,value)
|
75
|
+
@title = self.sub_var(@title,value)
|
76
|
+
@date = self.sub_var(@date,value)
|
77
|
+
@tags.collect! {|tag| tag = self.sub_var(tag,value) }
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
include FileUtils
|
3
|
+
require 'appscript'
|
4
|
+
include Appscript
|
5
|
+
|
6
|
+
module PaperlessService
|
7
|
+
|
8
|
+
DEVONTHINKPRO = 'DEVONthink Pro'
|
9
|
+
|
10
|
+
class DevonThinkPro
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@app = app(PaperlessService::DEVONTHINKPRO)
|
14
|
+
@app.activate
|
15
|
+
end
|
16
|
+
|
17
|
+
def create(options)
|
18
|
+
destination = options[:destination]
|
19
|
+
date = options[:date]
|
20
|
+
from_file = options[:file]
|
21
|
+
title = options[:title] || File.basename(from_file)
|
22
|
+
tags = options[:tags].collect!{|x| x="'#{x}'"} # Add quotes around each tag in case there is a space
|
23
|
+
|
24
|
+
time = Time.new(date.year, date.month, date.day)
|
25
|
+
FileUtils.touch from_file, :mtime => time
|
26
|
+
|
27
|
+
if tags.length > 0
|
28
|
+
# Add open meta tags to file
|
29
|
+
system("#{OPENMETA} -p '#{from_file}' -a #{tags.join(' ')}")
|
30
|
+
end
|
31
|
+
|
32
|
+
# Extract the database and folder name from the destination
|
33
|
+
matches = destination.match(/(.+)::(.+)/)
|
34
|
+
dt_database = matches[1]
|
35
|
+
dt_folder = matches[2]
|
36
|
+
|
37
|
+
unless dt_folder && dt_database
|
38
|
+
raise "Unable to determine database and folder for DevonThinkPro: #{destination}"
|
39
|
+
end
|
40
|
+
|
41
|
+
db_conn = @app.open_database(dt_database)
|
42
|
+
|
43
|
+
app("System Events").processes[PaperlessService::DEVONTHINKPRO].visible.set(false)
|
44
|
+
|
45
|
+
group = @app.create_location(dt_folder, {:in => db_conn})
|
46
|
+
@app.import(from_file, {:to => group, :name => title} )
|
47
|
+
|
48
|
+
if options[:delete]
|
49
|
+
FileUtils.rm from_file, :force => true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
include FileUtils
|
3
|
+
require 'markdown'
|
4
|
+
require 'appscript'
|
5
|
+
include Appscript
|
6
|
+
|
7
|
+
module PaperlessService
|
8
|
+
|
9
|
+
EVERNOTE = 'Evernote'
|
10
|
+
|
11
|
+
class Evernote
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@app = app(PaperlessService::EVERNOTE)
|
15
|
+
@app.activate
|
16
|
+
end
|
17
|
+
|
18
|
+
def create(options)
|
19
|
+
destination = options[:destination]
|
20
|
+
date = options[:date]
|
21
|
+
from_file = options[:file]
|
22
|
+
title = options[:title] || File.basename(from_file)
|
23
|
+
tags = options[:tags]
|
24
|
+
text_ext = options[:text_ext]
|
25
|
+
|
26
|
+
create_options = { :created => date }
|
27
|
+
file_ext = File.extname(from_file.gsub(/\./,''))
|
28
|
+
|
29
|
+
if text_ext.index file_ext
|
30
|
+
create_options[:with_text] = File.open(from_file, "rb") {|io| io.read}
|
31
|
+
else
|
32
|
+
if file_ext.match(/md$/i)
|
33
|
+
# If this is a mardown file insert it into Evernote as html
|
34
|
+
text = File.open(from_file, "rb") {|io| io.read}
|
35
|
+
create_options[:with_html] = Markdown.new(text).to_html
|
36
|
+
else
|
37
|
+
# Create a note from a file and let Evernote choose how to attach the file
|
38
|
+
create_options[:from_file] = MacTypes::FileURL.path(from_file)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
create_options[:tags] = tags if tags.length > 0
|
43
|
+
create_options[:notebook] = destination if destination
|
44
|
+
|
45
|
+
@app.create_note(create_options)
|
46
|
+
|
47
|
+
if options[:delete]
|
48
|
+
FileUtils.rm from_file, :force => true
|
49
|
+
end
|
50
|
+
|
51
|
+
@app.synchronize
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
include FileUtils
|
3
|
+
|
4
|
+
module PaperlessService
|
5
|
+
|
6
|
+
FINDER = 'Finder'
|
7
|
+
|
8
|
+
class Finder
|
9
|
+
|
10
|
+
NO_MOVE = '<nomove>'
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@app = app(PaperlessService::FINDER)
|
14
|
+
@app.activate
|
15
|
+
end
|
16
|
+
|
17
|
+
def create(options)
|
18
|
+
destination = options[:destination]
|
19
|
+
date = options[:date]
|
20
|
+
from_file = options[:file]
|
21
|
+
title = options[:title]
|
22
|
+
tags = options[:tags].collect!{|x| x="'#{x}'"} # Add quotes around each tag in case there is a space
|
23
|
+
|
24
|
+
if destination == NO_MOVE || destination == File.dirname(from_file)
|
25
|
+
new_filename = File.join(File.dirname(from_file), title + File.extname(from_file))
|
26
|
+
else
|
27
|
+
FileUtils.mkdir_p destination unless File.exists?(destination)
|
28
|
+
new_filename = File.join(destination, title + File.extname(from_file))
|
29
|
+
end
|
30
|
+
|
31
|
+
FileUtils.cp from_file, new_filename, :force => true
|
32
|
+
|
33
|
+
time = Time.new(date.year, date.month, date.day)
|
34
|
+
FileUtils.touch new_filename, {:mtime => time}
|
35
|
+
|
36
|
+
if tags.length > 0
|
37
|
+
# Add open meta tags to file
|
38
|
+
system("#{OPENMETA} -p '#{new_filename}' -a #{tags.join(' ')}")
|
39
|
+
end
|
40
|
+
|
41
|
+
if options[:delete] && from_file != new_filename
|
42
|
+
FileUtils.rm from_file, :force => true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
data/lib/paperless.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'paperless/version.rb'
|
2
|
+
require 'paperless/engine.rb'
|
3
|
+
require 'paperless/rule.rb'
|
4
|
+
require 'paperless/date_search.rb'
|
5
|
+
require 'paperless/services/evernote.rb'
|
6
|
+
require 'paperless/services/devonthinkpro.rb'
|
7
|
+
require 'paperless/services/finder.rb'
|
8
|
+
require 'paperless/ocr_engines/acrobat.rb'
|
9
|
+
require 'paperless/ocr_engines/pdfpen.rb'
|
10
|
+
require 'paperless/ocr_engines/pdfpenpro.rb'
|
11
|
+
require 'paperless/ocr_engines/devonthinkpro.rb'
|
12
|
+
|
13
|
+
# Add requires for other files you add to your project here, so
|
14
|
+
# you just need to require this one file in your bin file
|