calfilter 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,6 @@
1
+ === 1.0.0 / 2008-05-02
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
data/Manifest.txt ADDED
@@ -0,0 +1,10 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ example.rb
6
+ lib/calfilter.rb
7
+ lib/calfilter/cgi.rb
8
+ lib/calfilter/tripit.rb
9
+ test/test_calfilter.rb
10
+ test/test_calfilter_cgi.rb
data/README.txt ADDED
@@ -0,0 +1,69 @@
1
+ = calfilter
2
+
3
+ * http://opensource.thinkrelevance.com/wiki/calfilter
4
+
5
+ == DESCRIPTION:
6
+
7
+ calfilter is a small library to assist in writing filtering
8
+ programs for icalendar files or streams. It can be used for
9
+ various purposes, including:
10
+
11
+ * removing items from icalendar feeds that are not interesting to you
12
+ * removing private information from your own calendar before publishing it to others
13
+ * reformatting a provided calendar to highlight particular information
14
+
15
+ == FEATURES/PROBLEMS:
16
+
17
+ * require 'calfilter/tripit' to add some methods specific to
18
+ tripit.com calendar feeds.
19
+
20
+ * require 'calfilter/cgi' to automatically turn your filter into
21
+ a CGI script. The CGI object is available as 'CalFilter::CGI'.
22
+
23
+ == SYNOPSIS:
24
+
25
+ require 'calfilter'
26
+
27
+ cals = filter_calendars_at('some_url') do |cal|
28
+ cal.keep(:events) # not journals, todos, or freebusys
29
+
30
+ cal.filter_events do |evt|
31
+ # Remove events I've marked private
32
+ evt.remove if evt.description =~ /PRIVATE/
33
+ # Don't reveal phone numbers of my contacts
34
+ evt.description.sub! /\d{3}-\d{4}/, '###-####'
35
+ end
36
+ end
37
+
38
+ == REQUIREMENTS:
39
+
40
+ calfilter depends on the icalendar gem.
41
+
42
+ == INSTALL:
43
+
44
+ sudo gem install calfilter
45
+
46
+ == LICENSE:
47
+
48
+ (The MIT License)
49
+
50
+ Copyright (c) 2008 Relevance, Inc.
51
+
52
+ Permission is hereby granted, free of charge, to any person obtaining
53
+ a copy of this software and associated documentation files (the
54
+ 'Software'), to deal in the Software without restriction, including
55
+ without limitation the rights to use, copy, modify, merge, publish,
56
+ distribute, sublicense, and/or sell copies of the Software, and to
57
+ permit persons to whom the Software is furnished to do so, subject to
58
+ the following conditions:
59
+
60
+ The above copyright notice and this permission notice shall be
61
+ included in all copies or substantial portions of the Software.
62
+
63
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
64
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
65
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
66
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
67
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
68
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
69
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/calfilter.rb'
6
+
7
+ class Hoe
8
+ def extra_deps
9
+ @extra_deps.reject do |x|
10
+ Array(x).first == 'hoe'
11
+ end
12
+ end
13
+ end
14
+
15
+ Hoe.new('calfilter', CalFilter::VERSION) do |p|
16
+ p.rubyforge_name = 'thinkrelevance'
17
+ p.developer('Glenn Vanderburg', 'glenn@thinkrelevance.com')
18
+ p.extra_deps = %w{icalendar}
19
+ end
20
+
21
+ # vim: syntax=Ruby
data/example.rb ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ gem 'calfilter'
5
+ require 'calfilter'
6
+ require 'calfilter/cgi'
7
+
8
+ filter_calendars_at(CalFilter::CGI.query_string}) do |cal|
9
+ cal.keep(:events) # drop todos, journals, etc.
10
+
11
+ cal.filter_events do |evt|
12
+ evt.keep if evt.dtstart >= Date.today # ignore stuff in the past
13
+ end
14
+ end
@@ -0,0 +1,38 @@
1
+ require 'calfilter'
2
+ require 'cgi'
3
+ require 'stringio'
4
+
5
+ module CalFilter
6
+
7
+ class CGIWrapper
8
+ attr_reader :output_stream
9
+
10
+ def initialize(output_stream)
11
+ set_cgi_constant
12
+ CalFilter.output_stream = @output_stream = output_stream
13
+ end
14
+
15
+ def create_cgi_instance
16
+ CGI.new
17
+ end
18
+
19
+ def set_cgi_constant
20
+ CalFilter.const_set('CGI', create_cgi_instance) unless CalFilter.const_defined?('CGI')
21
+ end
22
+
23
+ def finish
24
+ CGI.out('text/calendar; charset=utf-8'){ output_stream.string }
25
+ end
26
+ end
27
+
28
+ def self.make_cgi_wrapper
29
+ CGIWrapper.new(StringIO.new)
30
+ end
31
+
32
+ CGIWRAPPER = make_cgi_wrapper
33
+
34
+ end
35
+
36
+ at_exit do
37
+ CalFilter::CGIWRAPPER.finish
38
+ end
@@ -0,0 +1,31 @@
1
+ require 'calfilter'
2
+
3
+ module CalFilter
4
+ module TripIt
5
+ EVENT_TYPES = {
6
+ # The keys are the $1 strings from description =~ /^\[(.*?)\]/m
7
+ nil => :trip,
8
+ 'Flight' => :flight,
9
+ 'Car Rental' => :car,
10
+ 'Hotel' => :hotel,
11
+ 'Directions' => :directions,
12
+ 'Activity' => :activity
13
+ }
14
+
15
+ def tripit_type(*args)
16
+ return :unknown unless __kind__ == 'event'
17
+ if args.empty?
18
+ description =~ /^\[(.+?)\]/m
19
+ TripIt::EVENT_TYPES[$1] || :unknown
20
+ else
21
+ args.include?(tripit_type)
22
+ end
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ class ResourceWrapper
29
+ include TripIt
30
+ end
31
+ end
data/lib/calfilter.rb ADDED
@@ -0,0 +1,166 @@
1
+ %w{rubygems icalendar date open-uri}.each{|l| require l}
2
+
3
+ module CalFilter
4
+ VERSION = '1.0.0'
5
+
6
+ def self.output_stream
7
+ @output_stream
8
+ end
9
+
10
+ def self.output_stream=(stream)
11
+ @output_stream = stream
12
+ end
13
+
14
+ class FilterError < RuntimeError
15
+ end
16
+
17
+ class ResourceWrapper
18
+ def initialize(delegate, kind)
19
+ @delegate = delegate
20
+ @kind = kind
21
+ end
22
+
23
+ def __delegate__
24
+ @delegate
25
+ end
26
+
27
+ def __action__
28
+ @keep_or_remove || :default
29
+ end
30
+
31
+ def __kind__
32
+ @kind
33
+ end
34
+
35
+ def remove
36
+ __flag__ :remove
37
+ end
38
+
39
+ def keep
40
+ __flag__ :keep
41
+ end
42
+
43
+ def method_missing(symbol, *args, &block)
44
+ __delegate__.send(symbol, *args, &block)
45
+ end
46
+
47
+ protected
48
+
49
+ def __flag__(sym)
50
+ other_sym = (sym == :keep ? :remove : :keep)
51
+ raise FilterError, "Cannot both keep and remove the same #{@kind}", __caller__ if @keep_or_remove == other_sym
52
+ @keep_or_remove = sym
53
+ throw :bailout if sym == :remove
54
+ end
55
+
56
+ def __caller__
57
+ f = __FILE__
58
+ stack = caller
59
+ stack.each_with_index do |s, i|
60
+ return stack[i..-1] unless s =~ Regexp.new("^#{Regexp.escape(f)}:")
61
+ end
62
+ end
63
+
64
+ end
65
+
66
+ class CalendarWrapper < ResourceWrapper
67
+ RESOURCE_TYPES = %w{events freebusys journals todos}
68
+
69
+ def initialize(calendar)
70
+ super(calendar, 'calendar')
71
+ end
72
+
73
+ def remove(*args)
74
+ if args.empty?
75
+ super
76
+ else
77
+ __remove_elements__ :remove, args
78
+ end
79
+ end
80
+
81
+ def keep(*args)
82
+ if args.empty?
83
+ super
84
+ else
85
+ __remove_elements__ :keep, RESOURCE_TYPES.map{|t|t.to_sym} - args
86
+ end
87
+ end
88
+
89
+ def method_missing(symbol, *args, &block)
90
+ if symbol.to_s =~ /^filter_(.*)$/ && RESOURCE_TYPES.include?($1)
91
+ __filter_resource__($1, *args, &block)
92
+ else
93
+ super(symbol, *args, &block)
94
+ end
95
+ end
96
+
97
+ private
98
+
99
+ def __remove_elements__(sym, to_remove)
100
+ other_sym = (sym == :keep ? :remove : :keep)
101
+ raise FilterError, "Cannot call both keep and remove for elements in the same calendar", __caller__ if @keep_or_remove_elements == other_sym
102
+ @keep_or_remove_elements = sym
103
+ to_remove.each{|sym| __delegate__.send(sym).clear}
104
+ end
105
+
106
+ def __filter_resource__(resource_type)
107
+ resources = __delegate__.send(resource_type.to_sym)
108
+ return resources unless block_given?
109
+ actions = resources.map do |res|
110
+ wrapper = CalFilter.wrap_resource(res, resource_type)
111
+ catch(:bailout) do
112
+ yield wrapper
113
+ end
114
+ wrapper.__action__
115
+ end
116
+ __delegate__.send("#{resource_type}=".to_sym, CalFilter::keep_or_delete_items(resources, resource_type, actions))
117
+ end
118
+
119
+ end
120
+
121
+ def self.wrap_calendar(cal)
122
+ CalendarWrapper.new(cal)
123
+ end
124
+
125
+ def self.wrap_resource(res, plural_resource_type)
126
+ # This works with the particular resource names in Icalendar:
127
+ singular_resource_type = plural_resource_type.sub(/s$/, '')
128
+ ResourceWrapper.new(res, singular_resource_type)
129
+ end
130
+
131
+ def self.keep_or_delete_items(items, type, actions)
132
+ if actions.include?(:keep) && actions.include?(:remove)
133
+ raise CalFilter::FilterError, "Cannot both keep and remove #{type} in the same group.", caller(2)
134
+ end
135
+ keep_action = (actions.include?(:keep) ? :keep : :default)
136
+ kept_items = []
137
+ items.each_with_index{|item, i| kept_items << item if actions[i] == keep_action}
138
+ kept_items
139
+ end
140
+
141
+ end
142
+
143
+ def filter_calendars_at(url, &block)
144
+ filter_calendars(open(url, 'r'), &block)
145
+ end
146
+
147
+ def filter_calendars(ics_data, &block)
148
+ filter_icalendars(Icalendar.parse(ics_data), &block)
149
+ end
150
+
151
+ def filter_icalendars(cals)
152
+ return cals unless block_given?
153
+ actions = cals.map do |cal|
154
+ wrapper = CalFilter.wrap_calendar(cal)
155
+ catch(:bailout) do
156
+ yield wrapper
157
+ end
158
+ wrapper.__action__
159
+ end
160
+ new_cals = CalFilter::keep_or_delete_items(cals, 'calendars', actions)
161
+ os = CalFilter.output_stream
162
+ unless os.nil?
163
+ new_cals.each{|cal| os.puts cal.to_ical}
164
+ end
165
+ new_cals
166
+ end
@@ -0,0 +1,102 @@
1
+ require 'rubygems'
2
+ require 'test/spec'
3
+ require 'mocha'
4
+
5
+ require 'calfilter'
6
+
7
+ describe "filtering calendars" do
8
+ it "should pass things straight through" do
9
+ expected_cals = [1, 2, 3]
10
+ actual_cals = filter_icalendars(expected_cals.dup)
11
+ assert_equal expected_cals.size, actual_cals.size
12
+ end
13
+
14
+ it "should delete a calendar when told" do
15
+ cals = filter_icalendars([1, 2, 3]){|cal| cal.remove if cal.__delegate__ == 2}
16
+ assert_equal [1, 3], cals
17
+ end
18
+
19
+ it "should keep a calendar when told" do
20
+ cals = filter_icalendars([1, 2, 3]){|cal| cal.keep if cal.__delegate__ == 2}
21
+ assert_equal [2], cals
22
+ end
23
+
24
+ it "should delete parts of a calendar when told" do
25
+ cals = filter_icalendars(%w{1 2 3}) do |cal|
26
+ events = mock(:clear => nil)
27
+ cal.__delegate__.stubs(:events).returns(events)
28
+ cal.remove(:events)
29
+ end
30
+ end
31
+
32
+ it "should keep parts of a calendar when told" do
33
+ cals = filter_icalendars(%w{1 2 3}) do |cal|
34
+ events = mock(:clear => nil)
35
+ cal.__delegate__.stubs(:events).returns(events)
36
+ cal.keep(:freebusys, :journals, :todos)
37
+ end
38
+ end
39
+
40
+ it "should complain if we both keep and remove a calendar" do
41
+ assert_raise(CalFilter::FilterError) do
42
+ cals = filter_icalendars([1]){|cal| cal.keep; cal.remove}
43
+ end
44
+ end
45
+
46
+ it "should complain if we keep one calendar and remove another" do
47
+ assert_raises(CalFilter::FilterError) do
48
+ cals = filter_icalendars([1, 2, 3]) do |cal|
49
+ case cal.__delegate__
50
+ when 1: cal.keep;
51
+ when 2: cal.remove;
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ it "should delegate unknown methods to the Calendar objects" do
58
+ results = []
59
+ cals = filter_icalendars([0, 1]){|cal| results << cal.zero?}
60
+ assert_equal [true, false], results
61
+ end
62
+
63
+ end
64
+
65
+ describe "filtering resources" do
66
+ before do
67
+ @cal = Icalendar::Calendar.new
68
+ @cal.event do
69
+ dtstart Date.new(2005, 04, 29)
70
+ dtend Date.new(2005, 04, 28)
71
+ summary "Meeting with the man."
72
+ description "Have a long lunch meeting and decide nothing..."
73
+ klass "PRIVATE"
74
+ end
75
+ @cal.event do
76
+ dtstart Date.new(2006, 04, 29)
77
+ dtend Date.new(2005, 04, 28)
78
+ summary "Project review"
79
+ description "Find a bunch of stuff to complain about and get complaining."
80
+ klass "PUBLIC"
81
+ end
82
+ end
83
+
84
+ xit "should leave resources alone if no block specified" do
85
+ filter_icalendars([@cal]) do |cal|
86
+ cal.__delegate__.expects(:events).returns(@cal.events)
87
+ cal.filter_events
88
+ end
89
+ end
90
+
91
+ xit "should delete a resource when told"
92
+ #@calw = CalFilter.wrap_resource(@cal.events, 'events')
93
+
94
+ xit "should keep a resource when told"
95
+
96
+ xit "should complain if we both keep and remove a resource"
97
+
98
+ xit "should complain if we keep one resource and remove another"
99
+
100
+ xit "should delegate unknown methods to the resource objects"
101
+
102
+ end
@@ -0,0 +1,35 @@
1
+ require 'rubygems'
2
+ require 'test/spec'
3
+ require 'mocha'
4
+
5
+ require 'calfilter'
6
+
7
+ def at_exit(&block)
8
+ $at_exit_block = block
9
+ end
10
+
11
+ describe "calfilter cgi scripts" do
12
+ before(:all) do
13
+ CalFilter::CGI = ''
14
+ require 'calfilter/cgi'
15
+ end
16
+
17
+ it "should initialize a CGIWrapper object" do
18
+ assert_not_nil CalFilter::CGIWrapper
19
+ end
20
+
21
+ it "should set CalFilter's output stream" do
22
+ assert_not_nil CalFilter::CGIWRAPPER.output_stream
23
+ assert_equal CalFilter::CGIWRAPPER.output_stream, CalFilter.output_stream
24
+ end
25
+
26
+ it "should finish the CGI on process exit" do
27
+ CalFilter::CGIWRAPPER.expects(:finish)
28
+ $at_exit_block.call
29
+ end
30
+
31
+ it "should write proper output when finishing" do
32
+ CalFilter::CGI.expects(:out).with('text/calendar; charset=utf-8')
33
+ CalFilter::CGIWRAPPER.finish
34
+ end
35
+ end
data.tar.gz.sig ADDED
Binary file
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: calfilter
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Glenn Vanderburg
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDRDCCAiygAwIBAgIBADANBgkqhkiG9w0BAQUFADBIMQ4wDAYDVQQDDAVnbGVu
14
+ bjEeMBwGCgmSJomT8ixkARkWDnRoaW5rcmVsZXZhbmNlMRYwFAYKCZImiZPyLGQB
15
+ GRYGY29tZ2x2MB4XDTA4MDMwNDIwNDIzNFoXDTA5MDMwNDIwNDIzNFowSDEOMAwG
16
+ A1UEAwwFZ2xlbm4xHjAcBgoJkiaJk/IsZAEZFg50aGlua3JlbGV2YW5jZTEWMBQG
17
+ CgmSJomT8ixkARkWBmNvbWdsdjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
18
+ ggEBALXdD5Y00ZMPO/dL8sj1IcfomhezB+9rsO/FoCnR9TJyaOGPBAJBEfyA3SkP
19
+ hpbCkkUDpNlRR2sQHrtqBJovpw2oX6zakrG8PnDQQPU1oo0tWkiDtPFQc9lgDJOA
20
+ S/nQiS2D9rusOmpj84KpC6DUN80M+ap9z04Xadobuv7Cer/dTOfs4skUBiN/aonA
21
+ qtaRNOlOPGyPGiCa8tUQd53fVml2hSKIgt/+HfBHHWZkHs9UQRsqd7GICFi5R24i
22
+ ZNXbaRzw4637eCcjBhlEes9KMJOwayZ1KXHWzOdSzRJUI6nT4AQjw3GCyuXBmCY0
23
+ LFrbGOLYuqfiv/zr+Z+qqyI3Ul0CAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8E
24
+ BAMCBLAwHQYDVR0OBBYEFOsd6jtw384ogcRecKkFdFpm9SQkMA0GCSqGSIb3DQEB
25
+ BQUAA4IBAQBokYH6Pe63OU1O9t4z6jEom2NDieUlLWD9PTshI4UXUjxd83mjmg/Y
26
+ Cer/yqFHqQEW6BLNRmH6l2lw2Rb8CZdlh7K8Q8F/94M+actty2UvMgTyVEtOnyh/
27
+ QU8nqEil5vl7ppCwDeSF32cebsQoimkgAamOxVZVe5ipP1+UIO+Eu92Jt5k0hrnd
28
+ 1Fz3W+wrffm45P2X/6Z36dXgZKn8dlHuYtsqgpQxBC92oE7UqHXvwAu3FFe+1EV7
29
+ LrV1pr2EyieDotJOooYNz/E+9ZeL14MBhDOVmPr4KHTTK4VwdxFtAKu2QK/NfAAl
30
+ zrNa6ECLh1VS/pV78rYbAO1ZXsg3l7bY
31
+ -----END CERTIFICATE-----
32
+
33
+ date: 2008-05-02 00:00:00 -05:00
34
+ default_executable:
35
+ dependencies:
36
+ - !ruby/object:Gem::Dependency
37
+ name: icalendar
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ description: "calfilter is a small library to assist in writing filtering programs for icalendar files or streams. It can be used for various purposes, including: * removing items from icalendar feeds that are not interesting to you * removing private information from your own calendar before publishing it to others * reformatting a provided calendar to highlight particular information"
46
+ email:
47
+ - glenn@thinkrelevance.com
48
+ executables: []
49
+
50
+ extensions: []
51
+
52
+ extra_rdoc_files:
53
+ - History.txt
54
+ - Manifest.txt
55
+ - README.txt
56
+ files:
57
+ - History.txt
58
+ - Manifest.txt
59
+ - README.txt
60
+ - Rakefile
61
+ - example.rb
62
+ - lib/calfilter.rb
63
+ - lib/calfilter/cgi.rb
64
+ - lib/calfilter/tripit.rb
65
+ - test/test_calfilter.rb
66
+ - test/test_calfilter_cgi.rb
67
+ has_rdoc: true
68
+ homepage: http://opensource.thinkrelevance.com/wiki/calfilter
69
+ post_install_message:
70
+ rdoc_options:
71
+ - --main
72
+ - README.txt
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: "0"
80
+ version:
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: "0"
86
+ version:
87
+ requirements: []
88
+
89
+ rubyforge_project: thinkrelevance
90
+ rubygems_version: 1.0.1
91
+ signing_key:
92
+ specification_version: 2
93
+ summary: calfilter is a small library to assist in writing filtering programs for icalendar files or streams
94
+ test_files:
95
+ - test/test_calfilter.rb
96
+ - test/test_calfilter_cgi.rb
metadata.gz.sig ADDED
@@ -0,0 +1 @@
1
+ u\�p S`S"y�+�a7��8i���0ԏ��B�(l3_�8�Ƚ��2p;���7v���ln�s;��ֵ;�l=�}���o�lށ�F%�̭XB�������d۾�;���!>�Yʿ�f;��1 � x��&�=.�EJ�W6@�#�+�L��S��y.�̿��q_T�ʙ2Ѭ$��\��\U�$�J�>>�����l|~@����vg��k-X$Z�i-��S ��;��j3�6=h