paperless 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|