siri_cal 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +155 -0
  3. data/Rakefile +37 -0
  4. data/lib/generators/install.rb +16 -0
  5. data/lib/generators/templates/siri_cal.rb +13 -0
  6. data/lib/generators/templates/siri_says/default.rb +3 -0
  7. data/lib/siri_cal.rb +41 -0
  8. data/lib/siri_cal/methods.rb +49 -0
  9. data/lib/siri_cal/say_proxy.rb +63 -0
  10. data/lib/siri_cal/version.rb +3 -0
  11. data/lib/tasks/siri_cal_tasks.rake +4 -0
  12. data/test/dummy/Rakefile +7 -0
  13. data/test/dummy/app/assets/javascripts/application.js +9 -0
  14. data/test/dummy/app/assets/stylesheets/application.css +7 -0
  15. data/test/dummy/app/controllers/application_controller.rb +3 -0
  16. data/test/dummy/app/helpers/application_helper.rb +2 -0
  17. data/test/dummy/app/models/movie.rb +2 -0
  18. data/test/dummy/app/models/user.rb +4 -0
  19. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  20. data/test/dummy/config.ru +4 -0
  21. data/test/dummy/config/application.rb +45 -0
  22. data/test/dummy/config/boot.rb +10 -0
  23. data/test/dummy/config/database.yml +25 -0
  24. data/test/dummy/config/environment.rb +5 -0
  25. data/test/dummy/config/environments/development.rb +30 -0
  26. data/test/dummy/config/environments/production.rb +60 -0
  27. data/test/dummy/config/environments/test.rb +42 -0
  28. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  29. data/test/dummy/config/initializers/inflections.rb +10 -0
  30. data/test/dummy/config/initializers/mime_types.rb +5 -0
  31. data/test/dummy/config/initializers/secret_token.rb +7 -0
  32. data/test/dummy/config/initializers/session_store.rb +8 -0
  33. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  34. data/test/dummy/config/locales/en.yml +5 -0
  35. data/test/dummy/config/routes.rb +58 -0
  36. data/test/dummy/db/development.sqlite3 +0 -0
  37. data/test/dummy/db/migrate/20111105175135_create_users.rb +11 -0
  38. data/test/dummy/db/migrate/20111108194230_create_movies.rb +11 -0
  39. data/test/dummy/db/schema.rb +31 -0
  40. data/test/dummy/db/test.sqlite3 +0 -0
  41. data/test/dummy/lib/siri_says/default.rb +3 -0
  42. data/test/dummy/log/development.log +102 -0
  43. data/test/dummy/log/test.log +4932 -0
  44. data/test/dummy/public/404.html +26 -0
  45. data/test/dummy/public/422.html +26 -0
  46. data/test/dummy/public/500.html +26 -0
  47. data/test/dummy/public/favicon.ico +0 -0
  48. data/test/dummy/script/rails +6 -0
  49. data/test/dummy/test/fixtures/movies.yml +7 -0
  50. data/test/dummy/test/fixtures/users.yml +11 -0
  51. data/test/dummy/test/unit/movie_test.rb +7 -0
  52. data/test/dummy/test/unit/user_test.rb +7 -0
  53. data/test/fixtures/vcr_cassettes/invalid_credentials.yml +36 -0
  54. data/test/fixtures/vcr_cassettes/valid_credentials.yml +38 -0
  55. data/test/fixtures/vcr_cassettes/valid_credentials_with_events.yml +772 -0
  56. data/test/fixtures/vcr_cassettes/valid_credentials_with_events_to_delete.yml +948 -0
  57. data/test/generators/install_test.rb +13 -0
  58. data/test/siri_cal_test.rb +82 -0
  59. data/test/test_helper.rb +23 -0
  60. metadata +216 -0
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2011 BOUNMY Stephane
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,155 @@
1
+ SiriCal
2
+ =======
3
+
4
+ SiriCal is a simple limited solution to handle [iOS 5 Siri feature][s] in your Ruby app :
5
+
6
+ * provides Siri helpers to your ruby app by synchronizing google calendar events.
7
+ * an alternative limited solution before Apple release an API for Siri.
8
+ * relies on google_calendar gem : [google_calendar][gc].
9
+
10
+ This gem is much inspired by Tyson Tale's hack: [siri_says][ss].
11
+
12
+ Installation
13
+ ------------
14
+
15
+ #### Rails app
16
+
17
+ You can use the latest Rails 3 gem with the latest SiriCal gem:
18
+
19
+ In your gemfile
20
+
21
+ gem 'siri_cal'
22
+
23
+ or using rubygems
24
+
25
+ gem install siri_cal
26
+
27
+ After you install SiriCal, you need to run the generator:
28
+
29
+ rails generate siri_cal:install
30
+
31
+ The generator will install:
32
+
33
+ * an initializer which describes most SiriCal’s configuration options.
34
+ * a step file which describe siri sayings
35
+
36
+ #### iPhone
37
+
38
+ Add the calendar:
39
+
40
+ 1. Settings
41
+ 2. "Mail, Contacts, Calendars"
42
+ 3. "Add Account..."
43
+ 4. "Other"
44
+ 5. "Add CalDAV Account"
45
+ * Server: google.com
46
+ * Username: username@gmail.com
47
+ * Password: ___________
48
+ * Description: "sirical"
49
+ 6. "Next"
50
+
51
+ Choose the calendar as default so Siri will add events to it:
52
+
53
+ 1. Settings
54
+ 1. "Mail, Contacts, Calendars"
55
+ 2. "Default Calendar" --> sirical
56
+
57
+ Usage
58
+ -----
59
+
60
+ A model
61
+
62
+ class User < ActiveRecord::Base
63
+ siriable
64
+ has_many :movies
65
+ end
66
+
67
+
68
+ Be sure to have 2 fields containing your google calendar
69
+
70
+ * login (siriable_login here)
71
+ * password (siriable_password here)
72
+
73
+ db/schema.rb should look like:
74
+
75
+ create_table "users", :force => true do |t|
76
+ t.string "name"
77
+ t.string "siriable_login"
78
+ t.string "siriable_password"
79
+ t.datetime "created_at"
80
+ t.datetime "updated_at"
81
+ end
82
+
83
+ In lib/siri_says/default.rb
84
+
85
+ says /a movie (.+)/i do |movie_name|
86
+ puts "[Siri] Movie '#{movie_name}' scheduled by #{@object.name} at #{@event.start_time}"
87
+ end
88
+
89
+ * @object is the User instance "bob"
90
+ * @event is the Google::Event instance
91
+
92
+ Tell Siri:
93
+
94
+ "Schedule a movie transformers right now."
95
+
96
+ In your ruby code:
97
+
98
+ user = User.create :name => "bob", :siriable_login => "bob@gmail.com", :siriable_password => "bobibob"
99
+ user.execute_siri!
100
+
101
+ (seconds later)
102
+
103
+ [Siri] Movie 'transformers' scheduled by bob at 2010-11-08 12:20
104
+
105
+ Example of events
106
+ ------------------
107
+
108
+ From [Siri Says][ss] :
109
+
110
+ #### Immediate events
111
+
112
+ To create an immediate event, you can either create an event "now" or "all-day tomorrow":
113
+
114
+ * "Schedule a movie right now"
115
+ * "Schedule an event right now: movie"
116
+ * "Schedule an appointment tomorrow, all-day: movie"
117
+ * "New appointment now: movie"
118
+ * Etc.
119
+
120
+ #### Scheduled events
121
+
122
+ Create events that fire later just like you would any other scheduled event:
123
+
124
+ * "New appointment for tomorrow at 4am: deploy"
125
+ * "Schedule a deploy tomorrow at 4am"
126
+ * "Schedule an event tomorrow at 4am: deploy"
127
+ * "Schedule an appointment tomorrow, at 4am: deploy"
128
+ * Etc.
129
+
130
+ Compatibility
131
+ -------------
132
+
133
+ Tested under Rails 3.X.
134
+
135
+ Contribute
136
+ ----------
137
+
138
+ Pull requests for features and bug fix with tests are welcome.
139
+
140
+ This is my first gem so please consider this as beta version.
141
+
142
+ TODO
143
+ ----
144
+
145
+ * Find an asynchronous way to get calendar events.
146
+ * Possibility to use different caldav servers, not only gmail.
147
+
148
+ License
149
+ -------
150
+
151
+ This project rocks and uses MIT-LICENSE.
152
+
153
+ [s]: http://www.apple.com/iphone/features/siri.html
154
+ [ss]: https://github.com/tysontate/siri_says
155
+ [gc]: https://github.com/northworld/google_calendar
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'SiriCal'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+
25
+ Bundler::GemHelper.install_tasks
26
+
27
+ require 'rake/testtask'
28
+
29
+ Rake::TestTask.new(:test) do |t|
30
+ t.libs << 'lib'
31
+ t.libs << 'test'
32
+ t.pattern = 'test/**/*_test.rb'
33
+ t.verbose = false
34
+ end
35
+
36
+
37
+ task :default => :test
@@ -0,0 +1,16 @@
1
+ module SiriCal
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base #:nodoc:
4
+ source_root File.expand_path("../templates", __FILE__)
5
+ desc "Copies siri says file"
6
+
7
+ def copy_siri_says_default
8
+ copy_file "siri_says/default.rb", "lib/siri_says/default.rb"
9
+ end
10
+
11
+ def copy_config
12
+ copy_file "siri_cal.rb", "config/initializers/siri_cal.rb"
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,13 @@
1
+ SiriCal.setup do |config|
2
+ # Configure the path containing the siri says files.
3
+ config.siri_says_path = "lib/siri_says"
4
+
5
+ # Set the delete event policy
6
+ # :success delete event only when event matches one of the siri says block
7
+ # :always delete event once it is fetched from calendar
8
+ # :none never delete event
9
+ config.delete_event = :success
10
+
11
+ # Set the calendar name to connect to. Default: "sirical"
12
+ # config.calendar_name = "sirical"
13
+ end
@@ -0,0 +1,3 @@
1
+ says /^(?:|a )movie (.+)$/i do |movie_name|
2
+ puts "[Siri] Movie #{movie_name} scheduled by #{@object.name} at #{@event.start_time}"
3
+ end
data/lib/siri_cal.rb ADDED
@@ -0,0 +1,41 @@
1
+ Bundler.require
2
+ require 'active_support/concern'
3
+ require 'active_support/dependencies'
4
+ require 'rails/generators'
5
+
6
+ require 'generators/install'
7
+ require 'siri_cal/say_proxy'
8
+ require 'siri_cal/methods'
9
+
10
+ module SiriCal
11
+ extend ActiveSupport::Concern
12
+ class RedundantError < StandardError; end;
13
+
14
+ # Public: String path of the siri's says files. Default: "lib/siri_says"
15
+ mattr_accessor :siri_says_path
16
+ @@siri_says_path = "lib/siri_says"
17
+
18
+ # Public: String path of the siri's says files. Default: :success
19
+ mattr_accessor :delete_event
20
+ @@delete_event = :success
21
+
22
+ # Public: String name of the caldav calendar to connect to. Default: "sirical"
23
+ mattr_accessor :calendar_name
24
+ @@calendar_name = "sirical"
25
+
26
+ def self.setup
27
+ yield self
28
+ end
29
+
30
+ module StepMethods
31
+ def says(regexp=nil, &block)
32
+ @proxy = SayProxy
33
+ @proxy << Say.new(regexp, &block) if regexp && block
34
+ @proxy
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ ActiveRecord::Base.send :include, SiriCal
41
+ Object.send :include, SiriCal::StepMethods
@@ -0,0 +1,49 @@
1
+ require 'google_calendar'
2
+
3
+ module SiriCal
4
+ module ClassMethods
5
+ # Public: Initialize a Siriable object.
6
+ #
7
+ # options - The Hash options used to redefine the config (default: {}):
8
+ # :login - The Symbol login field to sign in with (default: :login).
9
+ # :password - The Symbol login field to sign in with (default: :password).
10
+ #
11
+ # Examples
12
+ #
13
+ # siriable :login => :caldav_login, :password => :caldav_password
14
+ #
15
+ #
16
+ # Returns nothing.
17
+
18
+ def siriable options={}
19
+ config = {}
20
+ config[:login] = options.delete(:login) || :siriable_login
21
+ config[:password] = options.delete(:password) || :siriable_password
22
+ config.each do |key, value|
23
+ define_method "siri_cal_#{key}" do
24
+ self.send(value)
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ module InstanceMethods
31
+ # Public: Initialize calendar
32
+ #
33
+ # Returns an instance of Google::Calendar.
34
+ def calendar
35
+ Google::Calendar.new :username => siri_cal_login, :password => siri_cal_password, :calendar => calendar_name
36
+ end
37
+
38
+ # Public: GET calendar's event and run then according to block defined in lib/siri_says.rb
39
+ #
40
+ # Returns nothing.
41
+ def execute_siri!
42
+ SayProxy.load_files
43
+ calendar.events.to_a.each do |event|
44
+ res = SayProxy.invoke_say(event, self)
45
+ event.delete if (res && delete_event == :success) || delete_event == :always
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,63 @@
1
+ module SiriCal
2
+
3
+ class Say
4
+ def initialize(regexp, &block)
5
+ self.regexp, self.block = regexp, block
6
+ end
7
+
8
+ attr_accessor :regexp, :block, :captures
9
+ end
10
+
11
+ class SayProxy
12
+ class << self
13
+ def proxy
14
+ @proxy ||= []
15
+ end
16
+
17
+ def <<(say)
18
+ proxy << say
19
+ end
20
+
21
+ def count
22
+ proxy.count
23
+ end
24
+
25
+ def matches_says(name)
26
+ proxy.select { |say| !!(say.regexp =~ name and say.captures = $~.captures) }
27
+ end
28
+
29
+ def invoke_say(event, object=nil)
30
+ matches = matches_says(event.title)
31
+ raise RedundantError, "You should have only one say step that matches \"#{name}\"" if matches.size > 1
32
+ if !matches.empty?
33
+ m = matches.first
34
+ @object, @event = object, event
35
+ self.instance_exec(*m.captures, &m.block)
36
+ return true
37
+ end
38
+ false
39
+ end
40
+
41
+ def clear
42
+ proxy.clear
43
+ end
44
+
45
+ # Internal : Load only once Siri says files
46
+ #
47
+ # Returns true on success
48
+ # Returns false if already loaded
49
+ def load_files
50
+ return false unless proxy.empty?
51
+ Dir.glob(File.join(SiriCal.siri_says_path, "*")).each do |filename|
52
+ load File.expand_path(filename)
53
+ end
54
+ true
55
+ end
56
+
57
+ def all
58
+ proxy
59
+ end
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,3 @@
1
+ module SiriCal
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :siri_cal do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
3
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4
+
5
+ require File.expand_path('../config/application', __FILE__)
6
+
7
+ Dummy::Application.load_tasks
@@ -0,0 +1,9 @@
1
+ // This is a manifest file that'll be compiled into including all the files listed below.
2
+ // Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
3
+ // be included in the compiled file accessible from http://example.com/assets/application.js
4
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
5
+ // the compiled file.
6
+ //
7
+ //= require jquery
8
+ //= require jquery_ujs
9
+ //= require_tree .
@@ -0,0 +1,7 @@
1
+ /*
2
+ * This is a manifest file that'll automatically include all the stylesheets available in this directory
3
+ * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
4
+ * the top of the compiled file, but it's generally better to create a new file per style scope.
5
+ *= require_self
6
+ *= require_tree .
7
+ */