rmsgen 0.0.5 → 0.0.6
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/lib/acts_like/string.rb +13 -0
- data/lib/rmsgen.rb +15 -3
- data/lib/rmsgen/compresser.rb +6 -7
- data/lib/rmsgen/fs_polnote_group.rb +13 -3
- data/lib/rmsgen/imap_client.rb +60 -0
- data/lib/rmsgen/imap_polnote_group.rb +14 -47
- data/lib/rmsgen/inquirer.rb +4 -10
- data/lib/rmsgen/part.rb +19 -0
- data/lib/rmsgen/part_group.rb +41 -13
- data/lib/rmsgen/parts/duration.rb +7 -0
- data/lib/rmsgen/parts/footer.rb +7 -0
- data/lib/rmsgen/parts/header.rb +9 -0
- data/lib/rmsgen/parts/indented_line.rb +7 -0
- data/lib/rmsgen/parts/plain_text.rb +5 -0
- data/lib/rmsgen/parts/polnote_url_request.rb +8 -0
- data/lib/rmsgen/parts/url.rb +5 -0
- data/lib/rmsgen/polnote.rb +16 -4
- data/lib/rmsgen/polnote_group.rb +19 -0
- data/lib/rmsgen/runtime.rb +17 -22
- data/lib/rmsgen/titleizer.rb +5 -10
- data/lib/rmsgen/version.rb +1 -1
- data/spec/fixtures/urgent_note +1 -2
- data/spec/imap_client_spec.rb +70 -0
- data/spec/imap_polnote_group_spec.rb +13 -24
- data/spec/part_group_spec.rb +3 -6
- data/spec/part_spec.rb +51 -0
- data/spec/polnote_group.rb +24 -0
- data/spec/polnote_spec.rb +2 -7
- data/spec/runtime_spec.rb +3 -13
- metadata +16 -2
data/lib/rmsgen.rb
CHANGED
@@ -2,6 +2,17 @@ require 'yaml'
|
|
2
2
|
require 'erb'
|
3
3
|
|
4
4
|
module Rmsgen
|
5
|
+
%w{ header
|
6
|
+
footer
|
7
|
+
plain_text
|
8
|
+
url
|
9
|
+
polnote_url_request
|
10
|
+
indented_line
|
11
|
+
duration
|
12
|
+
}.each do |fname|
|
13
|
+
require File.join(File.dirname(__FILE__), 'rmsgen', 'parts', fname)
|
14
|
+
end
|
15
|
+
|
5
16
|
%w{ part_group
|
6
17
|
polnote
|
7
18
|
titleizer
|
@@ -9,13 +20,14 @@ module Rmsgen
|
|
9
20
|
script
|
10
21
|
inquirer
|
11
22
|
runtime
|
23
|
+
part
|
12
24
|
link
|
25
|
+
imap_client
|
13
26
|
imap_polnote_group
|
14
27
|
fs_polnote_group
|
28
|
+
polnote_group
|
29
|
+
|
15
30
|
}.each do |fname|
|
16
31
|
require File.join(File.dirname(__FILE__), 'rmsgen', fname)
|
17
32
|
end
|
18
33
|
end
|
19
|
-
|
20
|
-
|
21
|
-
|
data/lib/rmsgen/compresser.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
module Rmsgen
|
2
2
|
class Compresser
|
3
|
-
def initialize(
|
4
|
-
@
|
5
|
-
@parts = polnote.parts
|
3
|
+
def initialize(part_group=[])
|
4
|
+
@part_group = part_group
|
6
5
|
run!
|
7
6
|
end
|
8
7
|
|
9
8
|
def body
|
10
|
-
@
|
9
|
+
@part_group.join PartGroup::DELIMETER
|
11
10
|
end
|
12
11
|
|
13
12
|
private
|
@@ -19,15 +18,15 @@ module Rmsgen
|
|
19
18
|
end
|
20
19
|
|
21
20
|
def rm_header
|
22
|
-
@
|
21
|
+
@part_group.delete_if { |x| x.is_a?(Rmsgen::Parts::Header) }
|
23
22
|
end
|
24
23
|
|
25
24
|
def rm_footer
|
26
|
-
@
|
25
|
+
@part_group.delete_if { |x| x.is_a?(Rmsgen::Parts::Footer) }
|
27
26
|
end
|
28
27
|
|
29
28
|
def single_line_paragraphs
|
30
|
-
@
|
29
|
+
@part_group.each { |part| part.gsub!("\n", ' ') }
|
31
30
|
end
|
32
31
|
end
|
33
32
|
end
|
@@ -1,12 +1,22 @@
|
|
1
1
|
module Rmsgen
|
2
2
|
class FsPolnoteGroup
|
3
3
|
def initialize(dir=nil)
|
4
|
-
|
5
|
-
@
|
6
|
-
@notes = @raw_notes.map { |note| Rmsgen::Polnote.new(:body => note) }
|
4
|
+
@note_bodies = note_bodies_from_directory(dir)
|
5
|
+
@notes = build_many_polnotes(@note_bodies)
|
7
6
|
end
|
7
|
+
|
8
8
|
def all
|
9
9
|
@notes
|
10
10
|
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def note_bodies_from_directory(dir)
|
15
|
+
Dir["#{dir}/*"].map { |f| File.read(f) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def build_many_polnotes(note_bodies)
|
19
|
+
note_bodies.map { |body| Rmsgen::Polnote.new(:body => body) }
|
20
|
+
end
|
11
21
|
end
|
12
22
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'rmsgen'
|
2
|
+
require 'net/imap'
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module Rmsgen
|
6
|
+
class IMAPClient
|
7
|
+
INBOX = 'INBOX'
|
8
|
+
RMS_EMAIL = 'rms@gnu.org'
|
9
|
+
RFC822 = 'RFC822'
|
10
|
+
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
def initialize(options)
|
14
|
+
@server = options['imap_server']
|
15
|
+
@login = options['imap_login']
|
16
|
+
@password = options['imap_password']
|
17
|
+
@imap_client = Net::IMAP.new(@server)
|
18
|
+
end
|
19
|
+
|
20
|
+
def_delegators :@imap_client, :select, :search, :fetch, :copy, :store, :expunge
|
21
|
+
|
22
|
+
def authenticate
|
23
|
+
@imap_client.authenticate('LOGIN', @login, @password)
|
24
|
+
end
|
25
|
+
|
26
|
+
def fetch_polnote_messages_from_inbox(&block)
|
27
|
+
authenticate
|
28
|
+
select INBOX
|
29
|
+
find_all_from_rms(&block)
|
30
|
+
end
|
31
|
+
|
32
|
+
def find_by_id(id)
|
33
|
+
select INBOX
|
34
|
+
fetch_message_body(id)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def find_all_from_rms
|
40
|
+
search_for_notes.map do |id|
|
41
|
+
if block_given?
|
42
|
+
yield(fetch_message_body(id), id)
|
43
|
+
else
|
44
|
+
fetch_message_body(id)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def search_for_notes(&block)
|
50
|
+
search(["FROM", RMS_EMAIL], &block)
|
51
|
+
end
|
52
|
+
|
53
|
+
def fetch_message_body(id)
|
54
|
+
fetch_result = fetch id, RFC822
|
55
|
+
if fetch_result && fetch_result.any?
|
56
|
+
fetch_result[0].attr[RFC822]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -1,26 +1,14 @@
|
|
1
1
|
module Rmsgen
|
2
2
|
class IMAPPolnoteGroup
|
3
|
-
require 'net/imap'
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
def initialize(options={})
|
8
|
-
@imap_options = options
|
9
|
-
@login = options['imap_login']
|
10
|
-
@password = options['imap_password']
|
11
|
-
@note_ids = init_note_ids || []
|
12
|
-
end
|
13
|
-
|
14
|
-
def fetch_notes
|
15
|
-
authenticate
|
16
|
-
follow_inbox
|
17
|
-
find_all_from_rms
|
4
|
+
def initialize(imap_client)
|
5
|
+
@imap_client = imap_client
|
18
6
|
end
|
19
7
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
8
|
+
def all
|
9
|
+
@imap_client.fetch_polnote_messages_from_inbox do |body, id|
|
10
|
+
Polnote.new :body => body, :id => id
|
11
|
+
end
|
24
12
|
end
|
25
13
|
|
26
14
|
def find(id)
|
@@ -29,42 +17,21 @@ module Rmsgen
|
|
29
17
|
end
|
30
18
|
|
31
19
|
def archive_polnote(id)
|
20
|
+
@imap_client.authenticate
|
32
21
|
follow_inbox
|
33
|
-
|
34
|
-
imap.search(["FROM", 'rms@gnu.org']).each do |note_id|
|
35
|
-
if note_id.to_i == id.to_i
|
36
|
-
imap.copy id.to_i, 'INBOX.old-messages'
|
37
|
-
imap.store(id.to_i, "+FLAGS", [:Deleted])
|
38
|
-
imap.expunge
|
39
|
-
archived = true
|
40
|
-
end
|
41
|
-
end
|
42
|
-
archived
|
22
|
+
move_to_archives(id)
|
43
23
|
end
|
44
24
|
|
45
25
|
private
|
46
|
-
|
47
|
-
def
|
48
|
-
@
|
49
|
-
|
50
|
-
|
51
|
-
def authenticate
|
52
|
-
imap.authenticate 'LOGIN', @login, @password
|
26
|
+
|
27
|
+
def move_to_archives(id)
|
28
|
+
@imap_client.copy id.to_i, 'INBOX.old-messages'
|
29
|
+
@imap_client.store(id.to_i, "+FLAGS", [:Deleted])
|
30
|
+
@imap_client.expunge
|
53
31
|
end
|
54
32
|
|
55
33
|
def follow_inbox
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
def find_all_from_rms
|
60
|
-
@note_ids.map { |id| fetch_message_body(id) }
|
61
|
-
end
|
62
|
-
|
63
|
-
def fetch_message_body(id)
|
64
|
-
fetch_result = imap.fetch id, 'RFC822'
|
65
|
-
if fetch_result && fetch_result.any?
|
66
|
-
fetch_result[0].attr['RFC822']
|
67
|
-
end
|
34
|
+
@imap_client.select 'INBOX'
|
68
35
|
end
|
69
36
|
end
|
70
37
|
end
|
data/lib/rmsgen/inquirer.rb
CHANGED
@@ -1,11 +1,5 @@
|
|
1
1
|
module Rmsgen
|
2
2
|
class Inquirer
|
3
|
-
PARTS = { :url => /^http/,
|
4
|
-
:note =>/\[Link/,
|
5
|
-
:duration => /^For.*week.*$/,
|
6
|
-
:indendation => /^ /
|
7
|
-
}
|
8
|
-
|
9
3
|
attr_reader :polnote
|
10
4
|
|
11
5
|
def initialize polnote, stdout=$stdout, answers=nil
|
@@ -35,13 +29,13 @@ module Rmsgen
|
|
35
29
|
|
36
30
|
def run!
|
37
31
|
@parts.each do |part|
|
38
|
-
if part
|
32
|
+
if part.is_a?(Rmsgen::Parts::Duration)
|
39
33
|
inquire_about_expiration
|
40
|
-
elsif part
|
34
|
+
elsif part.is_a?(Rmsgen::Parts::Url)
|
41
35
|
inquire_about_link part
|
42
|
-
elsif part
|
36
|
+
elsif part.is_a?(Rmsgen::Parts::PolnoteUrlRequest)
|
43
37
|
inquire_about_polnote_link part
|
44
|
-
elsif part
|
38
|
+
elsif part.is_a?(Rmsgen::Parts::IndentedLine)
|
45
39
|
append_to_previous_paragraph part
|
46
40
|
else
|
47
41
|
@parts_seen << part
|
data/lib/rmsgen/part.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Rmsgen
|
2
|
+
module Part
|
3
|
+
|
4
|
+
TOKEN_PARTS = {
|
5
|
+
/^http/ => Rmsgen::Parts::Url,
|
6
|
+
/Return-Path:/ => Rmsgen::Parts::Header,
|
7
|
+
/\[Link/i => Rmsgen::Parts::PolnoteUrlRequest,
|
8
|
+
/Dr Richard Stallman/ => Rmsgen::Parts::Footer,
|
9
|
+
/^ / => Rmsgen::Parts::IndentedLine,
|
10
|
+
/^For.*week.*$/ => Rmsgen::Parts::Duration
|
11
|
+
}
|
12
|
+
|
13
|
+
def self.parse(raw)
|
14
|
+
token_part = TOKEN_PARTS.find { |pattern, part| raw =~ pattern }
|
15
|
+
return Rmsgen::Parts::PlainText.new(raw) unless token_part
|
16
|
+
token_part[1].new(raw)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/rmsgen/part_group.rb
CHANGED
@@ -1,23 +1,51 @@
|
|
1
|
-
|
2
|
-
attr_reader :text
|
1
|
+
require 'forwardable'
|
3
2
|
|
4
|
-
|
3
|
+
class PartGroup
|
4
|
+
extend Forwardable
|
5
|
+
include Comparable
|
6
|
+
|
7
|
+
# Carriage return new line.
|
8
|
+
#
|
9
|
+
CRNL = /\r\n/
|
10
|
+
CRNL_CRNL = /\r\n\r\n/
|
11
|
+
DELIMETER = "\n\n"
|
12
|
+
NL = /\n/
|
13
|
+
NL_NL = /\n\n/
|
14
|
+
NL_PLACEHOLDER = '[newline]'
|
15
|
+
SPACE = ' '
|
16
|
+
|
17
|
+
attr_reader :text, :parts
|
18
|
+
|
19
|
+
def_delegators :@parts, :delete_if, :<<, :each, :join,
|
20
|
+
:inject, :each_with_index, :[], :map, :size
|
5
21
|
|
6
22
|
def initialize(text)
|
7
23
|
@text = text
|
24
|
+
@parts = []
|
8
25
|
assign_parts!
|
9
26
|
end
|
10
27
|
|
28
|
+
def <=>(other)
|
29
|
+
parts.map(&:to_s) <=> other.map(&:to_s)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
11
34
|
def assign_parts!
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
35
|
+
massage_linebreaks
|
36
|
+
parts = @text.split(DELIMETER)
|
37
|
+
assign_parsed_parts(parts)
|
38
|
+
@parts.delete_if(&:empty?)
|
39
|
+
end
|
40
|
+
|
41
|
+
def assign_parsed_parts(parts)
|
42
|
+
parts.each { |p| @parts << Rmsgen::Part.parse(p) }
|
43
|
+
end
|
44
|
+
|
45
|
+
def massage_linebreaks
|
46
|
+
@text.gsub!(CRNL_CRNL, DELIMETER)
|
47
|
+
@text.gsub!(CRNL, SPACE)
|
48
|
+
@text.gsub!(NL_NL, NL_PLACEHOLDER)
|
49
|
+
@text.gsub!(NL_PLACEHOLDER, DELIMETER)
|
22
50
|
end
|
23
51
|
end
|
data/lib/rmsgen/polnote.rb
CHANGED
@@ -19,15 +19,23 @@ module Rmsgen
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def titleize
|
22
|
-
@title = Titleizer.new(self).
|
22
|
+
@title = Titleizer.new(self).to_html
|
23
23
|
end
|
24
24
|
|
25
25
|
def inquire
|
26
26
|
@body = Inquirer.new(self).body
|
27
27
|
end
|
28
28
|
|
29
|
-
def
|
30
|
-
|
29
|
+
def include?(pattern)
|
30
|
+
@body.include?(pattern)
|
31
|
+
end
|
32
|
+
|
33
|
+
def gsub!(x, y)
|
34
|
+
@body.gsub!(x, y)
|
35
|
+
end
|
36
|
+
|
37
|
+
def split(x)
|
38
|
+
@body.split(x)
|
31
39
|
end
|
32
40
|
|
33
41
|
def to_html
|
@@ -38,10 +46,14 @@ module Rmsgen
|
|
38
46
|
ERB.new(File.read(URGENT_TEMPLATE)).result(binding)
|
39
47
|
end
|
40
48
|
|
49
|
+
def parts
|
50
|
+
PartGroup.new(@body)
|
51
|
+
end
|
52
|
+
|
41
53
|
private
|
42
54
|
|
43
55
|
def compress!
|
44
|
-
@body = Compresser.new(
|
56
|
+
@body = Compresser.new(parts).body
|
45
57
|
end
|
46
58
|
|
47
59
|
def sanitize_urgent_attribute(attribute)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Rmsgen
|
2
|
+
module PolnoteGroup
|
3
|
+
def self.fetch(source)
|
4
|
+
polnote_group = group(source)
|
5
|
+
polnote_group.all
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def self.group(source)
|
12
|
+
case source
|
13
|
+
when String then Rmsgen::FsPolnoteGroup.new(source)
|
14
|
+
else
|
15
|
+
Rmsgen::IMAPPolnoteGroup.new(source)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/rmsgen/runtime.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
module Rmsgen
|
2
2
|
class Runtime
|
3
|
+
|
3
4
|
def initialize(config)
|
4
5
|
@config = config
|
5
6
|
raise "Ensure you have populated a config file" unless @config
|
6
|
-
@output =
|
7
|
-
@notes =
|
7
|
+
@output = config['output_file']
|
8
|
+
@notes = PolnoteGroup.fetch(polnote_source)
|
8
9
|
run!
|
9
10
|
end
|
10
11
|
|
@@ -12,13 +13,26 @@ module Rmsgen
|
|
12
13
|
puts 'no polnotes in queue' if @notes.empty?
|
13
14
|
@notes.each do |note|
|
14
15
|
system('clear')
|
15
|
-
polnote = Rmsgen::
|
16
|
+
polnote = Rmsgen::Polnote.new(:body => note)
|
17
|
+
Rmsgen::Inquirer.inquire_about_note(polnote)
|
16
18
|
write(polnote)
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
20
22
|
private
|
21
23
|
|
24
|
+
def polnote_source
|
25
|
+
@config['email_dir'] || Rmsgen::IMAPClient.new(imap_options)
|
26
|
+
end
|
27
|
+
|
28
|
+
def imap_options
|
29
|
+
{
|
30
|
+
'imap_server' => @config['imap_server'],
|
31
|
+
'imap_login' => @config['imap_login'],
|
32
|
+
'imap_password' => @config['imap_password']
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
22
36
|
def write(note)
|
23
37
|
if @output
|
24
38
|
File.open(@output, 'a') do |file|
|
@@ -29,24 +43,5 @@ module Rmsgen
|
|
29
43
|
puts
|
30
44
|
end
|
31
45
|
end
|
32
|
-
|
33
|
-
def fetch_notes
|
34
|
-
if @config['email_dir']
|
35
|
-
notes = Dir["#{@config['email_dir']}/*"].map { |f| File.read(f) }
|
36
|
-
else
|
37
|
-
notes = fetch_notes_from_imap
|
38
|
-
end
|
39
|
-
notes.map { |note| Rmsgen::Polnote.new(:body => note) } if notes
|
40
|
-
end
|
41
|
-
|
42
|
-
def fetch_notes_from_imap
|
43
|
-
options = {
|
44
|
-
'imap_server' => @config['imap_server'],
|
45
|
-
'imap_login' => @config['imap_login'],
|
46
|
-
'imap_password' => @config['imap_password']
|
47
|
-
}
|
48
|
-
|
49
|
-
Rmsgen::IMAPPolnoteGroup.new(options).fetch_notes
|
50
|
-
end
|
51
46
|
end
|
52
47
|
end
|
data/lib/rmsgen/titleizer.rb
CHANGED
@@ -11,16 +11,11 @@ module Rmsgen
|
|
11
11
|
@title = options[:title]
|
12
12
|
@body = polnote.body
|
13
13
|
@script = Script.new($stdout)
|
14
|
-
|
15
14
|
run!
|
16
15
|
end
|
17
16
|
|
18
|
-
def body
|
19
|
-
ERB.new(File.read(TEMPLATE)).result(binding)
|
20
|
-
end
|
21
|
-
|
22
17
|
def to_html
|
23
|
-
|
18
|
+
ERB.new(File.read(TEMPLATE)).result(binding)
|
24
19
|
end
|
25
20
|
|
26
21
|
private
|
@@ -29,12 +24,12 @@ module Rmsgen
|
|
29
24
|
@title = capitalize(get_title_from_options_or_script)
|
30
25
|
end
|
31
26
|
|
32
|
-
def
|
33
|
-
|
27
|
+
def capitalize(str)
|
28
|
+
str.split(SPACE).map(&:capitalize).join(SPACE)
|
34
29
|
end
|
35
30
|
|
36
|
-
def
|
37
|
-
title.
|
31
|
+
def get_title_from_options_or_script
|
32
|
+
@title || @script.prompt_for_title
|
38
33
|
end
|
39
34
|
|
40
35
|
def today_format
|
data/lib/rmsgen/version.rb
CHANGED
data/spec/fixtures/urgent_note
CHANGED
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'rmsgen'
|
2
|
+
|
3
|
+
describe Rmsgen::IMAPClient do
|
4
|
+
let(:imap_options) do
|
5
|
+
{
|
6
|
+
'imap_server' => 'mail.example.com',
|
7
|
+
'imap_login' => 'login',
|
8
|
+
'imap_password' => 'password'
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'authenticates with the server' do
|
13
|
+
net_imap_instance = mock
|
14
|
+
Net::IMAP.should_receive(:new).with('mail.example.com').and_return(net_imap_instance)
|
15
|
+
net_imap_instance.should_receive(:authenticate).with('LOGIN', 'login', 'password').and_return(nil)
|
16
|
+
imap_client = Rmsgen::IMAPClient.new(imap_options)
|
17
|
+
imap_client.authenticate
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'fetches messages from the inbox' do
|
21
|
+
before do
|
22
|
+
@net_imap_instance = mock(:search => [], :select => [])
|
23
|
+
@message_collection = mock(:message_collection)
|
24
|
+
Net::IMAP.should_receive(:new).with('mail.example.com').and_return(@net_imap_instance)
|
25
|
+
@client = Rmsgen::IMAPClient.new(imap_options)
|
26
|
+
@client.should_receive(:authenticate).once
|
27
|
+
end
|
28
|
+
|
29
|
+
after do
|
30
|
+
@client.fetch_polnote_messages_from_inbox
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'delegates select to the imap client' do
|
34
|
+
@net_imap_instance.should_receive(:select).once.with('INBOX')
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'delegates search to ' do
|
38
|
+
@net_imap_instance.should_receive(:search).once.with(["FROM", 'rms@gnu.org'])
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'delegates fetch to imap client and uses RFC822' do
|
42
|
+
@net_imap_instance.should_receive(:search).and_return([1])
|
43
|
+
fetch_result = [mock(:notes, :attr => { "RFC822" => 'Hello World'} )]
|
44
|
+
@net_imap_instance.should_receive(:fetch).once.with(1, 'RFC822').and_return(fetch_result)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'finding a single message body' do
|
49
|
+
let(:net_imap_instance) { mock(:net_imap, :select => nil, :fetch => []) }
|
50
|
+
let(:client) do
|
51
|
+
Rmsgen::IMAPClient.new(imap_options)
|
52
|
+
end
|
53
|
+
|
54
|
+
before do
|
55
|
+
Net::IMAP.should_receive(:new).with('mail.example.com').and_return(net_imap_instance)
|
56
|
+
end
|
57
|
+
|
58
|
+
after do
|
59
|
+
client.find_by_id(1)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'delegates select to imap client' do
|
63
|
+
net_imap_instance.should_receive(:select).once.with('INBOX')
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'calls fetch for the id' do
|
67
|
+
net_imap_instance.should_receive(:fetch).with(1, 'RFC822').once
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -1,45 +1,34 @@
|
|
1
1
|
require 'rmsgen'
|
2
2
|
|
3
3
|
describe Rmsgen::IMAPPolnoteGroup do
|
4
|
-
context 'fetching notes' do
|
5
|
-
let(:imap) { double('
|
6
|
-
let(:options) do {
|
7
|
-
'imap_server' => 'foo.bar.com',
|
8
|
-
'imap_login' => 'login',
|
9
|
-
'imap_password' => 'password'}
|
10
|
-
end
|
4
|
+
context 'fetching notes from an imap server' do
|
5
|
+
let(:imap) { double('imap client') }
|
11
6
|
|
12
|
-
let(:
|
13
|
-
imap.should_receive(:
|
7
|
+
let(:set_imap_expectations_and_get_all) do
|
8
|
+
imap.should_receive(:fetch_polnote_messages_from_inbox).any_number_of_times
|
14
9
|
imap.should_receive(:authenticate).any_number_of_times
|
10
|
+
imap.should_receive(:search).any_number_of_times
|
15
11
|
Net::IMAP.should_receive(:new).any_number_of_times.and_return(imap)
|
16
12
|
imap.should_receive(:select).any_number_of_times
|
17
|
-
Rmsgen::IMAPPolnoteGroup.new(
|
13
|
+
Rmsgen::IMAPPolnoteGroup.new(imap).all
|
18
14
|
end
|
19
15
|
|
20
|
-
|
21
|
-
|
22
|
-
do_fetch
|
16
|
+
after(:each) do
|
17
|
+
set_imap_expectations_and_get_all
|
23
18
|
end
|
24
19
|
|
25
20
|
it 'selects the inbox folder' do
|
26
21
|
imap.should_receive(:select).any_number_of_times.with('INBOX')
|
27
|
-
do_fetch
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'searches for messages from rms' do
|
31
|
-
imap.should_receive(:search).once.with(["FROM", 'rms@gnu.org'])
|
32
|
-
do_fetch
|
33
22
|
end
|
34
23
|
|
35
24
|
it 'fetches each message' do
|
36
|
-
message_id = double('message_id')
|
37
|
-
search_result = [message_id]
|
38
25
|
|
39
|
-
|
26
|
+
# message_id = double('message_id')
|
27
|
+
# search_result = [message_id]
|
28
|
+
|
29
|
+
# imap.stub(:search) { search_result }
|
40
30
|
|
41
|
-
|
42
|
-
do_fetch
|
31
|
+
# imap.should_receive(:fetch).with(message_id, 'RFC822')
|
43
32
|
end
|
44
33
|
end
|
45
34
|
end
|
data/spec/part_group_spec.rb
CHANGED
@@ -3,19 +3,16 @@ require 'rmsgen'
|
|
3
3
|
describe PartGroup do
|
4
4
|
it "accepts text as input" do
|
5
5
|
input = "hello\n\nworld"
|
6
|
-
|
7
|
-
p.text.should be == input
|
6
|
+
PartGroup.new(input).text.should be == input
|
8
7
|
end
|
9
8
|
|
10
9
|
it "output list of parts ordered by appearance" do
|
11
10
|
input = "\n\n\n\n1\n\n2\n\n3\n\n4"
|
12
|
-
|
13
|
-
p.should == ['1', '2', '3', '4']
|
11
|
+
PartGroup.new(input).should == ['1', '2', '3', '4']
|
14
12
|
end
|
15
13
|
|
16
14
|
it "splits input into parts based on carriage return and newline" do
|
17
15
|
input = "1\r\n\r\n2\r\n\r\n3\r\n\r\n4"
|
18
|
-
|
19
|
-
p.should == ['1', '2', '3', '4']
|
16
|
+
PartGroup.new(input).should == ['1', '2', '3', '4']
|
20
17
|
end
|
21
18
|
end
|
data/spec/part_spec.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'rmsgen'
|
2
|
+
|
3
|
+
describe Rmsgen::Parts::PlainText do
|
4
|
+
context 'behaving like a string' do
|
5
|
+
it 'returns the input string' do
|
6
|
+
p = Rmsgen::Parts::PlainText.new('foo')
|
7
|
+
p.to_s.should == 'foo'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe Rmsgen::Parts::PolnoteUrlRequest do
|
13
|
+
context 'behaving like a string' do
|
14
|
+
it 'returns the input string' do
|
15
|
+
p = Rmsgen::Parts::PolnoteUrlRequest.new('foo')
|
16
|
+
p.to_s.should == 'foo'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe Rmsgen::Part do
|
22
|
+
context 'parse' do
|
23
|
+
it 'detects a url' do
|
24
|
+
subject.parse('http').should be_instance_of(Rmsgen::Parts::Url)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'detects the headers' do
|
28
|
+
subject.parse('Return-Path:').should be_instance_of(Rmsgen::Parts::Header)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'detects an indented line' do
|
32
|
+
subject.parse(' hello world').should be_instance_of(Rmsgen::Parts::IndentedLine)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'detects a duration' do
|
36
|
+
subject.parse('For one week').should be_instance_of(Rmsgen::Parts::Duration)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'detects plain text' do
|
40
|
+
subject.parse('bla blah blah').should be_instance_of(Rmsgen::Parts::PlainText)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'detects a polnote url request' do
|
44
|
+
subject.parse('[Link to a polnote]').should be_instance_of(Rmsgen::Parts::PolnoteUrlRequest)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'detects a downcased polnote url request' do
|
48
|
+
subject.parse('[link').should be_instance_of(Rmsgen::Parts::PolnoteUrlRequest)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rmsgen'
|
2
|
+
|
3
|
+
describe Rmsgen::PolnoteGroup do
|
4
|
+
context '.fetch' do
|
5
|
+
context 'from a file system' do
|
6
|
+
it 'collects file contents' do
|
7
|
+
file_system_polnote_group = mock
|
8
|
+
file_system_polnote_group.should_receive(:all)
|
9
|
+
Rmsgen::PolnoteGroup.should_receive(:group).and_return(file_system_polnote_group)
|
10
|
+
Rmsgen::PolnoteGroup.fetch('/some/path')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'from an imap server' do
|
15
|
+
it 'collects email contents' do
|
16
|
+
imap_polnote_group = mock
|
17
|
+
imap_polnote_group.should_receive(:all)
|
18
|
+
Rmsgen::PolnoteGroup.should_receive(:group).and_return(imap_polnote_group)
|
19
|
+
imap_options = { 'imap_server' => 'foo.test.com', 'imap_login' => 'login', 'imap_password' => 'password' }
|
20
|
+
Rmsgen::PolnoteGroup.fetch(imap_options)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/spec/polnote_spec.rb
CHANGED
@@ -2,7 +2,6 @@ require 'rmsgen'
|
|
2
2
|
require 'fake_gets'
|
3
3
|
|
4
4
|
describe Rmsgen::Polnote do
|
5
|
-
|
6
5
|
def fixture(name)
|
7
6
|
File.read("spec/fixtures/#{name}")
|
8
7
|
end
|
@@ -21,7 +20,7 @@ describe Rmsgen::Polnote do
|
|
21
20
|
|
22
21
|
it "has parts" do
|
23
22
|
note = Rmsgen::Polnote.new(:body => imap_note)
|
24
|
-
note.parts.should ==
|
23
|
+
note.parts.size.should be == 2
|
25
24
|
end
|
26
25
|
end
|
27
26
|
|
@@ -29,12 +28,8 @@ describe Rmsgen::Polnote do
|
|
29
28
|
let(:note) { fixture(:link_to_polnote) }
|
30
29
|
|
31
30
|
it 'parses the body' do
|
32
|
-
text_a = "rainbow"
|
33
|
-
polnote_url = "http://somenote"
|
34
|
-
text_b = "blue"
|
35
|
-
|
36
31
|
$stdout = StringIO.new
|
37
|
-
$stdin = FakeGetMany.new(
|
32
|
+
$stdin = FakeGetMany.new('rainbow', 'http://somenote', 'blue')
|
38
33
|
polnote = Rmsgen::Polnote.new(:body => note)
|
39
34
|
polnote.inquire
|
40
35
|
polnote.to_html.should ==
|
data/spec/runtime_spec.rb
CHANGED
@@ -12,23 +12,13 @@ describe Rmsgen::Runtime do
|
|
12
12
|
|
13
13
|
context 'when and there is a note' do
|
14
14
|
let(:runtime) { Rmsgen::Runtime }
|
15
|
-
let(:imap) {
|
16
|
-
let(:search_result) { mock(:search_result) }
|
15
|
+
let(:imap) { stub(:imap) }
|
17
16
|
|
18
17
|
it 'fetches the note' do
|
19
18
|
$stdout = StringIO.new
|
20
19
|
$stdin = FakeGet.new('hello')
|
21
|
-
|
22
|
-
|
23
|
-
imap_note = mock(:note)
|
24
|
-
notes = [imap_note]
|
25
|
-
|
26
|
-
imap_note.stub(:attr) { {"RFC822"=>"hello world"} }
|
27
|
-
imap.stub(:authenticate)
|
28
|
-
imap.stub(:select)
|
29
|
-
|
30
|
-
imap.stub(:search) { [search_result] }
|
31
|
-
imap.stub(:fetch) { notes }
|
20
|
+
Rmsgen::IMAPClient.should_receive(:new).and_return(imap)
|
21
|
+
imap.should_receive(:fetch_polnote_messages_from_inbox).and_return([])
|
32
22
|
expect { runtime.new(config).run! }.to_not raise_error
|
33
23
|
end
|
34
24
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rmsgen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-09-
|
12
|
+
date: 2011-09-30 00:00:00.000000000Z
|
13
13
|
dependencies: []
|
14
14
|
description: A library to help generate html markup from RMS emails
|
15
15
|
email:
|
@@ -46,15 +46,26 @@ files:
|
|
46
46
|
- features/support/env.rb
|
47
47
|
- features/support/hooks.rb
|
48
48
|
- features/urgent_polnote.feature
|
49
|
+
- lib/acts_like/string.rb
|
49
50
|
- lib/rmsgen.rb
|
50
51
|
- lib/rmsgen/cli/main.rb
|
51
52
|
- lib/rmsgen/compresser.rb
|
52
53
|
- lib/rmsgen/fs_polnote_group.rb
|
54
|
+
- lib/rmsgen/imap_client.rb
|
53
55
|
- lib/rmsgen/imap_polnote_group.rb
|
54
56
|
- lib/rmsgen/inquirer.rb
|
55
57
|
- lib/rmsgen/link.rb
|
58
|
+
- lib/rmsgen/part.rb
|
56
59
|
- lib/rmsgen/part_group.rb
|
60
|
+
- lib/rmsgen/parts/duration.rb
|
61
|
+
- lib/rmsgen/parts/footer.rb
|
62
|
+
- lib/rmsgen/parts/header.rb
|
63
|
+
- lib/rmsgen/parts/indented_line.rb
|
64
|
+
- lib/rmsgen/parts/plain_text.rb
|
65
|
+
- lib/rmsgen/parts/polnote_url_request.rb
|
66
|
+
- lib/rmsgen/parts/url.rb
|
57
67
|
- lib/rmsgen/polnote.rb
|
68
|
+
- lib/rmsgen/polnote_group.rb
|
58
69
|
- lib/rmsgen/runtime.rb
|
59
70
|
- lib/rmsgen/script.rb
|
60
71
|
- lib/rmsgen/titleizer.rb
|
@@ -69,9 +80,12 @@ files:
|
|
69
80
|
- spec/fixtures/multiline_note
|
70
81
|
- spec/fixtures/urgent_note
|
71
82
|
- spec/fs_polnote_group_spec.rb
|
83
|
+
- spec/imap_client_spec.rb
|
72
84
|
- spec/imap_polnote_group_spec.rb
|
73
85
|
- spec/inqirer_spec.rb
|
74
86
|
- spec/part_group_spec.rb
|
87
|
+
- spec/part_spec.rb
|
88
|
+
- spec/polnote_group.rb
|
75
89
|
- spec/polnote_spec.rb
|
76
90
|
- spec/runtime_spec.rb
|
77
91
|
- spec/support/fake_gets.rb
|