gcalevents 0.4.10

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.
@@ -0,0 +1 @@
1
+ p1�S���4l,��w �𗍾5����O[���,i����:1��A��ڝ$hB��9@0I��ut�����uM�I ���XX���"<XR��d��%,L����R�����2Y�m?�s�OoU_��\�d�e�IwO�}!и*�}��:؈uQ�xZ/5�Lo̡qK:�p�� �m�24K�]~ �G86eHfX�\�����v�>L�^ �$�yD>{�76�؃ j�D�ϚCSِ8��� ��m�����d�
@@ -0,0 +1,40 @@
1
+ CHANGELOG
2
+ *********
3
+ 0.4.10 2007-11-13
4
+ -----------------
5
+ Change of display format
6
+
7
+ 0.4.9 2007-11-11
8
+ ----------------
9
+ Description can be displayed shortened.
10
+
11
+ 0.4.8
12
+ -----
13
+ Bugfixes:
14
+ - works with one or none calendars defined in configuration
15
+
16
+ 0.4.7
17
+ -----
18
+ Added RDoc.
19
+ Bugfixes:
20
+ - added support for Windows without HOME environmental variable
21
+ Changes:
22
+ - "next day" to "earliest day" :)
23
+
24
+ 0.4.6
25
+ -----
26
+ Bugfixes:
27
+ - dealing with events that started in the past
28
+ - sending emails
29
+
30
+ 0.4.5
31
+ -----
32
+ - added displaying of Location field
33
+
34
+ 0.4.4
35
+ -----
36
+ - added email address and title to XML configuration
37
+
38
+ 0.4.0
39
+ -----
40
+ - Added sending mail
@@ -0,0 +1,7 @@
1
+ CHANGELOG
2
+ Manifest.txt
3
+ README
4
+ Rakefile
5
+ bin/gcalevents
6
+ lib/calendarchecker.rb
7
+ lib/calendars.rb
data/README ADDED
@@ -0,0 +1,40 @@
1
+ = GCalEvents
2
+
3
+ Read events from your Google Calendars and put it on console or sends to GMail.
4
+ Allow configuration of different 'look forward' time for different calendars.
5
+
6
+ == Instalation
7
+ Please use ruby gems:
8
+ % gem install --remote gcalevents+.
9
+
10
+ === Configuration
11
+ Configuration is stored in XML file at: $HOME/.gcalendar.xml.
12
+
13
+ ==== Sample configuration file
14
+ <?xml version="1.0" encoding="UTF-8"?>
15
+ <config>
16
+ <username>username@gmail.com</username> <!-- Google Account username -->
17
+ <password>y0uRpAsSw04d</password> <!-- Google Account password -->
18
+ <days>0</days> <!-- How many days in the future to read -->
19
+ <email_to>my@email.address</email_to> <!--Optional. Email address to send notifications. Default: username.-->
20
+ <email_to>my_friend@email.address</email_to> <!--Optional. There can be many email addresses.-->
21
+ <email_subject>MySubject</email_subject> <!--Optional. Default: "Google Calendar Events".-->
22
+ <banner>Upcoming events</banner> <!--Optional. Displayed before events. Default: "-=Events on Google Calendar=-". -->
23
+ <calendars> <!--Optional. By default read all calendars for days specified in this XML. -->
24
+ <title forward="7">Realy important calendar</title>
25
+ <title forward="3">Birdthday</title>
26
+ <title forward="false" regexp="true">^Not really that important</title>
27
+ </calendars>
28
+ </config>
29
+ == Usage
30
+ When configured properly just run:
31
+ % gcalevents
32
+ After some time events will show off.
33
+
34
+ Read help for parameters:
35
+ % gcalevents -h
36
+
37
+ == Author
38
+ Roman 'MrStone' Kamyk (mailto:rkj@go2.pl),
39
+ Student of Poznan University Of Technology, Computing Science Institute.
40
+
@@ -0,0 +1,22 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/calendarchecker.rb'
6
+
7
+ Hoe.new('gcalevents', PROGVERSION) do |p|
8
+ p.rubyforge_name = 'gcalevents'
9
+ p.author = "Roman Kamyk"
10
+ p.email = 'roman.kamyk@gmail.com'
11
+ p.summary = 'Reads Google Calendar and prints events'
12
+ p.url = "http://gcalevents.rubyforge.org"
13
+ p.extra_deps = ["rake", "gcalapi", "xml-simple", "gmailer"]
14
+ @changes = p.changes = p.paragraphs_of('CHANGELOG', 0..1).join("\n\n")
15
+ end
16
+
17
+ task :publish => [:release, :post_news, :publish_docs] do
18
+ sh "svn ci -m '#{@changes}'"
19
+ sh "hg ci -m '#{@changes}'"
20
+ end
21
+
22
+ # vim: syntax=Ruby
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/ruby
2
+
3
+ begin
4
+ require 'calendarchecker.rb'
5
+ rescue LoadError
6
+ require 'rubygems'
7
+ require 'calendarchecker.rb'
8
+ end
9
+ GCalendarChecker.new.putEvents
10
+
@@ -0,0 +1,249 @@
1
+ #!/usr/bin/ruby
2
+ # See README
3
+ require 'rubygems'
4
+ require "googlecalendar/calendar"
5
+ require 'xmlsimple'
6
+ require 'optparse'
7
+ require 'calendars'
8
+ require 'gmailer'
9
+ require 'pp'
10
+
11
+ PROGNAME = "GCalEvents"
12
+ PROGVERSION = "0.4.10"
13
+
14
+ # Big, bad main class serving everything.
15
+ class GCalendarChecker
16
+ # read configuration from XML file.
17
+ def readConfig
18
+ xml = XmlSimple.xml_in(File.new("#{ENV['HOME'] || ENV['USERPROFILE']}/.gcalendar.xml"), "ForceArray"=>["title"])
19
+ @options[:username] = xml["username"]
20
+ @options[:password] = xml["password"]
21
+ @server = GoogleCalendar::Service.new(@options[:username], @options[:password])
22
+ @calendars = Calendars.new(xml["calendars"]);
23
+ @options[:forward] = xml["days"].to_i
24
+ @options[:email_to] = xml["email_to"] || @options[:username]
25
+ @options[:email_subject] = xml["email_subject"] || "Google Calendar Events"
26
+ @options[:banner] = xml["banner"] || "-=Events on Google Calendar=-"
27
+ @options[:desc_len] = xml["description_length"].to_i || -1
28
+ if $DEBUG
29
+ puts @options.inspect
30
+ puts @options[:email_to].class
31
+ @options[:email_to].each { |to|
32
+ puts "sendmail(msg, #{to})"
33
+ }
34
+ end
35
+ end
36
+
37
+ # Parses arguments from commandline
38
+ def parseOptions
39
+ OptionParser.new do |opts|
40
+ opts.banner = "Usage: #{$0} [options]"
41
+ opts.program_name = PROGNAME
42
+ opts.on("-d", "--days N", Integer, "Read events N days in the future") do |n|
43
+ @options[:forward] = n;
44
+ end
45
+ opts.on("-f", "--from-date Date", "Read events starting from Date") do |fromdate|
46
+ @options[:fromdate] = Time.parse(fromdate)
47
+ end
48
+ opts.on("-t", "--to-date Date", "Read events until Date. (Unless longer period specified by --date or in config file)") do |todate|
49
+ @options[:todate] = Time.parse(todate)
50
+ end
51
+ opts.on("-m", "--match-only Name", "Read events only from calendar Name") do |n|
52
+ @options[:match_only] = Regexp.new(n, true)
53
+ end
54
+ opts.on("-s", "--send-mail", "Send email with event to you google account") { @options[:send_mail] = true }
55
+ opts.on("-n", "--no-output", "Do not print anything to stdout") { @options[:no_output] = true }
56
+ opts.on("-e", "--encrypt", "Encrypt mail") { @options[:encrypt] = true }
57
+ opts.on("-i", "--sign", "Sign mail") { @options[:sign] = true }
58
+ opts.on_tail("-v", "--version", "Show version") do
59
+ puts "#{PROGNAME}, version #{PROGVERSION}"
60
+ exit
61
+ end
62
+ opts.on_tail("-h", "--help", "Show this message") do
63
+ puts opts
64
+ exit
65
+ end
66
+ end.parse!
67
+ @options
68
+ end
69
+
70
+ def initialize
71
+ @options = {}
72
+ begin
73
+ readConfig
74
+ rescue => e
75
+ puts "Error during parsing configuration: #{e}!"
76
+ puts e.backtrace
77
+ exit
78
+ end
79
+ begin
80
+ parseOptions
81
+ rescue => e
82
+ puts "Error during parsing options: #{e}!"
83
+ exit
84
+ end
85
+ if @options[:fromdate]
86
+ @startTime = @options[:fromdate]
87
+ else
88
+ @startTime = Time.now
89
+ end
90
+ if @options[:todate]
91
+ @endTime = @options[:todate]
92
+ else
93
+ @endTime = Time.local(@startTime.year, @startTime.month, @startTime.day, 23, 59, 59, 99)
94
+ end
95
+ end
96
+
97
+ def isToday(time)
98
+ now = Time.now
99
+ time.day == now.day and now+3600*24 > time
100
+ end
101
+
102
+ def isNextWeek(time)
103
+ nextWeek = Time.now+3600*24*6
104
+ time > Time.now and Time.local(nextWeek.year, nextWeek.month, nextWeek.day, 23, 59, 59, 99) > time
105
+ end
106
+
107
+ def isThisMonth(time)
108
+ now = Time.now
109
+ time.month == now.month
110
+ end
111
+
112
+ def isThisYear(time)
113
+ now = Time.now
114
+ time.year == now.year
115
+ end
116
+
117
+ def sameDay(t1, t2)
118
+ t2 -= 1 # So XXXX-YY-01 00:00 and XXXX-YY-02 00:00 be same days ;)
119
+ t1.day == t2.day and t1.month == t2.month and t1.year == t2.year
120
+ end
121
+
122
+ # Translates start and end time into a nice string.
123
+ def formatEventTime(time, endTime)
124
+ unless endTime.nil? or sameDay(time, endTime)
125
+ return "from #{formatTime(time)} to #{formatTime(endTime)}"
126
+ else
127
+ return "#{formatTime(time)}"
128
+ end
129
+ end
130
+
131
+ # Translates time into a string depending on how much in the future
132
+ # it is.
133
+ # It is:
134
+ # - "today",
135
+ # - "this weekday", if it is in one week,
136
+ # - "weekday monthday", if it is in this month,
137
+ # - "weekday monthday yearday", if it is this year,
138
+ # - "weekday isodate", else
139
+ def formatTime(time)
140
+ return "today" if isToday(time)
141
+ return "#{time.strftime("%a")}" if isNextWeek(time)
142
+ return "#{time.strftime("%a %d")}" if isThisMonth(time)
143
+ return "#{time.strftime("%a %d %b")}" if isThisYear(time)
144
+ return "#{time.strftime("%a %Y-%m-%d")}"
145
+ end
146
+
147
+ def shortDesc(desc)
148
+ noLB = desc.gsub(/\s+/, " ")
149
+ return noLB unless noLB.length > @options[:desc_len]
150
+ return noLB[0..@options[:desc_len]] + "..."
151
+ end
152
+
153
+ # Translates event into nice string, containing:
154
+ # - Title
155
+ # - Desciption
156
+ # - Location
157
+ # - Start and end time
158
+ def eventToString(event)
159
+ string = ""
160
+ est = event.st.localtime unless event.st.nil?
161
+ een = event.en.localtime unless event.en.nil?
162
+ unless est.nil?
163
+ string << "#{formatEventTime(est, een)}"
164
+ time = " #{est.strftime("%H:%M")}"
165
+ time << "-#{event.en.localtime.strftime("%H:%M")}"
166
+ string << time unless time == " 00:00-00:00"
167
+ end
168
+ string << "|#{event.title}"
169
+ string << " (#{shortDesc(event.desc)})" unless event.desc.nil? or event.desc.empty?
170
+ string << " @ #{event.where}" unless event.where.nil? or event.where.empty?
171
+ string
172
+ end
173
+
174
+ # Sends email containg body to *to* person using Google account from XML configuration.
175
+ def sendmail(body, receiver)
176
+ if @options[:encrypt]
177
+ body = `echo '#{body}' | gpg --armor -ser '#{receiver}'`
178
+ elsif @options[:sign]
179
+ body = `echo '#{body}' | gpg --clearsign -r '#{receiver}'`
180
+ end
181
+ GMailer.connect(@options[:username], @options[:password]) do |g|
182
+ g.send(
183
+ :to => receiver,
184
+ :subject => @options[:email_subject],
185
+ :body => body
186
+ )
187
+ end
188
+ end
189
+
190
+ def max(a, b)
191
+ return a if a>b
192
+ return b
193
+ end
194
+
195
+ def collectEvents(cal, startTime, endTime)
196
+ cal.events({"start-min"=>startTime, "start-max"=>endTime, "orderby"=>"starttime"}).collect { |event|
197
+ {:cal=>cal, :event=>event} unless event.st.nil?
198
+ }
199
+ end
200
+
201
+ # Reads events from Google Calendars
202
+ def getEvents
203
+ events = []
204
+ if $DEBUG
205
+ puts @server
206
+ puts GoogleCalendar::Calendar.calendars(@server)
207
+ end
208
+ GoogleCalendar::Calendar.calendars(@server).each { |feed, cal|
209
+ next unless @calendars.display?(cal.title)
210
+ next if @options[:match_only] and !(cal.title =~ @options[:match_only])
211
+ forward = max(@calendars.forward(cal.title), @options[:forward])
212
+ items = collectEvents(cal, @startTime, @endTime+24*3600*forward)
213
+ if $DEBUG
214
+ puts items
215
+ end
216
+ events += items.reject { |a| a.nil?} unless items.nil?
217
+ }
218
+ events
219
+ end
220
+
221
+ # Main method that puts all events on console and send email if apropriate.
222
+ def putEvents
223
+ begin
224
+ events = getEvents.sort{|a, b|
225
+ a[:event].st <=> b[:event].st
226
+ }
227
+ msg = "#{@options[:banner]}\n"
228
+ events.each { |event|
229
+ msg += "#{event[:cal].title}|#{eventToString(event[:event])}\n"
230
+ }
231
+ rescue => e
232
+ puts "Error during reading GCalendar - #{e}"
233
+ puts e.backtrace
234
+ exit
235
+ end
236
+ if @options[:send_mail]
237
+ @options[:email_to].each { |to|
238
+ sendmail(msg, to)
239
+ }
240
+ end
241
+ unless @options[:no_output]
242
+ puts msg
243
+ end
244
+ end
245
+ end
246
+
247
+ if $0 == __FILE__
248
+ GCalendarChecker.new.putEvents
249
+ end
@@ -0,0 +1,60 @@
1
+ # Remembers calendar meta data from xml configuration.
2
+ class Calendar
3
+ def initialize(calendar)
4
+ @regexp = false;
5
+ @display = true;
6
+ @forward = 0;
7
+ if calendar["forward"] == "false"
8
+ @display = false
9
+ else
10
+ @forward = calendar["forward"].to_i
11
+ end
12
+ @regexp = true if calendar["regexp"] == "true"
13
+ @title = calendar["content"]
14
+ if $DEBUG
15
+ puts calendar.inspect
16
+ puts "D: #{@display}, RE: #{@regexp}\n*******"
17
+ end
18
+ end
19
+
20
+ # Checks if title match this calendar.
21
+ def match?(title)
22
+ if @regexp
23
+ return title =~ /#{@title}/
24
+ else
25
+ return title == @title
26
+ end
27
+ end
28
+
29
+ attr_reader :forward, :display
30
+ end
31
+
32
+ # Container for calendars read from configuration.
33
+ class Calendars
34
+ def initialize(calendars)
35
+ @calendars = [];
36
+ return if calendars.nil?
37
+ calendars["title"].each { |cal|
38
+ @calendars << Calendar.new(cal)
39
+ }
40
+ end
41
+
42
+ # Checks if any calendar match title.
43
+ def display?(title)
44
+ cal = @calendars.find { |cal|
45
+ cal.match?(title)
46
+ }
47
+ return cal.display unless cal.nil?
48
+ return true;
49
+ end
50
+
51
+ # Returns how many days in the future calendar should be chcecked.
52
+ def forward(title)
53
+ cal = @calendars.find { |cal|
54
+ cal.match?(title)
55
+ }
56
+ return cal.forward unless cal.nil?
57
+ return 0;
58
+ end
59
+ end
60
+
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
4
+ name: gcalevents
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.4.10
7
+ date: 2007-11-13 00:00:00 +01:00
8
+ summary: Reads Google Calendar and prints events
9
+ require_paths:
10
+ - lib
11
+ email: roman.kamyk@gmail.com
12
+ homepage: http://gcalevents.rubyforge.org
13
+ rubyforge_project: gcalevents
14
+ description: The author was too lazy to write a description
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ - |
29
+ -----BEGIN CERTIFICATE-----
30
+ MIIDODCCAiCgAwIBAgIBADANBgkqhkiG9w0BAQUFADBCMRQwEgYDVQQDDAtyb21h
31
+ bi5rYW15azEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYD
32
+ Y29tMB4XDTA3MTExMDA1MzUzM1oXDTA4MTEwOTA1MzUzM1owQjEUMBIGA1UEAwwL
33
+ cm9tYW4ua2FteWsxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixk
34
+ ARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMdV1ujoU4I2
35
+ daF4KANtDPTSjLYhXC1CiiyEgGEVA6GvieQ2NpNNsSXl+6tbWXGNUWFHj50rrLTC
36
+ e1dJSGGTZa9ZjI6fkeb/Gr13s71ncCJ+hBbpvktWIWdvOvzvNo9bdzNCKX00Rlk5
37
+ hQzxhm/ZxQ2VG4ZDYc/gWOCzKYH8aKrAzzdjRsxE/QMgnVbnirCGSPQTjPVhBvcX
38
+ pH2yDvZF9NOs3D89JvA4P50WRCe8/kKPx7TG9Qkd303/FmO8yDUvJn0KgiYkm1pc
39
+ Sb+kcDZnh2+2uvkygLLDQhV5m7DfFLLkgwb/t7R4tSNFqcHoa0829rnSVBbCZACg
40
+ mrXhThP3LX8CAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0O
41
+ BBYEFGVgSLBvjD5kTd+1XMf58PK9llj6MA0GCSqGSIb3DQEBBQUAA4IBAQCGX43w
42
+ PspP+rmsfCKztiUwtfb4d+eqW62WaAUBT37KeW8IEm3UpAe5T1c3fFm46bxM3a2Y
43
+ wUeLqSMSquXNzb2fy+3vLAUYHc4UkR5nA5kB+F3RJwuc7LJCBGlkPsCfa91dE6j5
44
+ S80vqeRf4ITITHZbFLuVFFvQb/nPGe2LtyP4+neAktSu4r7rQ5vLbQQ/NSAliFrP
45
+ pJbWXmfjKQsDKGgs1TiISC3kfLcynhCgCcbLCek5Oc0U195z36e8x3aYEJSGFVmF
46
+ y8xfBxyZ4t0FP3lTPvGMfmSKOVOjcwT4OVpzdvRXWR8lghrQlAzNG5HdOxMzeBjb
47
+ Z2byiG0rlbybmXMS
48
+ -----END CERTIFICATE-----
49
+
50
+ post_install_message:
51
+ authors:
52
+ - Roman Kamyk
53
+ files:
54
+ - CHANGELOG
55
+ - Manifest.txt
56
+ - README
57
+ - Rakefile
58
+ - bin/gcalevents
59
+ - lib/calendarchecker.rb
60
+ - lib/calendars.rb
61
+ test_files: []
62
+
63
+ rdoc_options:
64
+ - --main
65
+ - README.txt
66
+ extra_rdoc_files:
67
+ - Manifest.txt
68
+ executables:
69
+ - gcalevents
70
+ extensions: []
71
+
72
+ requirements: []
73
+
74
+ dependencies:
75
+ - !ruby/object:Gem::Dependency
76
+ name: rake
77
+ version_requirement:
78
+ version_requirements: !ruby/object:Gem::Version::Requirement
79
+ requirements:
80
+ - - ">"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.0.0
83
+ version:
84
+ - !ruby/object:Gem::Dependency
85
+ name: gcalapi
86
+ version_requirement:
87
+ version_requirements: !ruby/object:Gem::Version::Requirement
88
+ requirements:
89
+ - - ">"
90
+ - !ruby/object:Gem::Version
91
+ version: 0.0.0
92
+ version:
93
+ - !ruby/object:Gem::Dependency
94
+ name: xml-simple
95
+ version_requirement:
96
+ version_requirements: !ruby/object:Gem::Version::Requirement
97
+ requirements:
98
+ - - ">"
99
+ - !ruby/object:Gem::Version
100
+ version: 0.0.0
101
+ version:
102
+ - !ruby/object:Gem::Dependency
103
+ name: gmailer
104
+ version_requirement:
105
+ version_requirements: !ruby/object:Gem::Version::Requirement
106
+ requirements:
107
+ - - ">"
108
+ - !ruby/object:Gem::Version
109
+ version: 0.0.0
110
+ version:
111
+ - !ruby/object:Gem::Dependency
112
+ name: hoe
113
+ version_requirement:
114
+ version_requirements: !ruby/object:Gem::Version::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: 1.3.0
119
+ version:
@@ -0,0 +1,2 @@
1
+ ��v��<��D~������\��'/�˭G_,~�� $����ɽ%[7�'�bi}����^ǣ�\�t��c��k�~pK暉�5��<\%��Nu�)�sQ����Sd�T�?�.H�Bȧ"����qvw]�.�fv�Q��Ws�H�9�k�� �\S e��|��o�2��������$O*a#�5��%�kǠ�{j�d(
2
+ ~��u-�"A�[�"q6����ȿ�J�W� ����F;�,^�1bpu�>�����Y