alexa-rails 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +165 -0
- data/Rakefile +36 -0
- data/app/assets/config/alexa_manifest.js +2 -0
- data/app/assets/javascripts/alexa/application.js +13 -0
- data/app/assets/stylesheets/alexa/application.css +15 -0
- data/app/controllers/alexa/application_controller.rb +6 -0
- data/app/controllers/alexa/intent_handlers_controller.rb +49 -0
- data/app/helpers/alexa/application_helper.rb +4 -0
- data/app/helpers/alexa/context_helper.rb +23 -0
- data/app/helpers/alexa/render_helper.rb +24 -0
- data/app/jobs/alexa/application_job.rb +4 -0
- data/app/mailers/alexa/application_mailer.rb +6 -0
- data/app/models/alexa/application_record.rb +5 -0
- data/app/models/alexa/usage.rb +11 -0
- data/app/models/alexa/user.rb +17 -0
- data/app/views/alexa/_response.json.erb +18 -0
- data/app/views/alexa/output/_card.json.erb +13 -0
- data/app/views/alexa/output/_ssml.json.erb +7 -0
- data/app/views/alexa/output/cards/_ask_for_permissions_consent.json.erb +6 -0
- data/app/views/alexa/output/cards/_simple.json.erb +5 -0
- data/app/views/alexa/permission_consents/device_address.text.erb +7 -0
- data/app/views/layouts/alexa/application.html.erb +14 -0
- data/config/routes.rb +3 -0
- data/lib/alexa/context.rb +38 -0
- data/lib/alexa/device.rb +61 -0
- data/lib/alexa/engine.rb +5 -0
- data/lib/alexa/intent_handlers/base.rb +158 -0
- data/lib/alexa/request.rb +97 -0
- data/lib/alexa/response.rb +85 -0
- data/lib/alexa/responses/bye.rb +26 -0
- data/lib/alexa/responses/delegate.rb +18 -0
- data/lib/alexa/responses/permission_consents/device_address.rb +28 -0
- data/lib/alexa/session.rb +35 -0
- data/lib/alexa/slot.rb +50 -0
- data/lib/alexa/version.rb +3 -0
- data/lib/alexa-rails.rb +19 -0
- data/lib/generators/alexa/migrations_generator.rb +22 -0
- data/lib/generators/alexa/templates/create_alexa_usages.rb +13 -0
- data/lib/generators/alexa/templates/create_alexa_users.rb +13 -0
- data/lib/tasks/alexa_tasks.rake +4 -0
- metadata +115 -0
@@ -0,0 +1,158 @@
|
|
1
|
+
module Alexa
|
2
|
+
module IntentHandlers
|
3
|
+
class Base
|
4
|
+
class << self
|
5
|
+
def inherited(subclass)
|
6
|
+
subclass.instance_variable_set("@_required_slot_names", _required_slot_names.clone)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Lets you set +required_slot_names+ per subclass
|
10
|
+
#
|
11
|
+
# class IntentHandlers::NewIntent < IntentHandlers::Base
|
12
|
+
# required_slot_names :Function, :CareerLevel
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# handler = IntentHandlers::NewIntent.new
|
16
|
+
# handler.required_slot_names # => [:Function, :CareerLevel]
|
17
|
+
|
18
|
+
def _required_slot_names
|
19
|
+
@_required_slot_names ||= []
|
20
|
+
end
|
21
|
+
|
22
|
+
def required_slot_names(*names)
|
23
|
+
@_required_slot_names = names.map(&:to_s)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_accessor :context
|
28
|
+
|
29
|
+
def initialize(alexa_context)
|
30
|
+
@context = alexa_context
|
31
|
+
end
|
32
|
+
|
33
|
+
def request
|
34
|
+
context.request
|
35
|
+
end
|
36
|
+
|
37
|
+
def handle
|
38
|
+
raise "Override .handle"
|
39
|
+
end
|
40
|
+
|
41
|
+
def session
|
42
|
+
request.session
|
43
|
+
end
|
44
|
+
|
45
|
+
def response
|
46
|
+
@_response ||= Alexa::Response.new(intent: self)
|
47
|
+
end
|
48
|
+
|
49
|
+
def say_welcome?
|
50
|
+
@say_welcome == true
|
51
|
+
end
|
52
|
+
|
53
|
+
def slots
|
54
|
+
request.slots
|
55
|
+
end
|
56
|
+
|
57
|
+
def intent_usage_count
|
58
|
+
@_usage_count ||= context.user.usage_count_for(intent_name: request.intent_name)
|
59
|
+
end
|
60
|
+
|
61
|
+
def show_device_address_permission_consent_card?
|
62
|
+
@_show_device_address_permission_consent_card == true
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
protected
|
67
|
+
|
68
|
+
def has_all_slots?
|
69
|
+
empty_slots.empty?
|
70
|
+
end
|
71
|
+
|
72
|
+
def has_required_slots?
|
73
|
+
non_empty_slot_names = non_empty_slots.map { |_, s| s.name }
|
74
|
+
(required_slot_names - non_empty_slot_names).empty?
|
75
|
+
end
|
76
|
+
|
77
|
+
def empty_slots
|
78
|
+
@_empty_slots ||= slots.select { |name, slot| slot.value.nil? }
|
79
|
+
end
|
80
|
+
|
81
|
+
def non_empty_slots
|
82
|
+
@_non_empty_slots ||= slots.select { |name, slot| !slot.value.nil? }
|
83
|
+
end
|
84
|
+
|
85
|
+
def unmatched_slots
|
86
|
+
@_unmatched_slots ||= slots.select { |_, slot| slot.bad_match? }
|
87
|
+
end
|
88
|
+
|
89
|
+
def required_slot_names
|
90
|
+
self.class._required_slot_names
|
91
|
+
end
|
92
|
+
|
93
|
+
def intent_confirmed?
|
94
|
+
# TODO: Move this to Alexa::Request
|
95
|
+
request.params["request"]["intent"]["confirmationStatus"] == "CONFIRMED"
|
96
|
+
end
|
97
|
+
|
98
|
+
def intent_denied?
|
99
|
+
# TODO: Move this to Alexa::Request
|
100
|
+
request.params["request"]["intent"]["confirmationStatus"] == "DENIED"
|
101
|
+
end
|
102
|
+
|
103
|
+
def dialog_complete?
|
104
|
+
dialog_state == "COMPLETED"
|
105
|
+
end
|
106
|
+
|
107
|
+
def has_unmatched_slots?
|
108
|
+
unmatched_slots.any?
|
109
|
+
end
|
110
|
+
|
111
|
+
def dialog_state
|
112
|
+
request.dialog_state
|
113
|
+
end
|
114
|
+
|
115
|
+
def sorry_response
|
116
|
+
{
|
117
|
+
"version": "1.0",
|
118
|
+
sessionAttributes: session,
|
119
|
+
"response": {
|
120
|
+
"outputSpeech": {
|
121
|
+
"type": "PlainText",
|
122
|
+
"ssml": "Sorry! Looks like I couldn't process your request, may be try something else?"
|
123
|
+
},
|
124
|
+
"shouldEndSession": false
|
125
|
+
}
|
126
|
+
}
|
127
|
+
end
|
128
|
+
|
129
|
+
def show_device_address_permission_consent_card!
|
130
|
+
@_show_device_address_permission_consent_card = true
|
131
|
+
end
|
132
|
+
|
133
|
+
def device_address_permission_consent_response
|
134
|
+
@_device_address_permission_consent_response ||= Alexa::Responses::PermissionConsents::DeviceAddress.new(intent: self)
|
135
|
+
end
|
136
|
+
|
137
|
+
def delegate_response
|
138
|
+
@_delegate_response ||= Alexa::Responses::Delegate.new
|
139
|
+
end
|
140
|
+
|
141
|
+
def bye_response
|
142
|
+
@_bye_response ||= Alexa::Responses::Bye.new(intent: self)
|
143
|
+
end
|
144
|
+
|
145
|
+
def say_welcome!
|
146
|
+
@say_welcome = true
|
147
|
+
end
|
148
|
+
|
149
|
+
def video_supported?
|
150
|
+
context.device.video_supported?
|
151
|
+
end
|
152
|
+
|
153
|
+
def audio_supported?
|
154
|
+
context.device.audio_supported?
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module Alexa
|
2
|
+
class Request
|
3
|
+
attr_accessor :body, :params
|
4
|
+
|
5
|
+
def initialize(request)
|
6
|
+
@req = request
|
7
|
+
@body = request.body
|
8
|
+
@params = if request.body.size > 0
|
9
|
+
request.body.rewind
|
10
|
+
JSON.parse(request.body.read).with_indifferent_access
|
11
|
+
else
|
12
|
+
{}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def application_id
|
17
|
+
session.application_id
|
18
|
+
end
|
19
|
+
|
20
|
+
def user_id
|
21
|
+
session.user_id
|
22
|
+
end
|
23
|
+
|
24
|
+
def type
|
25
|
+
params["request"]["type"]
|
26
|
+
end
|
27
|
+
|
28
|
+
def intent_request?
|
29
|
+
type == "IntentRequest"
|
30
|
+
end
|
31
|
+
|
32
|
+
def launch_request?
|
33
|
+
type == "LaunchRequest"
|
34
|
+
end
|
35
|
+
|
36
|
+
def session_ended_request?
|
37
|
+
type == "SessionEndedRequest"
|
38
|
+
end
|
39
|
+
|
40
|
+
def help_request?
|
41
|
+
intent_request? && intent_name == "AMAZON.HelpIntent"
|
42
|
+
end
|
43
|
+
|
44
|
+
def cancel_request?
|
45
|
+
intent_request? && intent_name == "AMAZON.CancelIntent"
|
46
|
+
end
|
47
|
+
|
48
|
+
def session
|
49
|
+
@_session ||= Alexa::Session.new(params["session"].dup)
|
50
|
+
end
|
51
|
+
|
52
|
+
def slots
|
53
|
+
@_slots ||= begin
|
54
|
+
if intent_request?
|
55
|
+
return [] if help_request?
|
56
|
+
return [] if cancel_request?
|
57
|
+
|
58
|
+
params["request"]["intent"]["slots"]
|
59
|
+
.inject(HashWithIndifferentAccess.new) do |hash, slot|
|
60
|
+
name = slot[0]
|
61
|
+
data = slot[1]
|
62
|
+
hash[name] = Alexa::Slot.new(data)
|
63
|
+
hash
|
64
|
+
end
|
65
|
+
else
|
66
|
+
[]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def dialog_state
|
72
|
+
params["request"]["dialogState"]
|
73
|
+
end
|
74
|
+
|
75
|
+
def valid?
|
76
|
+
Rails.configuration.x.alexa.skill_ids.include?(application_id)
|
77
|
+
end
|
78
|
+
|
79
|
+
def intent_name
|
80
|
+
return nil if !intent_request?
|
81
|
+
params["request"]["intent"]["name"]
|
82
|
+
end
|
83
|
+
|
84
|
+
def locale
|
85
|
+
request_locale = params["request"]["locale"]
|
86
|
+
case params["request"]["locale"]
|
87
|
+
when "en-US", "en-GB", "en-IN", 'en-CA'
|
88
|
+
# this is to match pjpp locale codes
|
89
|
+
params["request"]["locale"].gsub("-", "_").downcase
|
90
|
+
when "de-DE"
|
91
|
+
"de"
|
92
|
+
else
|
93
|
+
"en_gb"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Alexa
|
2
|
+
class Response
|
3
|
+
attr_accessor :intent, :directives
|
4
|
+
|
5
|
+
def initialize(intent:, directives: [])
|
6
|
+
@intent = intent
|
7
|
+
@directives = directives
|
8
|
+
@slots_to_not_render_elicitation = []
|
9
|
+
end
|
10
|
+
|
11
|
+
# Marks a slot for elicitation.
|
12
|
+
#
|
13
|
+
# Options:
|
14
|
+
# - skip_render: Lets you skip the rendering of the elicited slot's view.
|
15
|
+
# Helpful when you have the elication text already in the
|
16
|
+
# response and don't wanna override it.
|
17
|
+
def elicit_slot!(slot_to_elicit, skip_render: false)
|
18
|
+
directives << {
|
19
|
+
type: "Dialog.ElicitSlot",
|
20
|
+
slotToElicit: slot_to_elicit
|
21
|
+
}
|
22
|
+
|
23
|
+
if skip_render
|
24
|
+
@slots_to_not_render_elicitation << slot_to_elicit
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def partial_path(format: :ssml, filename: nil)
|
29
|
+
if elicit_directives.any?
|
30
|
+
slot_to_elicit = elicit_directives.first[:slotToElicit]
|
31
|
+
end
|
32
|
+
|
33
|
+
template_path = "alexa/#{intent.context.locale}/intent_handlers/"\
|
34
|
+
"#{intent.class.name.demodulize.underscore}"
|
35
|
+
|
36
|
+
if filename.present?
|
37
|
+
if format == :ssml
|
38
|
+
"#{template_path}/#{filename}.ssml.erb"
|
39
|
+
else
|
40
|
+
"#{template_path}/#{filename}.text.erb"
|
41
|
+
end
|
42
|
+
else
|
43
|
+
if intent.show_device_address_permission_consent_card? && format == :text
|
44
|
+
return Alexa::Responses::PermissionConsents::DeviceAddress.new(
|
45
|
+
intent: intent
|
46
|
+
).partial_path(format: :text)
|
47
|
+
end
|
48
|
+
|
49
|
+
if slot_to_elicit.present? && !@slots_to_not_render_elicitation.include?(slot_to_elicit)
|
50
|
+
if format == :ssml
|
51
|
+
"#{template_path}/elicitations/#{slot_to_elicit.underscore}.ssml.erb"
|
52
|
+
else
|
53
|
+
"#{template_path}/elicitations/#{slot_to_elicit.underscore}.text.erb"
|
54
|
+
end
|
55
|
+
else
|
56
|
+
if format == :ssml
|
57
|
+
"#{template_path}/speech.ssml.erb"
|
58
|
+
else
|
59
|
+
"#{template_path}/display.text.erb"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def elicit_directives
|
66
|
+
return [] if directives.empty?
|
67
|
+
directives.select { |directive| directive[:type] == "Dialog.ElicitSlot" }
|
68
|
+
end
|
69
|
+
|
70
|
+
def keep_listening!
|
71
|
+
@keep_listening = true
|
72
|
+
self
|
73
|
+
end
|
74
|
+
|
75
|
+
def keep_listening?
|
76
|
+
@keep_listening == true
|
77
|
+
end
|
78
|
+
|
79
|
+
def end_session?
|
80
|
+
return false if keep_listening?
|
81
|
+
return false if elicit_directives.any?
|
82
|
+
return true
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Alexa
|
2
|
+
module Responses
|
3
|
+
class Bye < Alexa::Response
|
4
|
+
attr_accessor :intent, :directives
|
5
|
+
|
6
|
+
def initialize(intent:, directives: [])
|
7
|
+
@intent = intent
|
8
|
+
end
|
9
|
+
|
10
|
+
def partial_path(format: :ssml)
|
11
|
+
template_path = "alexa/#{intent.context.locale}/intent_handlers/"\
|
12
|
+
"#{intent.class.name.demodulize.underscore}"
|
13
|
+
|
14
|
+
if format == :ssml
|
15
|
+
"#{template_path}/bye.ssml.erb"
|
16
|
+
else
|
17
|
+
"#{template_path}/bye.text.erb"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def end_session?
|
22
|
+
true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Alexa
|
2
|
+
module Responses
|
3
|
+
module PermissionConsents
|
4
|
+
class DeviceAddress < Alexa::Response
|
5
|
+
attr_accessor :intent, :directives
|
6
|
+
|
7
|
+
def initialize(intent:, directives: [])
|
8
|
+
@intent = intent
|
9
|
+
end
|
10
|
+
|
11
|
+
def partial_path(format: :ssml)
|
12
|
+
if format == :ssml
|
13
|
+
"alexa/#{intent.context.locale}/intent_handlers/"\
|
14
|
+
"#{intent.class.name.demodulize.underscore}"\
|
15
|
+
"/permission_consents/"\
|
16
|
+
"device_address.ssml.erb"
|
17
|
+
else
|
18
|
+
"alexa/permission_consents/device_address.text.erb"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def end_session?
|
23
|
+
true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Alexa
|
2
|
+
class Session < HashWithIndifferentAccess
|
3
|
+
def initialize(session={})
|
4
|
+
@variables = session
|
5
|
+
super(session["attributes"])
|
6
|
+
end
|
7
|
+
|
8
|
+
def elicitation_count_for(slot_name)
|
9
|
+
self["elicitations"] ||= {}
|
10
|
+
if self["elicitations"][slot_name].present?
|
11
|
+
return self["elicitations"][slot_name]["count"]
|
12
|
+
end
|
13
|
+
return 0
|
14
|
+
end
|
15
|
+
|
16
|
+
def increment_elicitation_count!(slot_name)
|
17
|
+
count = elicitation_count_for(slot_name)
|
18
|
+
self["elicitations"].merge!(
|
19
|
+
"#{slot_name}": { count: count + 1 }
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def new?
|
24
|
+
@variables["new"] == true
|
25
|
+
end
|
26
|
+
|
27
|
+
def application_id
|
28
|
+
@variables["application"]["applicationId"]
|
29
|
+
end
|
30
|
+
|
31
|
+
def user_id
|
32
|
+
@variables["user"]["userId"]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/alexa/slot.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
module Alexa
|
2
|
+
class Slot
|
3
|
+
attr_accessor :name, :value
|
4
|
+
|
5
|
+
def initialize(attributes={})
|
6
|
+
@name = attributes['name']
|
7
|
+
@value = attributes['value']
|
8
|
+
@resolutions = attributes['resolutions']
|
9
|
+
end
|
10
|
+
|
11
|
+
def matched_value
|
12
|
+
if matched?
|
13
|
+
resolution["values"].first["value"]["name"]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def matched_id
|
18
|
+
if matched?
|
19
|
+
resolution["values"].first["value"]["id"]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def matched?
|
24
|
+
return false if !has_resolutions?
|
25
|
+
resolution["status"]["code"] == "ER_SUCCESS_MATCH"
|
26
|
+
end
|
27
|
+
|
28
|
+
def bad_match?
|
29
|
+
return false if !has_resolutions?
|
30
|
+
resolution["status"]["code"] == "ER_SUCCESS_NO_MATCH"
|
31
|
+
end
|
32
|
+
|
33
|
+
def has_resolutions?
|
34
|
+
@resolutions.present?
|
35
|
+
end
|
36
|
+
|
37
|
+
def resolution
|
38
|
+
return nil if !has_resolutions?
|
39
|
+
@resolutions["resolutionsPerAuthority"].first
|
40
|
+
end
|
41
|
+
|
42
|
+
def as_json(options={})
|
43
|
+
h = { name: name }
|
44
|
+
# add other attributes only if they are present
|
45
|
+
h.merge!(value: value) if value.present?
|
46
|
+
h.merge!(resolutions: @resolutions) if @resolutions.present?
|
47
|
+
h
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/alexa-rails.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "alexa/engine"
|
2
|
+
require 'alexa/context'
|
3
|
+
require 'alexa/device'
|
4
|
+
require 'alexa/request'
|
5
|
+
require 'alexa/response'
|
6
|
+
require 'alexa/session'
|
7
|
+
require 'alexa/slot'
|
8
|
+
require 'alexa/version'
|
9
|
+
require 'alexa/responses/bye'
|
10
|
+
require 'alexa/responses/delegate'
|
11
|
+
require 'alexa/responses/permission_consents/device_address'
|
12
|
+
require 'alexa/intent_handlers/base'
|
13
|
+
require_relative '../app/models/alexa/user'
|
14
|
+
require_relative '../app/models/alexa/usage'
|
15
|
+
|
16
|
+
|
17
|
+
module Alexa
|
18
|
+
# Your code goes here...
|
19
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/migration'
|
3
|
+
|
4
|
+
module Alexa
|
5
|
+
module Generators
|
6
|
+
class MigrationsGenerator < ::Rails::Generators::Base
|
7
|
+
include Rails::Generators::Migration
|
8
|
+
source_root File.expand_path('../templates', __FILE__)
|
9
|
+
desc "Add the migrations for Alexa"
|
10
|
+
|
11
|
+
def self.next_migration_number(path)
|
12
|
+
next_migration_number = current_migration_number(path) + 1
|
13
|
+
ActiveRecord::Migration.next_migration_number(next_migration_number)
|
14
|
+
end
|
15
|
+
|
16
|
+
def copy_migrations
|
17
|
+
migration_template "create_alexa_users.rb", "db/migrate/create_alexa_users.rb"
|
18
|
+
migration_template "create_alexa_usages.rb", "db/migrate/create_alexa_usages.rb"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class CreateAlexaUsages < ActiveRecord::Migration[4.2]
|
2
|
+
def up
|
3
|
+
create_table :alexa_usages do |t|
|
4
|
+
t.references :alexa_user, foreign_key: true
|
5
|
+
t.string :intent_name
|
6
|
+
t.integer :count, default: 0
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def down
|
11
|
+
drop_table :alexa_usages
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class CreateAlexaUsers < ActiveRecord::Migration[4.2]
|
2
|
+
def up
|
3
|
+
create_table :alexa_users do |t|
|
4
|
+
t.string :amazon_id
|
5
|
+
end
|
6
|
+
add_index :alexa_users, :amazon_id
|
7
|
+
end
|
8
|
+
|
9
|
+
def down
|
10
|
+
remove_index :alexa_users, :amazon_id
|
11
|
+
drop_table :alexa_users
|
12
|
+
end
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: alexa-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sri Vishnu Totakura
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-03-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 5.1.4
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 5.1.4
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pg
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: The gem adds additional capabilities to your rails app to serve as a
|
42
|
+
backend for your Alexa skill by providing routing, controllers, views and structure
|
43
|
+
to easily develop and maintain skills' backend
|
44
|
+
email:
|
45
|
+
- srivishnu@totakura.in
|
46
|
+
executables: []
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- MIT-LICENSE
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- app/assets/config/alexa_manifest.js
|
54
|
+
- app/assets/javascripts/alexa/application.js
|
55
|
+
- app/assets/stylesheets/alexa/application.css
|
56
|
+
- app/controllers/alexa/application_controller.rb
|
57
|
+
- app/controllers/alexa/intent_handlers_controller.rb
|
58
|
+
- app/helpers/alexa/application_helper.rb
|
59
|
+
- app/helpers/alexa/context_helper.rb
|
60
|
+
- app/helpers/alexa/render_helper.rb
|
61
|
+
- app/jobs/alexa/application_job.rb
|
62
|
+
- app/mailers/alexa/application_mailer.rb
|
63
|
+
- app/models/alexa/application_record.rb
|
64
|
+
- app/models/alexa/usage.rb
|
65
|
+
- app/models/alexa/user.rb
|
66
|
+
- app/views/alexa/_response.json.erb
|
67
|
+
- app/views/alexa/output/_card.json.erb
|
68
|
+
- app/views/alexa/output/_ssml.json.erb
|
69
|
+
- app/views/alexa/output/cards/_ask_for_permissions_consent.json.erb
|
70
|
+
- app/views/alexa/output/cards/_simple.json.erb
|
71
|
+
- app/views/alexa/permission_consents/device_address.text.erb
|
72
|
+
- app/views/layouts/alexa/application.html.erb
|
73
|
+
- config/routes.rb
|
74
|
+
- lib/alexa-rails.rb
|
75
|
+
- lib/alexa/context.rb
|
76
|
+
- lib/alexa/device.rb
|
77
|
+
- lib/alexa/engine.rb
|
78
|
+
- lib/alexa/intent_handlers/base.rb
|
79
|
+
- lib/alexa/request.rb
|
80
|
+
- lib/alexa/response.rb
|
81
|
+
- lib/alexa/responses/bye.rb
|
82
|
+
- lib/alexa/responses/delegate.rb
|
83
|
+
- lib/alexa/responses/permission_consents/device_address.rb
|
84
|
+
- lib/alexa/session.rb
|
85
|
+
- lib/alexa/slot.rb
|
86
|
+
- lib/alexa/version.rb
|
87
|
+
- lib/generators/alexa/migrations_generator.rb
|
88
|
+
- lib/generators/alexa/templates/create_alexa_usages.rb
|
89
|
+
- lib/generators/alexa/templates/create_alexa_users.rb
|
90
|
+
- lib/tasks/alexa_tasks.rake
|
91
|
+
homepage: https://github.com/tsrivishnu/alexa-rails
|
92
|
+
licenses:
|
93
|
+
- MIT
|
94
|
+
metadata: {}
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
requirements: []
|
110
|
+
rubyforge_project:
|
111
|
+
rubygems_version: 2.5.2.1
|
112
|
+
signing_key:
|
113
|
+
specification_version: 4
|
114
|
+
summary: Serve Alexa skills with your rails app as backend
|
115
|
+
test_files: []
|