lib/sup/draft.rb (2720B) - raw
1 module Redwood
2
3 class DraftManager
4 include Redwood::Singleton
5
6 attr_accessor :source
7 def initialize dir
8 @dir = dir
9 @source = nil
10 end
11
12 def self.source_name; "sup://drafts"; end
13 def self.source_id; 9999; end
14 def new_source; @source = DraftLoader.new @dir; end
15
16 def write_draft
17 offset = @source.gen_offset
18 fn = @source.fn_for_offset offset
19 File.open(fn, "w", :encoding => $encoding) { |f| yield f }
20 PollManager.poll_from @source
21 end
22
23 def discard m
24 raise ArgumentError, "not a draft: source id #{m.source.id.inspect}, should be #{DraftManager.source_id.inspect} for #{m.id.inspect}" unless m.source.id.to_i == DraftManager.source_id
25 Index.delete m.id
26 File.delete @source.fn_for_offset(m.source_info) rescue Errno::ENOENT
27 UpdateManager.relay self, :single_message_deleted, m
28 end
29 end
30
31 class DraftLoader < Source
32 attr_accessor :dir
33 yaml_properties
34
35 def initialize dir
36 Dir.mkdir dir unless File.exist? dir
37 super DraftManager.source_name, true, false
38 @dir = dir
39 @cur_offset = 0
40 end
41
42 def properly_initialized?
43 !!(@dir && @cur_offset)
44 end
45
46 def id; DraftManager.source_id; end
47 def to_s; DraftManager.source_name; end
48 def uri; DraftManager.source_name; end
49
50 def poll
51 ids = get_ids
52 ids.each do |id|
53 if id >= @cur_offset
54 @cur_offset = id + 1
55 yield :add,
56 :info => id,
57 :labels => [:draft, :inbox],
58 :progress => 0.0
59 end
60 end
61 end
62
63 def gen_offset
64 i = @cur_offset
65 while File.exist? fn_for_offset(i)
66 i += 1
67 end
68 i
69 end
70
71 def fn_for_offset o; File.join(@dir, o.to_s); end
72
73 def load_header offset
74 File.open(fn_for_offset(offset)) { |f| parse_raw_email_header f }
75 end
76
77 def load_message offset
78 raise SourceError, "Draft not found" unless File.exist? fn_for_offset(offset)
79 File.open(fn_for_offset(offset)) do |f|
80 message = RMail::Parser.read f
81 message.header.set "Content-Type", "text/plain; charset=#{$encoding}"
82 message
83 end
84 end
85
86 def fallback_date_for_message offset
87 File.mtime fn_for_offset(offset)
88 end
89
90 def raw_header offset
91 ret = ""
92 File.open(fn_for_offset(offset), "r") do |f|
93 until f.eof? || (l = f.gets) =~ /^$/
94 ret += l
95 end
96 end
97 ret
98 end
99
100 def each_raw_message_line offset
101 File.open(fn_for_offset(offset), "r") do |f|
102 yield f.gets until f.eof?
103 end
104 end
105
106 def raw_message offset
107 IO.read fn_for_offset(offset)
108 end
109
110 def start_offset; 0; end
111 def end_offset
112 ids = get_ids
113 ids.empty? ? 0 : (ids.last + 1)
114 end
115
116 private
117
118 def get_ids
119 Dir.entries(@dir).select { |x| x =~ /^\d+$/ }.map { |x| x.to_i }.sort
120 end
121 end
122
123 end