gmail-britta 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -1
- data/Gemfile.lock +5 -1
- data/README.rdoc +5 -1
- data/VERSION +1 -1
- data/gmail-britta.gemspec +16 -6
- data/lib/gmail-britta.rb +26 -228
- data/lib/gmail-britta/delegate.rb +17 -0
- data/lib/gmail-britta/filter.rb +142 -0
- data/lib/gmail-britta/single_write_accessors.rb +58 -0
- data/test/test_gmail-britta.rb +45 -0
- metadata +61 -29
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -13,7 +13,9 @@ GEM
|
|
13
13
|
rake
|
14
14
|
rdoc
|
15
15
|
json (1.7.5)
|
16
|
+
minitest (3.1.0)
|
16
17
|
multi_json (1.3.6)
|
18
|
+
nokogiri (1.5.6)
|
17
19
|
rake (0.9.2.2)
|
18
20
|
rcov (1.0.0)
|
19
21
|
rdoc (3.12)
|
@@ -29,9 +31,11 @@ PLATFORMS
|
|
29
31
|
ruby
|
30
32
|
|
31
33
|
DEPENDENCIES
|
32
|
-
bundler (~> 1.
|
34
|
+
bundler (~> 1.2.0)
|
33
35
|
haml (~> 3.1.6)
|
34
36
|
jeweler (~> 1.8.4)
|
37
|
+
minitest
|
38
|
+
nokogiri
|
35
39
|
rcov
|
36
40
|
rdoc (~> 3.12)
|
37
41
|
shoulda
|
data/README.rdoc
CHANGED
@@ -4,6 +4,10 @@ This gem assists in writing complex gmail filters. You probably have a
|
|
4
4
|
lot of questions, and I'm sorry this README currently answers so few
|
5
5
|
of them )-:
|
6
6
|
|
7
|
+
A lot of this is very hacky, as it started as a oneoff ruby script -
|
8
|
+
very sorry for any amateurish code you may encounter. All I can say
|
9
|
+
is, it works for me [-:
|
10
|
+
|
7
11
|
== Contributing to gmail-britta
|
8
12
|
|
9
13
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
@@ -11,7 +15,7 @@ of them )-:
|
|
11
15
|
* Fork the project.
|
12
16
|
* Start a feature/bugfix branch.
|
13
17
|
* Commit and push until you are happy with your contribution.
|
14
|
-
* Make sure to add tests for it.
|
18
|
+
* Make sure to add tests for it. (Note that are only very few tests yet. I would totally appreciate if you started fleshing out this suite, but I wouldn't expect you to add much of anything.)
|
15
19
|
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
16
20
|
|
17
21
|
== Copyright
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.3
|
data/gmail-britta.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "gmail-britta"
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Andreas Fuchs"]
|
12
|
-
s.date = "2012-
|
12
|
+
s.date = "2012-12-22"
|
13
13
|
s.description = "This gem helps create large (>50) gmail filter chains by writing xml compatible with gmail's \"import/export filters\" feature."
|
14
14
|
s.email = "asf@boinkor.net"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -25,7 +25,11 @@ Gem::Specification.new do |s|
|
|
25
25
|
"Rakefile",
|
26
26
|
"VERSION",
|
27
27
|
"gmail-britta.gemspec",
|
28
|
-
"lib/gmail-britta.rb"
|
28
|
+
"lib/gmail-britta.rb",
|
29
|
+
"lib/gmail-britta/delegate.rb",
|
30
|
+
"lib/gmail-britta/filter.rb",
|
31
|
+
"lib/gmail-britta/single_write_accessors.rb",
|
32
|
+
"test/test_gmail-britta.rb"
|
29
33
|
]
|
30
34
|
s.homepage = "http://github.com/antifuchs/gmail-britta"
|
31
35
|
s.licenses = ["MIT"]
|
@@ -40,24 +44,30 @@ Gem::Specification.new do |s|
|
|
40
44
|
s.add_runtime_dependency(%q<haml>, ["~> 3.1.6"])
|
41
45
|
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
42
46
|
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
43
|
-
s.add_development_dependency(%q<bundler>, ["~> 1.
|
47
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.2.0"])
|
44
48
|
s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
|
45
49
|
s.add_development_dependency(%q<rcov>, [">= 0"])
|
50
|
+
s.add_development_dependency(%q<minitest>, [">= 0"])
|
51
|
+
s.add_development_dependency(%q<nokogiri>, [">= 0"])
|
46
52
|
else
|
47
53
|
s.add_dependency(%q<haml>, ["~> 3.1.6"])
|
48
54
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
49
55
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
50
|
-
s.add_dependency(%q<bundler>, ["~> 1.
|
56
|
+
s.add_dependency(%q<bundler>, ["~> 1.2.0"])
|
51
57
|
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
52
58
|
s.add_dependency(%q<rcov>, [">= 0"])
|
59
|
+
s.add_dependency(%q<minitest>, [">= 0"])
|
60
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
53
61
|
end
|
54
62
|
else
|
55
63
|
s.add_dependency(%q<haml>, ["~> 3.1.6"])
|
56
64
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
57
65
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
58
|
-
s.add_dependency(%q<bundler>, ["~> 1.
|
66
|
+
s.add_dependency(%q<bundler>, ["~> 1.2.0"])
|
59
67
|
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
60
68
|
s.add_dependency(%q<rcov>, [">= 0"])
|
69
|
+
s.add_dependency(%q<minitest>, [">= 0"])
|
70
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
61
71
|
end
|
62
72
|
end
|
63
73
|
|
data/lib/gmail-britta.rb
CHANGED
@@ -10,242 +10,34 @@ require 'time'
|
|
10
10
|
require 'haml'
|
11
11
|
require 'logger'
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
require 'gmail-britta/single_write_accessors'
|
14
|
+
require 'gmail-britta/delegate'
|
15
|
+
require 'gmail-britta/filter'
|
15
16
|
|
16
|
-
module
|
17
|
-
|
18
|
-
def
|
19
|
-
|
17
|
+
module GmailBritta
|
18
|
+
class Britta
|
19
|
+
def initialize(opts={})
|
20
|
+
@filters = []
|
21
|
+
@me = opts[:me] || 'me'
|
22
|
+
@logger = opts[:logger] || allocate_logger
|
20
23
|
end
|
21
24
|
|
22
|
-
def
|
23
|
-
|
25
|
+
def allocate_logger
|
26
|
+
logger = Logger.new(STDERR)
|
27
|
+
logger.level = Logger::WARN
|
28
|
+
logger
|
24
29
|
end
|
25
30
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
define_method(name) do |words|
|
30
|
-
if instance_variable_get(ivar_name)
|
31
|
-
raise "Only one use of #{name} is permitted per filter"
|
32
|
-
end
|
33
|
-
instance_variable_set(ivar_name, words)
|
34
|
-
end
|
35
|
-
define_method("get_#{name}") do
|
36
|
-
instance_variable_get(ivar_name)
|
37
|
-
end
|
38
|
-
if block_given?
|
39
|
-
define_method("output_#{name}") do
|
40
|
-
instance_variable_get(ivar_name) && block.call(instance_variable_get(ivar_name))
|
41
|
-
end
|
42
|
-
else
|
43
|
-
define_method("output_#{name}") do
|
44
|
-
instance_variable_get(ivar_name)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def single_write_boolean_accessor(name, gmail_name)
|
50
|
-
single_write_accessors[name] = gmail_name
|
51
|
-
ivar_name = self.ivar_name(name)
|
52
|
-
define_method(name) do |*args|
|
53
|
-
value = args.length > 0 ? args[0] : true
|
54
|
-
if instance_variable_get(ivar_name)
|
55
|
-
raise "Only one use of #{name} is permitted per filter"
|
56
|
-
end
|
57
|
-
instance_variable_set(ivar_name, value)
|
58
|
-
end
|
59
|
-
define_method("get_#{name}") do
|
60
|
-
instance_variable_get(ivar_name)
|
61
|
-
end
|
62
|
-
define_method("output_#{name}") do
|
63
|
-
instance_variable_get(ivar_name)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def self.included(base)
|
69
|
-
base.extend(ClassMethods)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
class GmailBritta
|
74
|
-
def initialize(opts={})
|
75
|
-
@filters = []
|
76
|
-
@me = opts[:me] || 'me'
|
77
|
-
end
|
78
|
-
|
79
|
-
attr_accessor :filters
|
80
|
-
attr_accessor :me
|
81
|
-
|
82
|
-
def self.filterset(opts={}, &block)
|
83
|
-
(britta = GmailBritta.new(opts)).rules(&block)
|
84
|
-
britta
|
85
|
-
end
|
31
|
+
attr_accessor :filters
|
32
|
+
attr_accessor :me
|
33
|
+
attr_accessor :logger
|
86
34
|
|
87
|
-
|
88
|
-
|
89
|
-
end
|
90
|
-
|
91
|
-
class Delegate
|
92
|
-
def initialize(britta)
|
93
|
-
@britta = britta
|
94
|
-
@filter = nil
|
95
|
-
end
|
96
|
-
|
97
|
-
def filter(&block)
|
98
|
-
Filter.new(@britta).perform(&block)
|
99
|
-
end
|
100
|
-
|
101
|
-
def perform(&block)
|
102
|
-
instance_eval(&block)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
class Filter
|
107
|
-
include SingleWriteAccessors
|
108
|
-
single_write_accessor :has, 'hasTheWord' do |list|
|
109
|
-
emit_filter_spec(list)
|
35
|
+
def rules(&block)
|
36
|
+
GmailBritta::Delegate.new(self, :logger => @logger).perform(&block)
|
110
37
|
end
|
111
|
-
single_write_accessor :has_not, 'doesNotHaveTheWord' do |list|
|
112
|
-
emit_filter_spec(list)
|
113
|
-
end
|
114
|
-
single_write_boolean_accessor :archive, 'shouldArchive'
|
115
|
-
single_write_boolean_accessor :delete_it, 'shouldTrash'
|
116
|
-
single_write_boolean_accessor :mark_read, 'shouldMarkAsRead'
|
117
|
-
single_write_boolean_accessor :mark_important, 'shouldAlwaysMarkAsImportant'
|
118
|
-
single_write_boolean_accessor :mark_unimportant, 'shouldNeverMarkAsImportant'
|
119
|
-
single_write_boolean_accessor :star, 'shouldStar'
|
120
|
-
single_write_boolean_accessor :never_spam, 'shouldNeverSpam'
|
121
|
-
single_write_accessor :label, 'label'
|
122
|
-
single_write_accessor :forward_to, 'forwardTo'
|
123
38
|
|
124
|
-
def
|
39
|
+
def generate
|
125
40
|
engine = Haml::Engine.new(<<-ATOM)
|
126
|
-
%entry
|
127
|
-
%category{:term => 'filter'}
|
128
|
-
%title Mail Filter
|
129
|
-
%content
|
130
|
-
- self.class.single_write_accessors.keys.each do |name|
|
131
|
-
- gmail_name = self.class.single_write_accessors[name]
|
132
|
-
- if value = self.send("output_\#{name}".intern)
|
133
|
-
%apps:property{:name => gmail_name, :value => value.to_s}
|
134
|
-
ATOM
|
135
|
-
engine.render(self)
|
136
|
-
end
|
137
|
-
|
138
|
-
def self.emit_filter_spec(filter, infix=' ')
|
139
|
-
str = ''
|
140
|
-
case filter
|
141
|
-
when String
|
142
|
-
str << filter
|
143
|
-
when Hash
|
144
|
-
filter.keys.each do |key|
|
145
|
-
case key
|
146
|
-
when :or
|
147
|
-
str << '('
|
148
|
-
str << emit_filter_spec(filter[key], ' OR ')
|
149
|
-
str << ')'
|
150
|
-
when :not
|
151
|
-
str << '-('
|
152
|
-
str << emit_filter_spec(filter[key], ' ')
|
153
|
-
str << ')'
|
154
|
-
end
|
155
|
-
end
|
156
|
-
when Array
|
157
|
-
str << filter.map {|elt| emit_filter_spec(elt, ' ')}.join(infix)
|
158
|
-
end
|
159
|
-
$log.debug " Filter spec #{filter.inspect} + #{infix.inspect} => #{str.inspect}"
|
160
|
-
str
|
161
|
-
end
|
162
|
-
|
163
|
-
def me
|
164
|
-
@britta.me
|
165
|
-
end
|
166
|
-
|
167
|
-
def initialize(britta)
|
168
|
-
@britta=britta
|
169
|
-
end
|
170
|
-
|
171
|
-
def log_definition
|
172
|
-
$log.debug "Filter: #{self}"
|
173
|
-
Filter.single_write_accessors.each do |name|
|
174
|
-
val = instance_variable_get(Filter.ivar_name(name))
|
175
|
-
$log.debug " #{name}: #{val}" if val
|
176
|
-
end
|
177
|
-
self
|
178
|
-
end
|
179
|
-
|
180
|
-
def perform(&block)
|
181
|
-
instance_eval(&block)
|
182
|
-
@britta.filters << self
|
183
|
-
self
|
184
|
-
end
|
185
|
-
|
186
|
-
def merge_negated_criteria(filter)
|
187
|
-
old_has_not = Marshal.load(Marshal.dump((filter.get_has_not || []).reject { |elt|
|
188
|
-
@has.member?(elt)
|
189
|
-
}))
|
190
|
-
old_has = Marshal.load( Marshal.dump((filter.get_has || []).reject { |elt|
|
191
|
-
@has.member?(elt)
|
192
|
-
}))
|
193
|
-
$log.debug(" M: oh #{old_has.inspect}")
|
194
|
-
$log.debug(" M: ohn #{old_has_not.inspect}")
|
195
|
-
|
196
|
-
@has_not ||= []
|
197
|
-
@has_not += case
|
198
|
-
when old_has_not.first.is_a?(Hash) && old_has_not.first[:or]
|
199
|
-
old_has_not.first[:or] += old_has
|
200
|
-
old_has_not
|
201
|
-
when old_has_not.length > 0
|
202
|
-
[{:or => old_has_not + old_has}]
|
203
|
-
else
|
204
|
-
old_has
|
205
|
-
end
|
206
|
-
$log.debug(" M: h #{@has.inspect}")
|
207
|
-
$log.debug(" M: nhn #{@has_not.inspect}")
|
208
|
-
end
|
209
|
-
|
210
|
-
def otherwise(&block)
|
211
|
-
filter = Filter.new(@britta).perform(&block)
|
212
|
-
filter.merge_negated_criteria(self)
|
213
|
-
filter.log_definition
|
214
|
-
filter
|
215
|
-
end
|
216
|
-
|
217
|
-
def merge_positive_criteria(filter)
|
218
|
-
new_has = (@has || []) + (filter.get_has || [])
|
219
|
-
new_has_not = (@has_not || []) + (filter.get_has_not || [])
|
220
|
-
@has = new_has
|
221
|
-
@has_not = new_has_not
|
222
|
-
end
|
223
|
-
|
224
|
-
def also(&block)
|
225
|
-
filter = Filter.new(@britta).perform(&block)
|
226
|
-
filter.merge_positive_criteria(self)
|
227
|
-
filter.log_definition
|
228
|
-
filter
|
229
|
-
end
|
230
|
-
|
231
|
-
def archive_unless_directed(options={})
|
232
|
-
mark_as_read=options[:mark_read]
|
233
|
-
tos=(options[:to] || me).to_a
|
234
|
-
filter = Filter.new(@britta).perform do
|
235
|
-
has_not [{:or => tos.map {|to| "to:#{to}"}}]
|
236
|
-
archive
|
237
|
-
if mark_as_read
|
238
|
-
mark_read
|
239
|
-
end
|
240
|
-
end
|
241
|
-
filter.merge_positive_criteria(self)
|
242
|
-
filter.log_definition
|
243
|
-
self
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
def generate
|
248
|
-
engine = Haml::Engine.new(<<-ATOM)
|
249
41
|
!!! XML
|
250
42
|
%feed{:xmlns => 'http://www.w3.org/2005/Atom', 'xmlns:apps' => 'http://schemas.google.com/apps/2006'}
|
251
43
|
%title Mail Filters
|
@@ -257,6 +49,12 @@ ATOM
|
|
257
49
|
- filters.each do |filter|
|
258
50
|
!= filter.generate_xml
|
259
51
|
ATOM
|
260
|
-
|
52
|
+
engine.render(self)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.filterset(opts={}, &block)
|
57
|
+
(britta = Britta.new(opts)).rules(&block)
|
58
|
+
britta
|
261
59
|
end
|
262
60
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module GmailBritta
|
2
|
+
class Delegate
|
3
|
+
def initialize(britta, options={})
|
4
|
+
@britta = britta
|
5
|
+
@log = options[:logger]
|
6
|
+
@filter = nil
|
7
|
+
end
|
8
|
+
|
9
|
+
def filter(&block)
|
10
|
+
GmailBritta::Filter.new(@britta, :log => @log).perform(&block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def perform(&block)
|
14
|
+
instance_eval(&block)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module GmailBritta
|
2
|
+
class Filter
|
3
|
+
include SingleWriteAccessors
|
4
|
+
single_write_accessor :has, 'hasTheWord' do |list|
|
5
|
+
emit_filter_spec(list)
|
6
|
+
end
|
7
|
+
single_write_accessor :has_not, 'doesNotHaveTheWord' do |list|
|
8
|
+
emit_filter_spec(list)
|
9
|
+
end
|
10
|
+
single_write_boolean_accessor :archive, 'shouldArchive'
|
11
|
+
single_write_boolean_accessor :delete_it, 'shouldTrash'
|
12
|
+
single_write_boolean_accessor :mark_read, 'shouldMarkAsRead'
|
13
|
+
single_write_boolean_accessor :mark_important, 'shouldAlwaysMarkAsImportant'
|
14
|
+
single_write_boolean_accessor :mark_unimportant, 'shouldNeverMarkAsImportant'
|
15
|
+
single_write_boolean_accessor :star, 'shouldStar'
|
16
|
+
single_write_boolean_accessor :never_spam, 'shouldNeverSpam'
|
17
|
+
single_write_accessor :label, 'label'
|
18
|
+
single_write_accessor :forward_to, 'forwardTo'
|
19
|
+
|
20
|
+
def initialize(britta, options={})
|
21
|
+
@britta = britta
|
22
|
+
@log = options[:log]
|
23
|
+
end
|
24
|
+
|
25
|
+
def generate_xml
|
26
|
+
engine = Haml::Engine.new(<<-ATOM)
|
27
|
+
%entry
|
28
|
+
%category{:term => 'filter'}
|
29
|
+
%title Mail Filter
|
30
|
+
%content
|
31
|
+
- self.class.single_write_accessors.keys.each do |name|
|
32
|
+
- gmail_name = self.class.single_write_accessors[name]
|
33
|
+
- if value = self.send("output_\#{name}".intern)
|
34
|
+
%apps:property{:name => gmail_name, :value => value.to_s}
|
35
|
+
ATOM
|
36
|
+
engine.render(self)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.emit_filter_spec(filter, infix=' ')
|
40
|
+
str = ''
|
41
|
+
case filter
|
42
|
+
when String
|
43
|
+
str << filter
|
44
|
+
when Hash
|
45
|
+
filter.keys.each do |key|
|
46
|
+
case key
|
47
|
+
when :or
|
48
|
+
str << '('
|
49
|
+
str << emit_filter_spec(filter[key], ' OR ')
|
50
|
+
str << ')'
|
51
|
+
when :not
|
52
|
+
str << '-('
|
53
|
+
str << emit_filter_spec(filter[key], ' ')
|
54
|
+
str << ')'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
when Array
|
58
|
+
str << filter.map {|elt| emit_filter_spec(elt, ' ')}.join(infix)
|
59
|
+
end
|
60
|
+
str
|
61
|
+
end
|
62
|
+
|
63
|
+
def me
|
64
|
+
@britta.me
|
65
|
+
end
|
66
|
+
|
67
|
+
def log_definition
|
68
|
+
@log.debug "Filter: #{self}"
|
69
|
+
Filter.single_write_accessors.each do |name|
|
70
|
+
val = instance_variable_get(Filter.ivar_name(name))
|
71
|
+
@log.debug " #{name}: #{val}" if val
|
72
|
+
end
|
73
|
+
self
|
74
|
+
end
|
75
|
+
|
76
|
+
def perform(&block)
|
77
|
+
instance_eval(&block)
|
78
|
+
@britta.filters << self
|
79
|
+
self
|
80
|
+
end
|
81
|
+
|
82
|
+
def merge_negated_criteria(filter)
|
83
|
+
old_has_not = Marshal.load(Marshal.dump((filter.get_has_not || []).reject { |elt|
|
84
|
+
@has.member?(elt)
|
85
|
+
}))
|
86
|
+
old_has = Marshal.load( Marshal.dump((filter.get_has || []).reject { |elt|
|
87
|
+
@has.member?(elt)
|
88
|
+
}))
|
89
|
+
@log.debug(" M: oh #{old_has.inspect}")
|
90
|
+
@log.debug(" M: ohn #{old_has_not.inspect}")
|
91
|
+
|
92
|
+
@has_not ||= []
|
93
|
+
@has_not += case
|
94
|
+
when old_has_not.first.is_a?(Hash) && old_has_not.first[:or]
|
95
|
+
old_has_not.first[:or] += old_has
|
96
|
+
old_has_not
|
97
|
+
when old_has_not.length > 0
|
98
|
+
[{:or => old_has_not + old_has}]
|
99
|
+
else
|
100
|
+
old_has
|
101
|
+
end
|
102
|
+
@log.debug(" M: h #{@has.inspect}")
|
103
|
+
@log.debug(" M: nhn #{@has_not.inspect}")
|
104
|
+
end
|
105
|
+
|
106
|
+
def otherwise(&block)
|
107
|
+
filter = Filter.new(@britta).perform(&block)
|
108
|
+
filter.merge_negated_criteria(self)
|
109
|
+
filter.log_definition
|
110
|
+
filter
|
111
|
+
end
|
112
|
+
|
113
|
+
def merge_positive_criteria(filter)
|
114
|
+
new_has = (@has || []) + (filter.get_has || [])
|
115
|
+
new_has_not = (@has_not || []) + (filter.get_has_not || [])
|
116
|
+
@has = new_has
|
117
|
+
@has_not = new_has_not
|
118
|
+
end
|
119
|
+
|
120
|
+
def also(&block)
|
121
|
+
filter = Filter.new(@britta).perform(&block)
|
122
|
+
filter.merge_positive_criteria(self)
|
123
|
+
filter.log_definition
|
124
|
+
filter
|
125
|
+
end
|
126
|
+
|
127
|
+
def archive_unless_directed(options={})
|
128
|
+
mark_as_read=options[:mark_read]
|
129
|
+
tos=(options[:to] || me).to_a
|
130
|
+
filter = Filter.new(@britta).perform do
|
131
|
+
has_not [{:or => tos.map {|to| "to:#{to}"}}]
|
132
|
+
archive
|
133
|
+
if mark_as_read
|
134
|
+
mark_read
|
135
|
+
end
|
136
|
+
end
|
137
|
+
filter.merge_positive_criteria(self)
|
138
|
+
filter.log_definition
|
139
|
+
self
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module GmailBritta
|
2
|
+
module SingleWriteAccessors
|
3
|
+
module ClassMethods
|
4
|
+
def ivar_name(name)
|
5
|
+
"@#{name}".intern
|
6
|
+
end
|
7
|
+
|
8
|
+
def single_write_accessors
|
9
|
+
@single_write_accessors ||= {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def single_write_accessor(name, gmail_name, &block)
|
13
|
+
single_write_accessors[name] = gmail_name
|
14
|
+
ivar_name = self.ivar_name(name)
|
15
|
+
define_method(name) do |words|
|
16
|
+
if instance_variable_get(ivar_name)
|
17
|
+
raise "Only one use of #{name} is permitted per filter"
|
18
|
+
end
|
19
|
+
instance_variable_set(ivar_name, words)
|
20
|
+
end
|
21
|
+
define_method("get_#{name}") do
|
22
|
+
instance_variable_get(ivar_name)
|
23
|
+
end
|
24
|
+
if block_given?
|
25
|
+
define_method("output_#{name}") do
|
26
|
+
instance_variable_get(ivar_name) && block.call(instance_variable_get(ivar_name))
|
27
|
+
end
|
28
|
+
else
|
29
|
+
define_method("output_#{name}") do
|
30
|
+
instance_variable_get(ivar_name)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def single_write_boolean_accessor(name, gmail_name)
|
36
|
+
single_write_accessors[name] = gmail_name
|
37
|
+
ivar_name = self.ivar_name(name)
|
38
|
+
define_method(name) do |*args|
|
39
|
+
value = args.length > 0 ? args[0] : true
|
40
|
+
if instance_variable_get(ivar_name)
|
41
|
+
raise "Only one use of #{name} is permitted per filter"
|
42
|
+
end
|
43
|
+
instance_variable_set(ivar_name, value)
|
44
|
+
end
|
45
|
+
define_method("get_#{name}") do
|
46
|
+
instance_variable_get(ivar_name)
|
47
|
+
end
|
48
|
+
define_method("output_#{name}") do
|
49
|
+
instance_variable_get(ivar_name)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.included(base)
|
55
|
+
base.extend(ClassMethods)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'minitest/unit'
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'minitest/autorun'
|
5
|
+
|
6
|
+
require 'gmail-britta'
|
7
|
+
|
8
|
+
describe GmailBritta do
|
9
|
+
def simple_filterset
|
10
|
+
fs = GmailBritta.filterset() do
|
11
|
+
filter {
|
12
|
+
has 'to:asf@boinkor.net'
|
13
|
+
label 'ohai'
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def dom(filterset)
|
19
|
+
text = simple_filterset.generate
|
20
|
+
#puts text
|
21
|
+
Nokogiri::XML.parse(text)
|
22
|
+
end
|
23
|
+
|
24
|
+
def ns
|
25
|
+
{
|
26
|
+
'a' => 'http://www.w3.org/2005/Atom',
|
27
|
+
'apps' => 'http://schemas.google.com/apps/2006'
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
it "runs" do
|
32
|
+
filters = simple_filterset.generate
|
33
|
+
assert(filters, "Should generate something")
|
34
|
+
assert(filters.is_a?(String), "Generated filters should be a string")
|
35
|
+
end
|
36
|
+
|
37
|
+
it "generates xml" do
|
38
|
+
filters = dom(simple_filterset)
|
39
|
+
|
40
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry',ns).length, "Should have exactly one filter entry")
|
41
|
+
assert_equal(2, filters.xpath('/a:feed/a:entry/apps:property',ns).length, "Should have two properties")
|
42
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@name="label"]',ns).length, "Should have exactly one 'label' property")
|
43
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@name="hasTheWord"]',ns).length, "Should have exactly one 'has' property")
|
44
|
+
end
|
45
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gmail-britta
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 29
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 3
|
10
|
+
version: 0.1.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Andreas Fuchs
|
@@ -15,11 +15,10 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-
|
18
|
+
date: 2012-12-22 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
|
22
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
21
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
23
22
|
none: false
|
24
23
|
requirements:
|
25
24
|
- - ~>
|
@@ -30,12 +29,12 @@ dependencies:
|
|
30
29
|
- 1
|
31
30
|
- 6
|
32
31
|
version: 3.1.6
|
33
|
-
version_requirements: *id001
|
34
|
-
name: haml
|
35
32
|
prerelease: false
|
33
|
+
type: :runtime
|
34
|
+
name: haml
|
35
|
+
requirement: *id001
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
|
-
|
38
|
-
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
39
38
|
none: false
|
40
39
|
requirements:
|
41
40
|
- - ">="
|
@@ -44,12 +43,12 @@ dependencies:
|
|
44
43
|
segments:
|
45
44
|
- 0
|
46
45
|
version: "0"
|
47
|
-
version_requirements: *id002
|
48
|
-
name: shoulda
|
49
46
|
prerelease: false
|
50
|
-
- !ruby/object:Gem::Dependency
|
51
47
|
type: :development
|
52
|
-
|
48
|
+
name: shoulda
|
49
|
+
requirement: *id002
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
53
52
|
none: false
|
54
53
|
requirements:
|
55
54
|
- - ~>
|
@@ -59,28 +58,28 @@ dependencies:
|
|
59
58
|
- 3
|
60
59
|
- 12
|
61
60
|
version: "3.12"
|
62
|
-
version_requirements: *id003
|
63
|
-
name: rdoc
|
64
61
|
prerelease: false
|
65
|
-
- !ruby/object:Gem::Dependency
|
66
62
|
type: :development
|
67
|
-
|
63
|
+
name: rdoc
|
64
|
+
requirement: *id003
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
68
67
|
none: false
|
69
68
|
requirements:
|
70
69
|
- - ~>
|
71
70
|
- !ruby/object:Gem::Version
|
72
|
-
hash:
|
71
|
+
hash: 31
|
73
72
|
segments:
|
74
73
|
- 1
|
75
|
-
-
|
74
|
+
- 2
|
76
75
|
- 0
|
77
|
-
version: 1.
|
78
|
-
version_requirements: *id004
|
79
|
-
name: bundler
|
76
|
+
version: 1.2.0
|
80
77
|
prerelease: false
|
81
|
-
- !ruby/object:Gem::Dependency
|
82
78
|
type: :development
|
83
|
-
|
79
|
+
name: bundler
|
80
|
+
requirement: *id004
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
84
83
|
none: false
|
85
84
|
requirements:
|
86
85
|
- - ~>
|
@@ -91,12 +90,40 @@ dependencies:
|
|
91
90
|
- 8
|
92
91
|
- 4
|
93
92
|
version: 1.8.4
|
94
|
-
|
93
|
+
prerelease: false
|
94
|
+
type: :development
|
95
95
|
name: jeweler
|
96
|
+
requirement: *id005
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
hash: 3
|
104
|
+
segments:
|
105
|
+
- 0
|
106
|
+
version: "0"
|
96
107
|
prerelease: false
|
108
|
+
type: :development
|
109
|
+
name: rcov
|
110
|
+
requirement: *id006
|
97
111
|
- !ruby/object:Gem::Dependency
|
112
|
+
version_requirements: &id007 !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
hash: 3
|
118
|
+
segments:
|
119
|
+
- 0
|
120
|
+
version: "0"
|
121
|
+
prerelease: false
|
98
122
|
type: :development
|
99
|
-
|
123
|
+
name: minitest
|
124
|
+
requirement: *id007
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
version_requirements: &id008 !ruby/object:Gem::Requirement
|
100
127
|
none: false
|
101
128
|
requirements:
|
102
129
|
- - ">="
|
@@ -105,9 +132,10 @@ dependencies:
|
|
105
132
|
segments:
|
106
133
|
- 0
|
107
134
|
version: "0"
|
108
|
-
version_requirements: *id006
|
109
|
-
name: rcov
|
110
135
|
prerelease: false
|
136
|
+
type: :development
|
137
|
+
name: nokogiri
|
138
|
+
requirement: *id008
|
111
139
|
description: This gem helps create large (>50) gmail filter chains by writing xml compatible with gmail's "import/export filters" feature.
|
112
140
|
email: asf@boinkor.net
|
113
141
|
executables: []
|
@@ -127,6 +155,10 @@ files:
|
|
127
155
|
- VERSION
|
128
156
|
- gmail-britta.gemspec
|
129
157
|
- lib/gmail-britta.rb
|
158
|
+
- lib/gmail-britta/delegate.rb
|
159
|
+
- lib/gmail-britta/filter.rb
|
160
|
+
- lib/gmail-britta/single_write_accessors.rb
|
161
|
+
- test/test_gmail-britta.rb
|
130
162
|
homepage: http://github.com/antifuchs/gmail-britta
|
131
163
|
licenses:
|
132
164
|
- MIT
|