reagent-dockit 0.1 → 0.1.1

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/README CHANGED
@@ -28,10 +28,14 @@ default:
28
28
  password: password
29
29
  remote_uri: http://mail.example.com/exchange/john.doe@example.com/
30
30
  local_port: 2000
31
+ timezone: US/Eastern
31
32
 
32
33
  The resulting url for subscribing in iCal when running this daemon on the localhost would be:
33
34
  http://localhost:2000/john.doe.ics
34
35
 
36
+ Timezones are include US/ Eastern,Pacific,Mountain or any other standard format.
37
+ See iCal's options for timezones for a complete listing.
38
+
35
39
  Starting the Daemon
36
40
  -----------------
37
41
  Given the yaml file defined example, the command would be:
data/Rakefile CHANGED
@@ -1,10 +1,18 @@
1
1
  require 'rubygems'
2
2
  require 'rake/gempackagetask'
3
+ require 'spec/rake/spectask'
3
4
 
5
+ desc "build the gem"
4
6
  task :gem do
5
7
  system('gem build dockit.gemspec')
6
8
  end
7
9
 
8
10
  task :install => [:package] do
9
11
  sh %{sudo gem install pkg/#{GEM}-#{VERSION}}
10
- end
12
+ end
13
+
14
+ Spec::Rake::SpecTask.new do |t|
15
+ t.spec_files = FileList['spec/**/*_spec.rb']
16
+ end
17
+
18
+ task :default => :spec
@@ -1,42 +1,35 @@
1
1
  require 'rubygems'
2
2
  require 'rack'
3
3
  require 'yaml'
4
+ require 'activesupport'
4
5
 
5
6
  require "export"
6
-
7
- class String
8
- def blank?
9
- self.nil? || self.strip.empty?
10
- end
11
- end
12
-
13
- class NilClass
14
- def blank?
15
- true
16
- end
17
- end
7
+ require "user"
18
8
 
19
9
  class Dockit
20
10
  include Export
21
11
 
12
+ attr_accessor :user, :pid
13
+
22
14
  def initialize(config)
23
15
  # Get configuration information
24
16
  config_file = YAML.load_file(File.join(ENV['HOME'], ".dockit"))
25
- @user = config_file && config_file.has_key?(config) ?
17
+
18
+ user_config = config_file && config_file.has_key?(config) ?
26
19
  config_file[config] : config_file['default']
27
20
 
28
- raise "No users.yml found for user #{ARGV.first}!" unless @user
21
+ raise "No .dockit file found with user section: #{config}!" unless user_config
22
+
23
+ @user = User.new(user_config)
29
24
  end
30
25
 
31
26
  def run
32
- local_port = @user.fetch("local_port", 2000)
33
-
34
- pid = fork do
35
- Rack::Handler::Mongrel.run(rack_process(@user), :Port => local_port)
27
+ @pid = fork do
28
+ Rack::Handler::Mongrel.run(rack_process(@user), :Port => @user.local_port)
36
29
  end
37
30
 
38
- Process.detach(pid)
31
+ Process.detach(@pid)
39
32
 
40
- puts "Use sudo kill #{pid} to stop this process."
33
+ puts "Use sudo kill #{@pid} to stop this process."
41
34
  end
42
35
  end
@@ -0,0 +1,23 @@
1
+ require 'rexchange'
2
+
3
+ class Event
4
+
5
+ @@configuration = nil
6
+
7
+ def self.configuration=(configuration)
8
+ @@configuration = configuration
9
+ end
10
+
11
+ def self.all
12
+ endpoint = "#{@@configuration[:url]}/#{@@configuration[:email]}"
13
+ events = []
14
+
15
+ RExchange.open(endpoint, @@configuration[:email], @@configuration[:password]) do |mailbox|
16
+ mailbox.calendar.each do |appointment|
17
+ events << Event.new(appointment)
18
+ end
19
+ end
20
+ events
21
+ end
22
+
23
+ end
@@ -0,0 +1,22 @@
1
+ require 'event_collection'
2
+
3
+ class Event
4
+ def initialize(event)
5
+ @event = event
6
+ end
7
+
8
+ def dformat(t)
9
+ t.strftime('%Y%m%dT%H%M%S')
10
+ end
11
+
12
+ def method_missing(methodname, *args)
13
+ @event.send(methodname, *args)
14
+ end
15
+
16
+ def to_ics
17
+ filename = File.join(File.dirname(__FILE__), "templates", "event.ics.erb")
18
+ file = IO.read(filename)
19
+
20
+ ERB.new(file).result(binding)
21
+ end
22
+ end
@@ -0,0 +1,38 @@
1
+ require 'rexchange'
2
+
3
+ class EventCollection
4
+ def initialize
5
+ @collection = []
6
+ end
7
+
8
+ def size
9
+ @collection.size
10
+ end
11
+
12
+ def <<(event)
13
+ @collection << event if event
14
+ end
15
+
16
+ def to_ics
17
+ filename = File.join(File.dirname(__FILE__), "templates", "event_collection.ics.erb")
18
+ file = IO.read(filename)
19
+ ERB.new(file).inspect
20
+ end
21
+
22
+ def self.user=(user)
23
+ @user = user ? user : @user || User.new({})
24
+ end
25
+
26
+ def self.user
27
+ @user ||= User.new({})
28
+ end
29
+
30
+ def self.all(&block)
31
+ self.user=(nil) unless @user
32
+ RExchange.open(@user.remote_uri, @user.email, @user.password) do |mailbox|
33
+ mailbox.calendar.each do |event|
34
+ @collection << Event.new(event)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,5 +1,4 @@
1
- require 'rexchange'
2
- require 'chronic'
1
+ require 'event_collection'
3
2
 
4
3
  module Export
5
4
  def rack_process(user)
@@ -12,93 +11,85 @@ module Export
12
11
  end
13
12
 
14
13
  def exchange(user)
15
- username = user.fetch("username", ENV['USER'])
16
- domain = user.fetch("domain", 'localhost')
17
- email = "#{username}@#{domain}"
18
- password = user.fetch("password", 'password')
19
- remote_uri = user.fetch("remote_uri", "http://localhost/#{email}/")
14
+ file = File.new("#{user.username}.ics", "w")
15
+ raise "Failed to create file #{user.username}.ics" unless file
20
16
 
21
- # puts "User: #{username}@#{domain}, #{password}, #{remote_uri}"
22
-
23
- RExchange::open(remote_uri, email, password) do |mailbox|
24
-
25
- # create ics file, clearing any old one
26
- file = File.new("#{username}.ics", "w")
27
- raise "Failed to create file #{username}.ics" unless file
28
-
29
- file.puts "BEGIN:VCALENDAR"
30
- file.puts "CALSCALE:GREGORIAN"
31
- file.puts "PRODID:-//Apple Computer\, Inc//iCal 2.0//EN"
32
- file.puts "VERSION:2.0"
33
- file.puts "X-WR-CALNAME:#{username}"
34
-
35
- # itemcount = 0
36
-
37
- # Loop through all calendar events, making VEVENTS
38
- mailbox.calendar.each do |event|
39
-
40
- file.puts "BEGIN:VEVENT"
41
-
42
- # Set some properties for this event
43
- file.puts "DTSTAMP:#{dformat(event.created_at)}"
44
- file.puts "DTSTART:#{dformat(event.start_at)}"
45
- file.puts "DTEND:#{dformat(event.end_at)}"
46
- file.puts "LAST-MODIFIED:#{dformat(event.modified_at)}"
47
-
48
- file.puts "SUMMARY:" + (event.subject.blank? ? "Unknown Subject" : event.subject)
49
-
50
- description = event.body.blank? ? "" : event.body.gsub!("\n","\\n").gsub("^\n","")
51
- # ?? add event.href+"?Cmd=accept" or "decline" or "tentative"
52
- # description += event.href+"?Cmd=accept"
53
- # description += event.href+"?Cmd=decline"
54
- # description += event.href+"?Cmd=tentative"
55
-
56
- file.puts "DESCRIPTION:" + description
57
-
58
- file.puts "UID:" + event.uid if event.uid
59
-
60
- if event.reminder_offset && event.reminder_offset.to_i > 60
61
- # ouput valarm details. reminder_offset is in seconds
62
- ro_min = event.reminder_offset.to_i / 60
63
- file.puts "BEGIN:VALARM"
64
- file.puts "TRIGGER:-PT#{ro_min}M"
65
- # item.puts "DESCRIPTION:Påminnelse om aktivitet"
66
- file.puts "ACTION:DISPLAY"
67
- file.puts "END:VALARM"
68
- end
69
-
70
- #add event to calendar
71
- file.puts "END:VEVENT"
72
-
73
- # itemcount += 1
74
- end
75
-
76
- # puts mailbox.inspect
77
- # puts
78
- # puts mailbox.methods
79
-
80
- # Loop through all todos, creating VTODOS
81
- # Loop through all journals, creating VJOURNAL
82
- # Loop through all free/busy time, creating VFREEBUSY
83
- # event.busy_status
84
-
85
- #close ical file
86
- file.puts "END:VCALENDAR"
87
- file.close
88
-
89
- # p "Done! Wrote #{itemcount} appointment items"
90
-
91
- end
17
+ EventCollection.user = user
18
+ file.puts(EventCollection.all.to_ics)
19
+ file.close
20
+
21
+ # RExchange::open(user.remote_uri, user.email, user.password) do |mailbox|
22
+ #
23
+ # # create ics file, clearing any old one
24
+ # file = File.new("#{user.username}.ics", "w")
25
+ # raise "Failed to create file #{user.username}.ics" unless file
26
+ #
27
+ # file.puts "BEGIN:VCALENDAR"
28
+ # file.puts "CALSCALE:GREGORIAN"
29
+ # file.puts "PRODID:-//Apple Computer\, Inc//iCal 2.0//EN"
30
+ # file.puts "VERSION:2.0"
31
+ # file.puts "X-WR-CALNAME:#{user.title}"
32
+ #
33
+ # # itemcount = 0
34
+ #
35
+ # # Loop through all calendar events, making VEVENTS
36
+ # mailbox.calendar.each do |event|
37
+ #
38
+ # file.puts "BEGIN:VEVENT"
39
+ #
40
+ # # Set some properties for this event
41
+ # file.puts "DTSTAMP;TZID=#{user.timezone}:#{dformat(event.created_at)}"
42
+ # file.puts "DTSTART;TZID=#{user.timezone}:#{dformat(event.start_at)}"
43
+ # file.puts "DTEND;TZID=#{user.timezone}:#{dformat(event.end_at)}"
44
+ # file.puts "LAST-MODIFIED;TZID=#{user.timezone}:#{dformat(event.modified_at)}"
45
+ #
46
+ # file.puts "SUMMARY:" + (event.subject.blank? ? "Unknown Subject" : event.subject)
47
+ #
48
+ # description = event.body.blank? ? "" : event.body.gsub!("\n","\\n").gsub("^\n","")
49
+ # # ?? add event.href+"?Cmd=accept" or "decline" or "tentative"
50
+ # # description += event.href+"?Cmd=accept"
51
+ # # description += event.href+"?Cmd=decline"
52
+ # # description += event.href+"?Cmd=tentative"
53
+ #
54
+ # file.puts "DESCRIPTION:" + description
55
+ #
56
+ # file.puts "UID:" + event.uid if event.uid
57
+ #
58
+ # if event.reminder_offset && event.reminder_offset.to_i > 60
59
+ # # ouput valarm details. reminder_offset is in seconds
60
+ # ro_min = event.reminder_offset.to_i / 60
61
+ # file.puts "BEGIN:VALARM"
62
+ # file.puts "TRIGGER:-PT#{ro_min}M"
63
+ # # item.puts "DESCRIPTION:Påminnelse om aktivitet"
64
+ # file.puts "ACTION:DISPLAY"
65
+ # file.puts "END:VALARM"
66
+ # end
67
+ #
68
+ # #add event to calendar
69
+ # file.puts "END:VEVENT"
70
+ #
71
+ # # itemcount += 1
72
+ # end
73
+ #
74
+ # # puts mailbox.inspect
75
+ # # puts
76
+ # # puts mailbox.methods
77
+ #
78
+ # # Loop through all todos, creating VTODOS
79
+ # # Loop through all journals, creating VJOURNAL
80
+ # # Loop through all free/busy time, creating VFREEBUSY
81
+ # # event.busy_status
82
+ #
83
+ # #close ical file
84
+ # file.puts "END:VCALENDAR"
85
+ # file.close
86
+ #
87
+ # # p "Done! Wrote #{itemcount} appointment items"
88
+ #
89
+ # end
92
90
  end
93
91
 
94
92
  def dformat(t)
95
- # month = s[4..6]
96
- # day = s[8..9].to_i
97
- # hour = s[11..12].to_i
98
- # minute = s[14..15].to_i
99
- # second = s[17..18].to_i
100
- # year = s[23..27].to_i
101
- # Time.local(year, month, day, hour, minute, second).strftime('%Y%m%dT%H%M%S')
102
93
  t.strftime('%Y%m%dT%H%M%S')
103
94
  end
104
95
  end
@@ -0,0 +1,21 @@
1
+ BEGIN:VEVENT
2
+ DTSTAMP;TZID=<%= EventCollection.user.timezone %>:<%= dformat(@event.created_at) %>
3
+ DTSTART;TZID=<%= EventCollection.user.timezone %>:<%= dformat(@event.start_at) %>
4
+ DTEND;TZID=<%= EventCollection.user.timezone %>:<%= dformat(@event.end_at) %>
5
+ LAST-MODIFIED;TZID=<%= EventCollection.user.timezone %>:<%= dformat(@event.modified_at) %>
6
+
7
+ SUMMARY:<%= (@event.subject.blank? ? "Unknown Subject" : @event.subject) %>
8
+ <% description = @event.body.blank? ? "" : @event.body.gsub("\n","\\n").gsub("^\n","") %>
9
+
10
+ DESCRIPTION: <%= description %>
11
+ UID:<%= @event.uid if @event.uid %>
12
+
13
+ <% if @event.reminder_offset && @event.reminder_offset.to_i > 60 %>
14
+ <% ro_min = @event.reminder_offset.to_i / 60 %>
15
+ BEGIN:VALARM
16
+ TRIGGER:-PT<%= ro_min %>M
17
+ ACTION:DISPLAY
18
+ END:VALARM
19
+ <% end %>
20
+
21
+ END:VEVENT
@@ -0,0 +1,11 @@
1
+ BEGIN:VCALENDAR
2
+ CALSCALE:GREGORIAN
3
+ PRODID:-//Apple Computer\, Inc//iCal 2.0//EN
4
+ VERSION:2.0
5
+ X-WR-CALNAME:<%= @user.title %>
6
+
7
+ <% for event in @collection do %>
8
+ <% event.to_ics %>
9
+ <% end %>
10
+
11
+ END:VCALENDAR
@@ -0,0 +1,35 @@
1
+ class User
2
+ attr_accessor :username,
3
+ :domain,
4
+ :email,
5
+ :password,
6
+ :timezone,
7
+ :remote_uri,
8
+ :local_port,
9
+ :title
10
+
11
+ def initialize(config)
12
+ config.symbolize_keys!
13
+
14
+ self.username = config.fetch(:username, ENV['USER'])
15
+ self.domain = config.fetch(:domain, 'localhost')
16
+ self.email = "#{self.username}"
17
+ self.email << "@#{self.domain}" unless self.domain.blank?
18
+ self.password = config.fetch(:password, "password")
19
+ self.timezone = config.fetch(:timezone, "US/Eastern")
20
+ self.remote_uri = config.fetch(:remote_uri, "http://localhost/#{self.email}/")
21
+ self.local_port = config.fetch(:local_port, 2000)
22
+ self.title = config.fetch(:title, self.username)
23
+ end
24
+
25
+ def to_hash
26
+ {:username => self.username,
27
+ :domain => self.domain,
28
+ :email => self.email,
29
+ :password => self.password,
30
+ :timezone => self.timezone,
31
+ :remote_uri => self.remote_uri,
32
+ :local_port => self.local_port,
33
+ :title => self.title}
34
+ end
35
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reagent-dockit
3
3
  version: !ruby/object:Gem::Version
4
- version: "0.1"
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Pitale @ Viget Labs
@@ -31,13 +31,22 @@ dependencies:
31
31
  version: 0.3.0
32
32
  version:
33
33
  - !ruby/object:Gem::Dependency
34
- name: chronic
34
+ name: activesupport
35
35
  version_requirement:
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 0.2.3
40
+ version: "0"
41
+ version:
42
+ - !ruby/object:Gem::Dependency
43
+ name: erb
44
+ version_requirement:
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
41
50
  version:
42
51
  description: A rack application daemon that creates an iCal subscription file from exchange calendars.
43
52
  email: tony.pitale@viget.com
@@ -57,6 +66,14 @@ files:
57
66
  - Manifest
58
67
  - lib/dockit.rb
59
68
  - lib/export.rb
69
+ - lib/dockit
70
+ - lib/dockit/event.rb
71
+ - lib/event_collection.rb
72
+ - lib/event.rb
73
+ - lib/user.rb
74
+ - lib/templates
75
+ - lib/templates/event_collection.ics.erb
76
+ - lib/templates/event.ics.erb
60
77
  has_rdoc: false
61
78
  homepage: http://www.viget.com/extend/
62
79
  post_install_message: