reagent-dockit 0.1 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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: