gmail-britta 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/antifuchs/gmail-britta.png?branch=master)](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
|
-
|