gmail-britta 0.1.5 → 0.1.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/.travis.yml +11 -0
- data/Gemfile +10 -4
- data/Gemfile.lock +1 -2
- data/README.md +9 -0
- data/Rakefile +29 -29
- data/TODO.org +16 -0
- data/VERSION +1 -1
- data/examples/Gemfile +3 -0
- data/examples/Gemfile.lock +16 -0
- data/examples/README.md +2 -0
- data/examples/asf.rb +173 -0
- data/gmail-britta.gemspec +12 -18
- data/lib/gmail-britta/filter.rb +14 -10
- data/test/test_gmail-britta.rb +15 -2
- metadata +103 -165
data/.travis.yml
ADDED
data/Gemfile
CHANGED
@@ -6,13 +6,19 @@ gem 'haml', '~> 3.1.6'
|
|
6
6
|
# Add dependencies to develop your gem here.
|
7
7
|
# Include everything needed to run rake, tests, features, etc.
|
8
8
|
group :development do
|
9
|
+
gem "rake", "~> 0.9.2"
|
9
10
|
gem "shoulda", ">= 0"
|
11
|
+
gem "bundler", "~> 1.2.0"
|
12
|
+
gem "minitest"
|
13
|
+
gem "nokogiri"
|
14
|
+
end
|
15
|
+
|
16
|
+
group :doc do
|
10
17
|
gem "rdoc", "~> 3.12"
|
11
18
|
gem "yard", '~> 0.8.3'
|
12
19
|
gem 'redcarpet', '~> 2.2.2'
|
13
|
-
|
20
|
+
end
|
21
|
+
|
22
|
+
group :release do
|
14
23
|
gem "jeweler", "~> 1.8.4"
|
15
|
-
gem "rcov", ">= 0"
|
16
|
-
gem "minitest"
|
17
|
-
gem "nokogiri"
|
18
24
|
end
|
data/Gemfile.lock
CHANGED
@@ -17,7 +17,6 @@ GEM
|
|
17
17
|
multi_json (1.3.6)
|
18
18
|
nokogiri (1.5.6)
|
19
19
|
rake (0.9.2.2)
|
20
|
-
rcov (1.0.0)
|
21
20
|
rdoc (3.12)
|
22
21
|
json (~> 1.4)
|
23
22
|
redcarpet (2.2.2)
|
@@ -38,7 +37,7 @@ DEPENDENCIES
|
|
38
37
|
jeweler (~> 1.8.4)
|
39
38
|
minitest
|
40
39
|
nokogiri
|
41
|
-
|
40
|
+
rake (~> 0.9.2)
|
42
41
|
rdoc (~> 3.12)
|
43
42
|
redcarpet (~> 2.2.2)
|
44
43
|
shoulda
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# gmail-britta
|
2
2
|
|
3
|
+
[](https://travis-ci.org/antifuchs/gmail-britta)
|
4
|
+
|
3
5
|
This library helps you generate XML that you can import into gmail's
|
4
6
|
filter settings. It makes it more pleasant to write simple (and even
|
5
7
|
complex) filter chains.
|
@@ -162,6 +164,13 @@ gmail filter settings, and you'll label email from me and archive it
|
|
162
164
|
unless I email you specifically. Not that useful, but with your own
|
163
165
|
filters and the recipes above, you should be able to make it work (-:
|
164
166
|
|
167
|
+
## Some general tips & tricks
|
168
|
+
|
169
|
+
Here are some things to note when performing filter-fu with gmail:
|
170
|
+
|
171
|
+
* A filter condition tops out at 1500 chars, apparently. This fits a decent amount of conditions, but something to be careful about. There is no check in gmail-britta against this, but Gmail will refuse to import (or drop) filters that violate this.
|
172
|
+
* If you use `archive_unless_directed` heavily, you almost certainly want to check the "Don't override filters" box in Gmail's Inbox preferences.
|
173
|
+
|
165
174
|
## A short apology to you, dear code-diver
|
166
175
|
|
167
176
|
A lot of this is a bit hacky (particularly the filter condition merge
|
data/Rakefile
CHANGED
@@ -9,39 +9,39 @@ rescue Bundler::BundlerError => e
|
|
9
9
|
$stderr.puts "Run `bundle install` to install missing gems"
|
10
10
|
exit e.status_code
|
11
11
|
end
|
12
|
+
|
12
13
|
require 'rake'
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
15
|
+
begin
|
16
|
+
require 'jeweler'
|
17
|
+
Jeweler::Tasks.new do |gem|
|
18
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
19
|
+
gem.name = "gmail-britta"
|
20
|
+
gem.homepage = "http://github.com/antifuchs/gmail-britta"
|
21
|
+
gem.license = "MIT"
|
22
|
+
gem.summary = %Q{Create complex gmail filtersets with a ruby DSL.}
|
23
|
+
gem.description = %Q{This gem helps create large (>50) gmail filter chains by writing xml compatible with gmail's "import/export filters" feature.} #'
|
24
|
+
gem.email = "asf@boinkor.net"
|
25
|
+
gem.authors = ["Andreas Fuchs"]
|
26
|
+
# dependencies defined in Gemfile
|
27
|
+
end
|
28
|
+
Jeweler::RubygemsDotOrgTasks.new
|
29
|
+
rescue LoadError
|
25
30
|
end
|
26
|
-
Jeweler::RubygemsDotOrgTasks.new
|
27
31
|
|
28
|
-
|
29
|
-
|
30
|
-
test
|
31
|
-
|
32
|
-
|
32
|
+
begin
|
33
|
+
require 'rake/testtask'
|
34
|
+
Rake::TestTask.new(:test) do |test|
|
35
|
+
test.libs << 'lib' << 'test'
|
36
|
+
test.pattern = 'test/**/test_*.rb'
|
37
|
+
test.verbose = true
|
38
|
+
end
|
39
|
+
task :default => :test
|
40
|
+
rescue LoadError
|
33
41
|
end
|
34
42
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
test.verbose = true
|
40
|
-
test.rcov_opts << '--exclude "gems/*"'
|
43
|
+
begin
|
44
|
+
require 'yard'
|
45
|
+
YARD::Rake::YardocTask.new
|
46
|
+
rescue LoadError
|
41
47
|
end
|
42
|
-
|
43
|
-
task :default => :test
|
44
|
-
|
45
|
-
require 'yard'
|
46
|
-
|
47
|
-
YARD::Rake::YardocTask.new
|
data/TODO.org
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
* TODO Change the class structure for `Filter`: use a delegate
|
2
|
+
The result of this should allow the filter definition's `self`'s
|
3
|
+
class can be customized (for more targeted conditions and such).
|
4
|
+
* TODO Finalization model for single-filter definition
|
5
|
+
Allow defining multible conditions, actions in the filter body. Then
|
6
|
+
at the end of the block finalize into filter object & register that.
|
7
|
+
* TODO Check for maximum length of filter conditions
|
8
|
+
* TODO Avoid emitting empty filters if there is a .archive_unless_directed
|
9
|
+
* TODO Maybe a more convenient has/has_not criteria format?
|
10
|
+
Something like this?
|
11
|
+
#+BEGIN_SRC ruby
|
12
|
+
has :to, 'gandals@flyingschool.com'
|
13
|
+
has :from, 'fools@shire.com'
|
14
|
+
#+END_SRC
|
15
|
+
Might also make it easier to optimize filter expressions for length
|
16
|
+
(but how to specify OR? Guess this is for a version 1.0/2.0)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.6
|
data/examples/Gemfile
ADDED
data/examples/README.md
ADDED
data/examples/asf.rb
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'gmail-britta'
|
5
|
+
|
6
|
+
if File.exist?(File.expand_path("~/.gmail-britta.personal.rb"))
|
7
|
+
require "~/.gmail-britta.personal.rb"
|
8
|
+
else
|
9
|
+
# Some fake constants to let you run this (-:
|
10
|
+
MY_EMAILS = %w[test@example.com test.tester@example.com]
|
11
|
+
FB_EMAIL = 'from:notification+ieanrst9@facebookemail.com'
|
12
|
+
TWITTER_EMAILS = %w{n-yhex=abcdefg.def-3123f@postmaster.twitter.com}
|
13
|
+
TWITTER_TEST_EMAILS = %w{n-yhex=abcdefg.def-12345@postmaster.twitter.com}
|
14
|
+
BANK_EMAILS = %w{info@bankofamerica.com}
|
15
|
+
V_EMAILS=['from:someone_important@example.com', {:or => MY_EMAILS.map{|email| "to:#{email}"}}]
|
16
|
+
AMAZON_PACKAGE_TRACKING_EMAIL='amazon-package-tracker@example.com' # See https://github.com/antifuchs/amazon-autotracker
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
puts(GmailBritta.filterset(:me => MY_EMAILS) do
|
21
|
+
# Put all mailman reminders away
|
22
|
+
filter {
|
23
|
+
has ['subject:"moderator request"']
|
24
|
+
label 'bulk/mailman'
|
25
|
+
archive
|
26
|
+
mark_read
|
27
|
+
}
|
28
|
+
|
29
|
+
filter {
|
30
|
+
has ['list:mailman@', 'subject:reminder']
|
31
|
+
label 'bulk/mailman'
|
32
|
+
archive
|
33
|
+
mark_read
|
34
|
+
}
|
35
|
+
|
36
|
+
# Archive all mailman mail except confirmation ones
|
37
|
+
filter {
|
38
|
+
has %w{from:mailman subject:confirm}
|
39
|
+
label 'bulk'
|
40
|
+
}.otherwise {
|
41
|
+
has %w{from:mailman}
|
42
|
+
label 'bulk'
|
43
|
+
archive
|
44
|
+
}
|
45
|
+
|
46
|
+
# Label all sysadmin-related email
|
47
|
+
filter {
|
48
|
+
has %w{to:root}
|
49
|
+
archive
|
50
|
+
label 'bulk/admin'
|
51
|
+
}
|
52
|
+
|
53
|
+
# Mailing lists I read:
|
54
|
+
filter {
|
55
|
+
has %w{list:mcclim-*@common-lisp.net}
|
56
|
+
label 'lisp/McCLIM'
|
57
|
+
}.archive_unless_directed.otherwise {
|
58
|
+
has [{:or => %w{list:*@common-lisp.net list:summeroflisp-discuss@lispnyc.org}}]
|
59
|
+
label 'lisp'
|
60
|
+
}.archive_unless_directed
|
61
|
+
|
62
|
+
filter {
|
63
|
+
has [{:or => %w{list:sbcl-devel list:sbcl-help}}]
|
64
|
+
never_spam
|
65
|
+
label 'lisp/sbcl'
|
66
|
+
}.archive_unless_directed
|
67
|
+
|
68
|
+
filter {
|
69
|
+
has %w{list:cclan-list@lists.sourceforge.net}
|
70
|
+
never_spam
|
71
|
+
label 'lisp/cclan'
|
72
|
+
}.archive_unless_directed
|
73
|
+
|
74
|
+
filter {
|
75
|
+
has %w{list:openmcl-*}
|
76
|
+
label 'lisp/clozure'
|
77
|
+
}.archive_unless_directed
|
78
|
+
|
79
|
+
filter {
|
80
|
+
has %w{list:quicklisp@googlegroups.com}
|
81
|
+
label 'lisp/quicklisp'
|
82
|
+
}.archive_unless_directed
|
83
|
+
|
84
|
+
filter {
|
85
|
+
has [{:or => %w{list:thingiverse@googlegroups.com list:replicatorg-dev@googlegroups.com}}]
|
86
|
+
label 'thingiverse'
|
87
|
+
}.archive_unless_directed
|
88
|
+
|
89
|
+
filter {
|
90
|
+
has %w{list:openscad@rocklinux.org}
|
91
|
+
label 'thingiverse'
|
92
|
+
}.archive_unless_directed
|
93
|
+
|
94
|
+
filter {
|
95
|
+
has %w{list:emacs-orgmode@gnu.org}
|
96
|
+
label 'orgmode'
|
97
|
+
}.archive_unless_directed
|
98
|
+
|
99
|
+
filter {
|
100
|
+
has %w{list:elixir-lang-core@googlegroups.com}
|
101
|
+
label 'elixir'
|
102
|
+
}.archive_unless_directed
|
103
|
+
|
104
|
+
filter {
|
105
|
+
has [{:or => %w{list:discuss@lists.acemonstertoys.org list:amt-laserific@googlegroups.com
|
106
|
+
list:noisebridge-discuss@lists.noisebridge.net list:*@lists.metalab.at}}]
|
107
|
+
label 'hackerspaces'
|
108
|
+
}.archive_unless_directed
|
109
|
+
|
110
|
+
# Stuff from the bank:
|
111
|
+
filter {
|
112
|
+
has BANK_EMAILS
|
113
|
+
label 'banking'
|
114
|
+
mark_important
|
115
|
+
}
|
116
|
+
|
117
|
+
filter {
|
118
|
+
has V_EMAILS
|
119
|
+
label '=(-:<'
|
120
|
+
mark_important
|
121
|
+
never_spam
|
122
|
+
}
|
123
|
+
|
124
|
+
# People/things I get occasional personal email from:
|
125
|
+
filter {
|
126
|
+
has [{:or => %w{from:wakra@runtasia.at from:info@mordundmusik.at list:scw08@seedcamp.com list:startups@seedcamp.com}}]
|
127
|
+
label 'bulk'
|
128
|
+
}.archive_unless_directed
|
129
|
+
|
130
|
+
filter {
|
131
|
+
has [FB_EMAIL, {:or => ['subject:"added you as a friend"', 'subject:"sent you a message"', 'subject:"changed the time"']}]
|
132
|
+
label 'bulk/fb'
|
133
|
+
}.otherwise {
|
134
|
+
has [FB_EMAIL]
|
135
|
+
label 'bulk/fb'
|
136
|
+
archive
|
137
|
+
}.otherwise {
|
138
|
+
has TWITTER_EMAILS + [{:or => ['subject:"is now following"', 'subject:"direct message"']}]
|
139
|
+
label 'bulk/twitter'
|
140
|
+
}.otherwise {
|
141
|
+
has [{:or => TWITTER_EMAILS + TWITTER_TEST_EMAILS}]
|
142
|
+
label 'bulk/twitter'
|
143
|
+
archive
|
144
|
+
mark_read
|
145
|
+
}.otherwise {
|
146
|
+
# Mail from web services I don't care about THAT much:
|
147
|
+
bacon_senders = %w{sender@mailer.33mail.com store-news@amazon.com thisweek@yelp.com no-reply@vimeo.com
|
148
|
+
no-reply@mail.goodreads.com *@carsonified.com *@crossmediaweek.org updates@linkedin.com
|
149
|
+
tordotcom@mail.macmillan.com noreply@myopenid.com tor-forge@mail.macmillan.com announce@mailer.evernote.com
|
150
|
+
info@getsatisfaction.com Transport_for_London@info.tfl.gov.uk legendsofzork@joltonline.com news@xing.com
|
151
|
+
noreply@couchsurfing.com noreply@couchsurfing.org newsletter@getsatisfaction.com store-offers@amazon.com
|
152
|
+
gameware@letter.eyepin.com info@busymac.com engage@mail.communications.sun.com *@dotnetsolutions.co.uk
|
153
|
+
office@runtasia.at noreply@cellulare.net support@heroku.com team@mixcloud.com automailer@wikidot.com
|
154
|
+
no-reply@hi.im linkedin@em.linkedin.com chromium@googlecode.com
|
155
|
+
noreply@comixology.com support@plancast.com *@*.boinx.com news@plug.at newsletter@gog.com service@youtube.com
|
156
|
+
email@online.cvs.com info@mail.shoprunner.com yammer@yammer.com info@meetup.com}
|
157
|
+
|
158
|
+
has [{:or => "from:(#{bacon_senders.join("|")})"}]
|
159
|
+
archive
|
160
|
+
label 'bulk'
|
161
|
+
}.otherwise {
|
162
|
+
to_me = me.map {|address| "to:#{address}"}
|
163
|
+
has [{:or => to_me}]
|
164
|
+
label '_asf'
|
165
|
+
}
|
166
|
+
|
167
|
+
filter {
|
168
|
+
has %w{from:ship-confirm@amazon.com}
|
169
|
+
label 'bulk/packages'
|
170
|
+
forward_to AMAZON_PACKAGE_TRACKING_EMAIL
|
171
|
+
}
|
172
|
+
|
173
|
+
end.generate)
|
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.6"
|
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 = "
|
12
|
+
s.date = "2013-02-26"
|
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 = [
|
@@ -18,13 +18,19 @@ Gem::Specification.new do |s|
|
|
18
18
|
]
|
19
19
|
s.files = [
|
20
20
|
".document",
|
21
|
+
".travis.yml",
|
21
22
|
".yardopts",
|
22
23
|
"Gemfile",
|
23
24
|
"Gemfile.lock",
|
24
25
|
"LICENSE.txt",
|
25
26
|
"README.md",
|
26
27
|
"Rakefile",
|
28
|
+
"TODO.org",
|
27
29
|
"VERSION",
|
30
|
+
"examples/Gemfile",
|
31
|
+
"examples/Gemfile.lock",
|
32
|
+
"examples/README.md",
|
33
|
+
"examples/asf.rb",
|
28
34
|
"gmail-britta.gemspec",
|
29
35
|
"lib/gmail-britta.rb",
|
30
36
|
"lib/gmail-britta/filter.rb",
|
@@ -35,7 +41,7 @@ Gem::Specification.new do |s|
|
|
35
41
|
s.homepage = "http://github.com/antifuchs/gmail-britta"
|
36
42
|
s.licenses = ["MIT"]
|
37
43
|
s.require_paths = ["lib"]
|
38
|
-
s.rubygems_version = "1.8.
|
44
|
+
s.rubygems_version = "1.8.23"
|
39
45
|
s.summary = "Create complex gmail filtersets with a ruby DSL."
|
40
46
|
|
41
47
|
if s.respond_to? :specification_version then
|
@@ -43,36 +49,24 @@ Gem::Specification.new do |s|
|
|
43
49
|
|
44
50
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
45
51
|
s.add_runtime_dependency(%q<haml>, ["~> 3.1.6"])
|
52
|
+
s.add_development_dependency(%q<rake>, ["~> 0.9.2"])
|
46
53
|
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
47
|
-
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
48
|
-
s.add_development_dependency(%q<yard>, ["~> 0.8.3"])
|
49
|
-
s.add_development_dependency(%q<redcarpet>, ["~> 2.2.2"])
|
50
54
|
s.add_development_dependency(%q<bundler>, ["~> 1.2.0"])
|
51
|
-
s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
|
52
|
-
s.add_development_dependency(%q<rcov>, [">= 0"])
|
53
55
|
s.add_development_dependency(%q<minitest>, [">= 0"])
|
54
56
|
s.add_development_dependency(%q<nokogiri>, [">= 0"])
|
55
57
|
else
|
56
58
|
s.add_dependency(%q<haml>, ["~> 3.1.6"])
|
59
|
+
s.add_dependency(%q<rake>, ["~> 0.9.2"])
|
57
60
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
58
|
-
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
59
|
-
s.add_dependency(%q<yard>, ["~> 0.8.3"])
|
60
|
-
s.add_dependency(%q<redcarpet>, ["~> 2.2.2"])
|
61
61
|
s.add_dependency(%q<bundler>, ["~> 1.2.0"])
|
62
|
-
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
63
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
64
62
|
s.add_dependency(%q<minitest>, [">= 0"])
|
65
63
|
s.add_dependency(%q<nokogiri>, [">= 0"])
|
66
64
|
end
|
67
65
|
else
|
68
66
|
s.add_dependency(%q<haml>, ["~> 3.1.6"])
|
67
|
+
s.add_dependency(%q<rake>, ["~> 0.9.2"])
|
69
68
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
70
|
-
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
71
|
-
s.add_dependency(%q<yard>, ["~> 0.8.3"])
|
72
|
-
s.add_dependency(%q<redcarpet>, ["~> 2.2.2"])
|
73
69
|
s.add_dependency(%q<bundler>, ["~> 1.2.0"])
|
74
|
-
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
75
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
76
70
|
s.add_dependency(%q<minitest>, [">= 0"])
|
77
71
|
s.add_dependency(%q<nokogiri>, [">= 0"])
|
78
72
|
end
|
data/lib/gmail-britta/filter.rb
CHANGED
@@ -71,6 +71,10 @@ module GmailBritta
|
|
71
71
|
single_write_accessor :has_not, 'doesNotHaveTheWord' do |list|
|
72
72
|
emit_filter_spec(list)
|
73
73
|
end
|
74
|
+
|
75
|
+
# Filter for messages that have an attachment
|
76
|
+
# @macro bool_dsl_method
|
77
|
+
single_write_boolean_accessor :has_attachment, 'hasAttachment'
|
74
78
|
# @!endgroup
|
75
79
|
|
76
80
|
# Register and return a new filter that matches only if this
|
@@ -108,7 +112,7 @@ module GmailBritta
|
|
108
112
|
# @return [Filter] the current (not the newly-constructed filter)
|
109
113
|
def archive_unless_directed(options={})
|
110
114
|
mark_as_read=options[:mark_read]
|
111
|
-
tos=(options[:to] || me)
|
115
|
+
tos=Array(options[:to] || me)
|
112
116
|
filter = Filter.new(@britta, :log => @log).perform do
|
113
117
|
has_not [{:or => tos.map {|to| "to:#{to}"}}]
|
114
118
|
archive
|
@@ -190,7 +194,7 @@ ATOM
|
|
190
194
|
@has_not = new_has_not
|
191
195
|
end
|
192
196
|
|
193
|
-
def self.emit_filter_spec(filter, infix=' ')
|
197
|
+
def self.emit_filter_spec(filter, infix=' ', recursive=false)
|
194
198
|
str = ''
|
195
199
|
case filter
|
196
200
|
when String
|
@@ -199,17 +203,16 @@ ATOM
|
|
199
203
|
filter.keys.each do |key|
|
200
204
|
case key
|
201
205
|
when :or
|
202
|
-
|
203
|
-
str << emit_filter_spec(filter[key], ' OR ')
|
204
|
-
str << ')'
|
206
|
+
str << emit_filter_spec(filter[key], ' OR ', recursive)
|
205
207
|
when :not
|
206
|
-
|
207
|
-
str << emit_filter_spec(filter[key], ' ')
|
208
|
-
str << ')'
|
208
|
+
str << '-'
|
209
|
+
str << emit_filter_spec(filter[key], ' ', true)
|
209
210
|
end
|
210
211
|
end
|
211
212
|
when Array
|
212
|
-
str <<
|
213
|
+
str << '(' if recursive
|
214
|
+
str << filter.map {|elt| emit_filter_spec(elt, ' ', true)}.join(infix)
|
215
|
+
str << ')' if recursive
|
213
216
|
end
|
214
217
|
str
|
215
218
|
end
|
@@ -217,8 +220,9 @@ ATOM
|
|
217
220
|
# Note a filter definition on the logger.
|
218
221
|
# @note for debugging only.
|
219
222
|
def log_definition
|
223
|
+
return unless @log.debug?
|
220
224
|
@log.debug "Filter: #{self}"
|
221
|
-
Filter.single_write_accessors.each do |name|
|
225
|
+
Filter.single_write_accessors.each do |name, gmail_name|
|
222
226
|
val = instance_variable_get(Filter.ivar_name(name))
|
223
227
|
@log.debug " #{name}: #{val}" if val
|
224
228
|
end
|
data/test/test_gmail-britta.rb
CHANGED
@@ -16,7 +16,7 @@ describe GmailBritta do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def dom(filterset)
|
19
|
-
text =
|
19
|
+
text = filterset.generate
|
20
20
|
#puts text
|
21
21
|
Nokogiri::XML.parse(text)
|
22
22
|
end
|
@@ -44,5 +44,18 @@ describe GmailBritta do
|
|
44
44
|
assert_equal(2, filters.xpath('/a:feed/a:entry/apps:property[@name="hasTheWord"]',ns).length, "Should have exactly one 'has' property")
|
45
45
|
end
|
46
46
|
|
47
|
-
|
47
|
+
describe "issues" do
|
48
|
+
it "doesn't fail issue #4 - correctly-parenthesised nested ANDs" do
|
49
|
+
fs = GmailBritta.filterset do
|
50
|
+
filter {
|
51
|
+
has :or => [['subject:whee', 'from:zot@spammer.com'], 'from:bob@bob.com', 'from:foo@foo.com']
|
52
|
+
label 'yay'
|
53
|
+
}
|
54
|
+
end
|
55
|
+
filters = dom(fs)
|
56
|
+
|
57
|
+
filter_text = filters.xpath('/a:feed/a:entry/apps:property[@name="hasTheWord"]',ns).first['value']
|
58
|
+
assert_equal('(subject:whee from:zot@spammer.com) OR from:bob@bob.com OR from:foo@foo.com', filter_text)
|
59
|
+
end
|
60
|
+
end
|
48
61
|
end
|
metadata
CHANGED
@@ -1,191 +1,135 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: gmail-britta
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.6
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
- 5
|
10
|
-
version: 0.1.5
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Andreas Fuchs
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
12
|
+
date: 2013-02-26 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: haml
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
22
17
|
none: false
|
23
|
-
requirements:
|
18
|
+
requirements:
|
24
19
|
- - ~>
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
hash: 15
|
27
|
-
segments:
|
28
|
-
- 3
|
29
|
-
- 1
|
30
|
-
- 6
|
20
|
+
- !ruby/object:Gem::Version
|
31
21
|
version: 3.1.6
|
32
|
-
prerelease: false
|
33
22
|
type: :runtime
|
34
|
-
name: haml
|
35
|
-
requirement: *id001
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
|
-
version_requirements: &id002 !ruby/object:Gem::Requirement
|
38
|
-
none: false
|
39
|
-
requirements:
|
40
|
-
- - ">="
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
hash: 3
|
43
|
-
segments:
|
44
|
-
- 0
|
45
|
-
version: "0"
|
46
23
|
prerelease: false
|
47
|
-
|
48
|
-
name: shoulda
|
49
|
-
requirement: *id002
|
50
|
-
- !ruby/object:Gem::Dependency
|
51
|
-
version_requirements: &id003 !ruby/object:Gem::Requirement
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
25
|
none: false
|
53
|
-
requirements:
|
26
|
+
requirements:
|
54
27
|
- - ~>
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
version: "3.12"
|
61
|
-
prerelease: false
|
62
|
-
type: :development
|
63
|
-
name: rdoc
|
64
|
-
requirement: *id003
|
65
|
-
- !ruby/object:Gem::Dependency
|
66
|
-
version_requirements: &id004 !ruby/object:Gem::Requirement
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.1.6
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
67
33
|
none: false
|
68
|
-
requirements:
|
34
|
+
requirements:
|
69
35
|
- - ~>
|
70
|
-
- !ruby/object:Gem::Version
|
71
|
-
|
72
|
-
segments:
|
73
|
-
- 0
|
74
|
-
- 8
|
75
|
-
- 3
|
76
|
-
version: 0.8.3
|
77
|
-
prerelease: false
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 0.9.2
|
78
38
|
type: :development
|
79
|
-
name: yard
|
80
|
-
requirement: *id004
|
81
|
-
- !ruby/object:Gem::Dependency
|
82
|
-
version_requirements: &id005 !ruby/object:Gem::Requirement
|
83
|
-
none: false
|
84
|
-
requirements:
|
85
|
-
- - ~>
|
86
|
-
- !ruby/object:Gem::Version
|
87
|
-
hash: 3
|
88
|
-
segments:
|
89
|
-
- 2
|
90
|
-
- 2
|
91
|
-
- 2
|
92
|
-
version: 2.2.2
|
93
39
|
prerelease: false
|
94
|
-
|
95
|
-
name: redcarpet
|
96
|
-
requirement: *id005
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
version_requirements: &id006 !ruby/object:Gem::Requirement
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
41
|
none: false
|
100
|
-
requirements:
|
42
|
+
requirements:
|
101
43
|
- - ~>
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.9.2
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: shoulda
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
110
54
|
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
111
63
|
name: bundler
|
112
|
-
requirement:
|
113
|
-
- !ruby/object:Gem::Dependency
|
114
|
-
version_requirements: &id007 !ruby/object:Gem::Requirement
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
115
65
|
none: false
|
116
|
-
requirements:
|
66
|
+
requirements:
|
117
67
|
- - ~>
|
118
|
-
- !ruby/object:Gem::Version
|
119
|
-
|
120
|
-
segments:
|
121
|
-
- 1
|
122
|
-
- 8
|
123
|
-
- 4
|
124
|
-
version: 1.8.4
|
125
|
-
prerelease: false
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 1.2.0
|
126
70
|
type: :development
|
127
|
-
name: jeweler
|
128
|
-
requirement: *id007
|
129
|
-
- !ruby/object:Gem::Dependency
|
130
|
-
version_requirements: &id008 !ruby/object:Gem::Requirement
|
131
|
-
none: false
|
132
|
-
requirements:
|
133
|
-
- - ">="
|
134
|
-
- !ruby/object:Gem::Version
|
135
|
-
hash: 3
|
136
|
-
segments:
|
137
|
-
- 0
|
138
|
-
version: "0"
|
139
71
|
prerelease: false
|
140
|
-
|
141
|
-
name: rcov
|
142
|
-
requirement: *id008
|
143
|
-
- !ruby/object:Gem::Dependency
|
144
|
-
version_requirements: &id009 !ruby/object:Gem::Requirement
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
145
73
|
none: false
|
146
|
-
requirements:
|
147
|
-
- -
|
148
|
-
- !ruby/object:Gem::Version
|
149
|
-
|
150
|
-
|
151
|
-
- 0
|
152
|
-
version: "0"
|
153
|
-
prerelease: false
|
154
|
-
type: :development
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 1.2.0
|
78
|
+
- !ruby/object:Gem::Dependency
|
155
79
|
name: minitest
|
156
|
-
requirement:
|
157
|
-
- !ruby/object:Gem::Dependency
|
158
|
-
version_requirements: &id010 !ruby/object:Gem::Requirement
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
159
81
|
none: false
|
160
|
-
requirements:
|
161
|
-
- -
|
162
|
-
- !ruby/object:Gem::Version
|
163
|
-
|
164
|
-
segments:
|
165
|
-
- 0
|
166
|
-
version: "0"
|
167
|
-
prerelease: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
168
86
|
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
169
95
|
name: nokogiri
|
170
|
-
requirement:
|
171
|
-
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
description: This gem helps create large (>50) gmail filter chains by writing xml
|
111
|
+
compatible with gmail's "import/export filters" feature.
|
172
112
|
email: asf@boinkor.net
|
173
113
|
executables: []
|
174
|
-
|
175
114
|
extensions: []
|
176
|
-
|
177
|
-
extra_rdoc_files:
|
115
|
+
extra_rdoc_files:
|
178
116
|
- LICENSE.txt
|
179
117
|
- README.md
|
180
|
-
files:
|
118
|
+
files:
|
181
119
|
- .document
|
120
|
+
- .travis.yml
|
182
121
|
- .yardopts
|
183
122
|
- Gemfile
|
184
123
|
- Gemfile.lock
|
185
124
|
- LICENSE.txt
|
186
125
|
- README.md
|
187
126
|
- Rakefile
|
127
|
+
- TODO.org
|
188
128
|
- VERSION
|
129
|
+
- examples/Gemfile
|
130
|
+
- examples/Gemfile.lock
|
131
|
+
- examples/README.md
|
132
|
+
- examples/asf.rb
|
189
133
|
- gmail-britta.gemspec
|
190
134
|
- lib/gmail-britta.rb
|
191
135
|
- lib/gmail-britta/filter.rb
|
@@ -193,37 +137,31 @@ files:
|
|
193
137
|
- lib/gmail-britta/single_write_accessors.rb
|
194
138
|
- test/test_gmail-britta.rb
|
195
139
|
homepage: http://github.com/antifuchs/gmail-britta
|
196
|
-
licenses:
|
140
|
+
licenses:
|
197
141
|
- MIT
|
198
142
|
post_install_message:
|
199
143
|
rdoc_options: []
|
200
|
-
|
201
|
-
require_paths:
|
144
|
+
require_paths:
|
202
145
|
- lib
|
203
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
146
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
204
147
|
none: false
|
205
|
-
requirements:
|
206
|
-
- -
|
207
|
-
- !ruby/object:Gem::Version
|
208
|
-
|
209
|
-
segments:
|
148
|
+
requirements:
|
149
|
+
- - ! '>='
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
segments:
|
210
153
|
- 0
|
211
|
-
|
212
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
|
+
hash: -4216942302698371957
|
155
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
213
156
|
none: false
|
214
|
-
requirements:
|
215
|
-
- -
|
216
|
-
- !ruby/object:Gem::Version
|
217
|
-
|
218
|
-
segments:
|
219
|
-
- 0
|
220
|
-
version: "0"
|
157
|
+
requirements:
|
158
|
+
- - ! '>='
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
221
161
|
requirements: []
|
222
|
-
|
223
162
|
rubyforge_project:
|
224
|
-
rubygems_version: 1.8.
|
163
|
+
rubygems_version: 1.8.23
|
225
164
|
signing_key:
|
226
165
|
specification_version: 3
|
227
166
|
summary: Create complex gmail filtersets with a ruby DSL.
|
228
167
|
test_files: []
|
229
|
-
|