siri_cal 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.md +155 -0
- data/Rakefile +37 -0
- data/lib/generators/install.rb +16 -0
- data/lib/generators/templates/siri_cal.rb +13 -0
- data/lib/generators/templates/siri_says/default.rb +3 -0
- data/lib/siri_cal.rb +41 -0
- data/lib/siri_cal/methods.rb +49 -0
- data/lib/siri_cal/say_proxy.rb +63 -0
- data/lib/siri_cal/version.rb +3 -0
- data/lib/tasks/siri_cal_tasks.rake +4 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +9 -0
- data/test/dummy/app/assets/stylesheets/application.css +7 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/models/movie.rb +2 -0
- data/test/dummy/app/models/user.rb +4 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +45 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +30 -0
- data/test/dummy/config/environments/production.rb +60 -0
- data/test/dummy/config/environments/test.rb +42 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +10 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +58 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20111105175135_create_users.rb +11 -0
- data/test/dummy/db/migrate/20111108194230_create_movies.rb +11 -0
- data/test/dummy/db/schema.rb +31 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/lib/siri_says/default.rb +3 -0
- data/test/dummy/log/development.log +102 -0
- data/test/dummy/log/test.log +4932 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +26 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/dummy/test/fixtures/movies.yml +7 -0
- data/test/dummy/test/fixtures/users.yml +11 -0
- data/test/dummy/test/unit/movie_test.rb +7 -0
- data/test/dummy/test/unit/user_test.rb +7 -0
- data/test/fixtures/vcr_cassettes/invalid_credentials.yml +36 -0
- data/test/fixtures/vcr_cassettes/valid_credentials.yml +38 -0
- data/test/fixtures/vcr_cassettes/valid_credentials_with_events.yml +772 -0
- data/test/fixtures/vcr_cassettes/valid_credentials_with_events_to_delete.yml +948 -0
- data/test/generators/install_test.rb +13 -0
- data/test/siri_cal_test.rb +82 -0
- data/test/test_helper.rb +23 -0
- 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
|
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
|
data/test/dummy/Rakefile
ADDED
@@ -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
|
+
*/
|