alexa_skills_ruby 0.0.5
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.
- checksums.yaml +7 -0
- data/.gitignore +36 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +58 -0
- data/Rakefile +7 -0
- data/alexa_skills_ruby.gemspec +26 -0
- data/lib/alexa_skills_ruby.rb +27 -0
- data/lib/alexa_skills_ruby/errors.rb +4 -0
- data/lib/alexa_skills_ruby/handler.rb +87 -0
- data/lib/alexa_skills_ruby/json_object.rb +122 -0
- data/lib/alexa_skills_ruby/json_objects/application.rb +7 -0
- data/lib/alexa_skills_ruby/json_objects/base_request.rb +40 -0
- data/lib/alexa_skills_ruby/json_objects/card.rb +16 -0
- data/lib/alexa_skills_ruby/json_objects/image.rb +7 -0
- data/lib/alexa_skills_ruby/json_objects/intent.rb +11 -0
- data/lib/alexa_skills_ruby/json_objects/intent_request.rb +7 -0
- data/lib/alexa_skills_ruby/json_objects/launch_request.rb +7 -0
- data/lib/alexa_skills_ruby/json_objects/output_speech.rb +21 -0
- data/lib/alexa_skills_ruby/json_objects/reprompt.rb +7 -0
- data/lib/alexa_skills_ruby/json_objects/response.rb +29 -0
- data/lib/alexa_skills_ruby/json_objects/session.rb +9 -0
- data/lib/alexa_skills_ruby/json_objects/session_ended_request.rb +7 -0
- data/lib/alexa_skills_ruby/json_objects/skills_request.rb +9 -0
- data/lib/alexa_skills_ruby/json_objects/skills_response.rb +14 -0
- data/lib/alexa_skills_ruby/json_objects/user.rb +7 -0
- data/lib/alexa_skills_ruby/version.rb +3 -0
- data/spec/fixtures/example_intent.json +34 -0
- data/spec/fixtures/example_launch.json +19 -0
- data/spec/fixtures/example_response.json +28 -0
- data/spec/fixtures/example_session_ended.json +26 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/fixture_support.rb +11 -0
- data/spec/unit/handler_spec.rb +142 -0
- data/spec/unit/json_object_spec.rb +59 -0
- data/spec/unit/json_objects/skills_request_spec.rb +56 -0
- data/spec/unit/json_objects/skills_response_spec.rb +48 -0
- metadata +173 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1101b97d3f88c45eb43d643d75e3e8e8ca6b26c6
|
4
|
+
data.tar.gz: 0b6350b302c7ed1b643471986233069fe0a139c7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fc1a9404b923d9575c8a75aceed09e7bd0b9dda09230f08d475b199c7f7d53923160c39b9093d3d645872e8d0611eb3e805d31f40c35c11e56683a30aa9e2bdf
|
7
|
+
data.tar.gz: e3f2725899cd0147118eb291c6ba8f6753bb521d67232722695eaa78e9cd0eb6c58e9f4c1d12254da9d8796d7d36abe0a52a941a896cc88357f976a5f5869bbf
|
data/.gitignore
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
|
13
|
+
## Specific to RubyMotion:
|
14
|
+
.dat*
|
15
|
+
.repl_history
|
16
|
+
build/
|
17
|
+
|
18
|
+
## Documentation cache and generated files:
|
19
|
+
/.yardoc/
|
20
|
+
/_yardoc/
|
21
|
+
/doc/
|
22
|
+
/rdoc/
|
23
|
+
|
24
|
+
## Environment normalization:
|
25
|
+
/.bundle/
|
26
|
+
/vendor/bundle
|
27
|
+
/lib/bundler/man/
|
28
|
+
|
29
|
+
# for a library or gem, you might want to ignore these files since the code is
|
30
|
+
# intended to run in multiple environments; otherwise, check them in:
|
31
|
+
Gemfile.lock
|
32
|
+
# .ruby-version
|
33
|
+
# .ruby-gemset
|
34
|
+
|
35
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
36
|
+
.rvmrc
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Dan Elbert
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# alexa-skills-ruby
|
2
|
+
Simple library to interface with the Alexa Skills Kit
|
3
|
+
|
4
|
+
The primary way to interact with this library is by extending the `AlexaSkillsRuby::Handler` class. Create a subclass and
|
5
|
+
register event handlers.
|
6
|
+
|
7
|
+
The following handlers are available:
|
8
|
+
|
9
|
+
* `on_authenticate` - called before checking the ApplicationID
|
10
|
+
* `on_session_start` - called first if the request is flagged as a new session
|
11
|
+
* `on_launch` - called for a LaunchRequest
|
12
|
+
* `on_session_end` - called for a SessionEndedRequest
|
13
|
+
* `on_intent` called for an IntentRequest. Takes an optional string argument that specifies which intents it will be trigged on
|
14
|
+
|
15
|
+
In event handlers, the following methods are available:
|
16
|
+
|
17
|
+
* `request` - returns the current Request object, a `AlexaSkillsRuby::JsonObjects::BaseRequest`
|
18
|
+
* `session` - returns the current Session object, a `AlexaSkillsRuby::JsonObjects::Session`
|
19
|
+
* `session_attributes` - Hash containing the current session attributes. If the response is not flagged to end the session, all values will be sent with the response
|
20
|
+
* `response` - returns the current Response object, a `AlexaSkillsRuby::JsonObjects::Response`
|
21
|
+
* `application_id` - returns the value specified in the constructor options
|
22
|
+
* `logger` - returns the value specified in the constructor options
|
23
|
+
|
24
|
+
The `AlexaSkillsRuby::Handler` constructor takes an options hash and processes the following keys:
|
25
|
+
* `application_id` - If set, will raise a `AlexaSkillsRuby::InvalidApplicationId` if a request's application_id does not match
|
26
|
+
* `logger` - Will be available through the `logger` method in the handler; not otherwise used by the base class
|
27
|
+
|
28
|
+
## Example Sinatra App Using this Library
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
require 'sinatra'
|
32
|
+
require 'alexa_skills_ruby'
|
33
|
+
|
34
|
+
class CustomHandler < AlexaSkillsRuby::Handler
|
35
|
+
|
36
|
+
on_intent("GetZodiacHoroscopeIntent") do
|
37
|
+
slots = request.intent.slots
|
38
|
+
response.set_output_speech_text("Horiscope Text")
|
39
|
+
response.set_simple_card("title", "content")
|
40
|
+
logger.info 'GetZodiacHoroscopeIntent processed'
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
post '/' do
|
46
|
+
content_type :json
|
47
|
+
|
48
|
+
handler = CustomHandler.new(application_id: ENV['APPLICATION_ID'], logger: logger)
|
49
|
+
|
50
|
+
begin
|
51
|
+
handler.handle(request.body.read)
|
52
|
+
rescue AlexaSkillsRuby::InvalidApplicationId => e
|
53
|
+
logger.error e.to_s
|
54
|
+
403
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'alexa_skills_ruby/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "alexa_skills_ruby"
|
8
|
+
spec.version = AlexaSkillsRuby::VERSION
|
9
|
+
spec.authors = ["Dan Elbert"]
|
10
|
+
spec.email = ["dan.elbert@gmail.com"]
|
11
|
+
spec.homepage = 'https://github.com/DanElbert/alexa_skills_ruby'
|
12
|
+
spec.summary = %q{Simple library to interface with the Alexa Skills Kit}
|
13
|
+
|
14
|
+
spec.files = `git ls-files -z`.split("\x0")
|
15
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
16
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
17
|
+
spec.require_paths = ["lib"]
|
18
|
+
|
19
|
+
spec.add_runtime_dependency 'activesupport', '~> 4.2'
|
20
|
+
spec.add_runtime_dependency "multi_json", "~> 1.0"
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler"
|
23
|
+
spec.add_development_dependency "rake"
|
24
|
+
spec.add_development_dependency "rspec", "~> 3.4.0"
|
25
|
+
spec.add_development_dependency "oj", "~> 2.10.2"
|
26
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'active_support/core_ext/class/attribute'
|
2
|
+
require 'active_support/callbacks'
|
3
|
+
require 'multi_json'
|
4
|
+
|
5
|
+
require 'alexa_skills_ruby/version'
|
6
|
+
require 'alexa_skills_ruby/json_object'
|
7
|
+
require 'alexa_skills_ruby/json_objects/application'
|
8
|
+
require 'alexa_skills_ruby/json_objects/user'
|
9
|
+
require 'alexa_skills_ruby/json_objects/session'
|
10
|
+
require 'alexa_skills_ruby/json_objects/intent'
|
11
|
+
require 'alexa_skills_ruby/json_objects/base_request'
|
12
|
+
require 'alexa_skills_ruby/json_objects/intent_request'
|
13
|
+
require 'alexa_skills_ruby/json_objects/launch_request'
|
14
|
+
require 'alexa_skills_ruby/json_objects/session_ended_request'
|
15
|
+
require 'alexa_skills_ruby/json_objects/image'
|
16
|
+
require 'alexa_skills_ruby/json_objects/card'
|
17
|
+
require 'alexa_skills_ruby/json_objects/output_speech'
|
18
|
+
require 'alexa_skills_ruby/json_objects/reprompt'
|
19
|
+
require 'alexa_skills_ruby/json_objects/response'
|
20
|
+
require 'alexa_skills_ruby/json_objects/skills_request'
|
21
|
+
require 'alexa_skills_ruby/json_objects/skills_response'
|
22
|
+
require 'alexa_skills_ruby/errors'
|
23
|
+
require 'alexa_skills_ruby/handler'
|
24
|
+
|
25
|
+
module AlexaSkillsRuby
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module AlexaSkillsRuby
|
2
|
+
class Handler
|
3
|
+
include ActiveSupport::Callbacks
|
4
|
+
define_callbacks :authenticate, :session_start, :launch, :intent, :session_end
|
5
|
+
|
6
|
+
attr_reader :request, :session, :response
|
7
|
+
attr_accessor :application_id, :logger
|
8
|
+
|
9
|
+
def initialize(opts = {})
|
10
|
+
if opts[:application_id]
|
11
|
+
@application_id = opts[:application_id]
|
12
|
+
end
|
13
|
+
|
14
|
+
if opts[:logger]
|
15
|
+
@logger = opts[:logger]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def session_attributes
|
20
|
+
@session.attributes ||= {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def handle(request_json)
|
24
|
+
@skill_request = JsonObjects::SkillsRequest.new(MultiJson.load(request_json))
|
25
|
+
@skill_response = JsonObjects::SkillsResponse.new
|
26
|
+
|
27
|
+
@session = @skill_request.session
|
28
|
+
@request = @skill_request.request
|
29
|
+
@response = @skill_response.response
|
30
|
+
|
31
|
+
|
32
|
+
run_callbacks :authenticate do
|
33
|
+
if @application_id
|
34
|
+
if @application_id != session.application.application_id
|
35
|
+
raise InvalidApplicationId, "Invalid: [#{session.application.application_id}]"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
if session.new
|
41
|
+
run_callbacks :session_start
|
42
|
+
end
|
43
|
+
|
44
|
+
case request
|
45
|
+
when JsonObjects::LaunchRequest
|
46
|
+
run_callbacks :launch
|
47
|
+
when JsonObjects::IntentRequest
|
48
|
+
run_callbacks :intent
|
49
|
+
when JsonObjects::SessionEndedRequest
|
50
|
+
run_callbacks :session_end
|
51
|
+
end
|
52
|
+
|
53
|
+
if response.should_end_session
|
54
|
+
@skill_response.session_attributes = {}
|
55
|
+
else
|
56
|
+
@skill_response.session_attributes = session_attributes
|
57
|
+
end
|
58
|
+
|
59
|
+
MultiJson.dump(@skill_response.as_json)
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.on_authenticate(&block)
|
63
|
+
set_callback :authenticate, :before, block
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.on_session_start(&block)
|
67
|
+
set_callback :session_start, :before, block
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.on_launch(&block)
|
71
|
+
set_callback :launch, :before, block
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.on_session_end(&block)
|
75
|
+
set_callback :session_end, :before, block
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.on_intent(intent_name = nil, &block)
|
79
|
+
opts = {}
|
80
|
+
if intent_name
|
81
|
+
opts[:if] = -> { request.intent_name == intent_name }
|
82
|
+
end
|
83
|
+
set_callback :intent, :before, block, opts
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module AlexaSkillsRuby
|
2
|
+
class JsonObject
|
3
|
+
|
4
|
+
class_attribute :_json_object_properties
|
5
|
+
class_attribute :_properties
|
6
|
+
self._json_object_properties = {}
|
7
|
+
self._properties = []
|
8
|
+
|
9
|
+
def self.json_object_attribute(*args)
|
10
|
+
klass = args.pop
|
11
|
+
raise "Invalid arguments" unless klass && klass.is_a?(Class) && args.length > 0
|
12
|
+
|
13
|
+
args.compact.map { |a| a.to_sym }.each do |a|
|
14
|
+
attr_accessor a
|
15
|
+
self._json_object_properties[a.to_sym] = klass
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.attribute(*attrs)
|
20
|
+
attrs.compact.map { |a| a.to_sym }.each do |a|
|
21
|
+
attr_accessor a
|
22
|
+
self._properties << a
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class << self
|
27
|
+
alias_method :json_object_attributes, :json_object_attribute
|
28
|
+
alias_method :attributes, :attribute
|
29
|
+
end
|
30
|
+
|
31
|
+
# Copy properties on inheritance.
|
32
|
+
def self.inherited(subclass)
|
33
|
+
entities = _json_object_properties.dup
|
34
|
+
attrs = _properties.dup
|
35
|
+
subclass._json_object_properties = entities.each { |k, v| entities[k] = v.dup }
|
36
|
+
subclass._properties = attrs
|
37
|
+
super
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize(attrs = {})
|
41
|
+
populate_from_json(attrs)
|
42
|
+
end
|
43
|
+
|
44
|
+
def as_json(options = nil)
|
45
|
+
serialize_attributes(_properties + _json_object_properties.keys)
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_json(options = nil)
|
49
|
+
MultiJson.dump(as_json(options))
|
50
|
+
end
|
51
|
+
|
52
|
+
def populate_from_json(attrs)
|
53
|
+
return unless attrs
|
54
|
+
|
55
|
+
attrs.each do |k, v|
|
56
|
+
meth = "#{get_method_name(k)}=".to_sym
|
57
|
+
if self.respond_to? meth
|
58
|
+
if json_object_class = _json_object_properties[k.to_sym]
|
59
|
+
assign_json_object(meth, v, json_object_class)
|
60
|
+
else
|
61
|
+
self.send(meth, v)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def serialize_attributes(attrs)
|
68
|
+
json = {}
|
69
|
+
attrs.each do |k|
|
70
|
+
meth = k.to_sym
|
71
|
+
if self.respond_to?(meth)
|
72
|
+
if _json_object_properties[k.to_sym]
|
73
|
+
val = serialize_json_object(meth)
|
74
|
+
else
|
75
|
+
val = self.send(meth)
|
76
|
+
end
|
77
|
+
unless val.nil?
|
78
|
+
json[get_attribute_name(k)] = val
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
json
|
83
|
+
end
|
84
|
+
|
85
|
+
protected
|
86
|
+
|
87
|
+
def assign_json_object(assignment_method, value, klass)
|
88
|
+
|
89
|
+
if value.is_a? Array
|
90
|
+
data = value.map { |v| hydrate_entity(v, klass) }
|
91
|
+
else
|
92
|
+
data = hydrate_entity(value, klass)
|
93
|
+
end
|
94
|
+
|
95
|
+
self.send(assignment_method, data)
|
96
|
+
end
|
97
|
+
|
98
|
+
def hydrate_entity(json, klass)
|
99
|
+
klass.new(json)
|
100
|
+
end
|
101
|
+
|
102
|
+
def get_method_name(attr_name)
|
103
|
+
attr_name.to_s.gsub(/([a-z])([A-Z])([a-z]|^)/) { |m| "#{m[0]}_#{m[1].downcase}#{m[2]}" }
|
104
|
+
end
|
105
|
+
|
106
|
+
def get_attribute_name(meth_name)
|
107
|
+
meth_name.to_s.gsub(/([a-z])(_)([a-z])/) { |m| m[0] + m[2].upcase }
|
108
|
+
end
|
109
|
+
|
110
|
+
def serialize_json_object(method)
|
111
|
+
value = self.send(method)
|
112
|
+
case value
|
113
|
+
when nil
|
114
|
+
nil
|
115
|
+
when Array
|
116
|
+
value.map { |v| v.as_json }
|
117
|
+
else
|
118
|
+
value.as_json
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module AlexaSkillsRuby
|
2
|
+
module JsonObjects
|
3
|
+
class BaseRequest < JsonObject
|
4
|
+
attributes :type, :request_id, :timestamp
|
5
|
+
|
6
|
+
def self.new(*args, &block)
|
7
|
+
json = args.first
|
8
|
+
subclass = case
|
9
|
+
when self != BaseRequest
|
10
|
+
nil
|
11
|
+
when json.nil?
|
12
|
+
nil
|
13
|
+
when json['type'] == 'LaunchRequest'
|
14
|
+
LaunchRequest
|
15
|
+
when json['type'] == 'IntentRequest'
|
16
|
+
IntentRequest
|
17
|
+
when json['type'] == 'SessionEndedRequest'
|
18
|
+
SessionEndedRequest
|
19
|
+
else
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
|
23
|
+
if subclass
|
24
|
+
subclass.new(*args, &block)
|
25
|
+
else
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def intent_name
|
31
|
+
if self.is_a? IntentRequest
|
32
|
+
self.intent.name
|
33
|
+
else
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module AlexaSkillsRuby
|
2
|
+
module JsonObjects
|
3
|
+
class Card < JsonObject
|
4
|
+
attributes :type, :title, :content, :text
|
5
|
+
json_object_attributes :image, Image
|
6
|
+
|
7
|
+
def self.simple(title, content)
|
8
|
+
card = new
|
9
|
+
card.type = "Simple"
|
10
|
+
card.title = title
|
11
|
+
card.content = content
|
12
|
+
card
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module AlexaSkillsRuby
|
2
|
+
module JsonObjects
|
3
|
+
class OutputSpeech < JsonObject
|
4
|
+
attributes :type, :text, :ssml
|
5
|
+
|
6
|
+
def self.text(text)
|
7
|
+
os = new
|
8
|
+
os.text = text
|
9
|
+
os.type = 'PlainText'
|
10
|
+
os
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.ssml(ssml)
|
14
|
+
os = new
|
15
|
+
os.ssml = ssml
|
16
|
+
os.type = 'SSML'
|
17
|
+
os
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module AlexaSkillsRuby
|
2
|
+
module JsonObjects
|
3
|
+
class Response < JsonObject
|
4
|
+
attributes :should_end_session
|
5
|
+
json_object_attribute :output_speech, OutputSpeech
|
6
|
+
json_object_attribute :card, Card
|
7
|
+
json_object_attribute :reprompt, Reprompt
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
self.should_end_session = true
|
11
|
+
end
|
12
|
+
|
13
|
+
def set_output_speech_text(text)
|
14
|
+
self.output_speech = OutputSpeech.text(text)
|
15
|
+
end
|
16
|
+
|
17
|
+
def set_simple_card(title, content)
|
18
|
+
self.card = Card.simple(title, content)
|
19
|
+
end
|
20
|
+
|
21
|
+
def set_reprompt_speech_text(text)
|
22
|
+
os = OutputSpeech.text(text)
|
23
|
+
rp = Reprompt.new
|
24
|
+
rp.output_speech = os
|
25
|
+
self.reprompt = rp
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module AlexaSkillsRuby
|
2
|
+
module JsonObjects
|
3
|
+
class SkillsResponse < JsonObject
|
4
|
+
attributes :version, :session_attributes
|
5
|
+
json_object_attribute :response, Response
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
self.version = '1.0'
|
9
|
+
self.session_attributes = {}
|
10
|
+
self.response = JsonObjects::Response.new
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
{
|
2
|
+
"version": "1.0",
|
3
|
+
"session": {
|
4
|
+
"new": false,
|
5
|
+
"sessionId": "amzn1.echo-api.session.0000000-0000-0000-0000-00000000000",
|
6
|
+
"application": {
|
7
|
+
"applicationId": "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe"
|
8
|
+
},
|
9
|
+
"attributes": {
|
10
|
+
"supportedHoroscopePeriods": {
|
11
|
+
"daily": true,
|
12
|
+
"weekly": false,
|
13
|
+
"monthly": false
|
14
|
+
}
|
15
|
+
},
|
16
|
+
"user": {
|
17
|
+
"userId": "amzn1.account.AM3B00000000000000000000000"
|
18
|
+
}
|
19
|
+
},
|
20
|
+
"request": {
|
21
|
+
"type": "IntentRequest",
|
22
|
+
"requestId": "amzn1.echo-api.request.0000000-0000-0000-0000-00000000000",
|
23
|
+
"timestamp": "2015-05-13T12:34:56Z",
|
24
|
+
"intent": {
|
25
|
+
"name": "GetZodiacHoroscopeIntent",
|
26
|
+
"slots": {
|
27
|
+
"ZodiacSign": {
|
28
|
+
"name": "ZodiacSign",
|
29
|
+
"value": "virgo"
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
{
|
2
|
+
"version": "1.0",
|
3
|
+
"session": {
|
4
|
+
"new": true,
|
5
|
+
"sessionId": "amzn1.echo-api.session.0000000-0000-0000-0000-00000000000",
|
6
|
+
"application": {
|
7
|
+
"applicationId": "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe"
|
8
|
+
},
|
9
|
+
"attributes": {},
|
10
|
+
"user": {
|
11
|
+
"userId": "amzn1.account.AM3B00000000000000000000000"
|
12
|
+
}
|
13
|
+
},
|
14
|
+
"request": {
|
15
|
+
"type": "LaunchRequest",
|
16
|
+
"requestId": "amzn1.echo-api.request.0000000-0000-0000-0000-00000000000",
|
17
|
+
"timestamp": "2015-05-13T12:34:56Z"
|
18
|
+
}
|
19
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
{
|
2
|
+
"version": "1.0",
|
3
|
+
"sessionAttributes": {
|
4
|
+
"supportedHoriscopePeriods": {
|
5
|
+
"daily": true,
|
6
|
+
"weekly": false,
|
7
|
+
"monthly": false
|
8
|
+
}
|
9
|
+
},
|
10
|
+
"response": {
|
11
|
+
"outputSpeech": {
|
12
|
+
"type": "PlainText",
|
13
|
+
"text": "Today will provide you a new learning opportunity. Stick with it and the possibilities will be endless. Can I help you with anything else?"
|
14
|
+
},
|
15
|
+
"card": {
|
16
|
+
"type": "Simple",
|
17
|
+
"title": "Horoscope",
|
18
|
+
"content": "Today will provide you a new learning opportunity. Stick with it and the possibilities will be endless."
|
19
|
+
},
|
20
|
+
"reprompt": {
|
21
|
+
"outputSpeech": {
|
22
|
+
"type": "PlainText",
|
23
|
+
"text": "Can I help you with anything else?"
|
24
|
+
}
|
25
|
+
},
|
26
|
+
"shouldEndSession": false
|
27
|
+
}
|
28
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
{
|
2
|
+
"version": "1.0",
|
3
|
+
"session": {
|
4
|
+
"new": false,
|
5
|
+
"sessionId": "amzn1.echo-api.session.0000000-0000-0000-0000-00000000000",
|
6
|
+
"application": {
|
7
|
+
"applicationId": "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe"
|
8
|
+
},
|
9
|
+
"attributes": {
|
10
|
+
"supportedHoroscopePeriods": {
|
11
|
+
"daily": true,
|
12
|
+
"weekly": false,
|
13
|
+
"monthly": false
|
14
|
+
}
|
15
|
+
},
|
16
|
+
"user": {
|
17
|
+
"userId": "amzn1.account.AM3B00000000000000000000000"
|
18
|
+
}
|
19
|
+
},
|
20
|
+
"request": {
|
21
|
+
"type": "SessionEndedRequest",
|
22
|
+
"requestId": "amzn1.echo-api.request.0000000-0000-0000-0000-00000000000",
|
23
|
+
"timestamp": "2015-05-13T12:34:56Z",
|
24
|
+
"reason": "USER_INITIATED"
|
25
|
+
}
|
26
|
+
}
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'oj'
|
4
|
+
require 'rspec'
|
5
|
+
require File.expand_path('../../lib/alexa_skills_ruby', __FILE__)
|
6
|
+
|
7
|
+
MultiJson.use :oj
|
8
|
+
|
9
|
+
Dir[File.expand_path('../support/**/*', __FILE__)].each { |f| require f }
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
|
13
|
+
config.include FixtureSupport
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe AlexaSkillsRuby::Handler do
|
4
|
+
|
5
|
+
class TestHandler < AlexaSkillsRuby::Handler
|
6
|
+
|
7
|
+
attr_reader :auths, :intents, :launch, :ends, :starts
|
8
|
+
|
9
|
+
def initialize(*args)
|
10
|
+
super
|
11
|
+
@auths = []
|
12
|
+
@intents = []
|
13
|
+
@launch = []
|
14
|
+
@ends = []
|
15
|
+
@starts = []
|
16
|
+
end
|
17
|
+
|
18
|
+
on_session_start do
|
19
|
+
@starts << request
|
20
|
+
end
|
21
|
+
|
22
|
+
on_authenticate do
|
23
|
+
@auths << request
|
24
|
+
end
|
25
|
+
|
26
|
+
on_launch do
|
27
|
+
@launch << request
|
28
|
+
end
|
29
|
+
|
30
|
+
on_intent do
|
31
|
+
@intents << request
|
32
|
+
end
|
33
|
+
|
34
|
+
on_intent('special') do
|
35
|
+
@intents << request
|
36
|
+
end
|
37
|
+
|
38
|
+
on_session_end do
|
39
|
+
@ends << request
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
let(:handler) { TestHandler.new }
|
44
|
+
|
45
|
+
describe 'with a launch request' do
|
46
|
+
let(:request_json) { load_json 'example_launch.json' }
|
47
|
+
|
48
|
+
it 'fires the handlers' do
|
49
|
+
handler.handle(request_json)
|
50
|
+
|
51
|
+
expect(handler.auths.count).to eq 1
|
52
|
+
expect(handler.intents.count).to eq 0
|
53
|
+
expect(handler.ends.count).to eq 0
|
54
|
+
expect(handler.starts.count).to eq 1
|
55
|
+
expect(handler.launch.count).to eq 1
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'with an intent request' do
|
60
|
+
let(:request_json) { load_json 'example_intent.json' }
|
61
|
+
|
62
|
+
it 'fires the handlers' do
|
63
|
+
handler.handle(request_json)
|
64
|
+
|
65
|
+
expect(handler.auths.count).to eq 1
|
66
|
+
expect(handler.intents.count).to eq 1
|
67
|
+
expect(handler.ends.count).to eq 0
|
68
|
+
expect(handler.starts.count).to eq 0
|
69
|
+
expect(handler.launch.count).to eq 0
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'with a special intent request' do
|
74
|
+
let(:request_json) do
|
75
|
+
json = load_fixture 'example_intent.json'
|
76
|
+
json['request']['intent']['name'] = 'special'
|
77
|
+
Oj.dump(json)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'fires the handlers' do
|
81
|
+
handler.handle(request_json)
|
82
|
+
|
83
|
+
expect(handler.auths.count).to eq 1
|
84
|
+
expect(handler.intents.count).to eq 2
|
85
|
+
expect(handler.ends.count).to eq 0
|
86
|
+
expect(handler.starts.count).to eq 0
|
87
|
+
expect(handler.launch.count).to eq 0
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe 'with a session ended request' do
|
92
|
+
let(:request_json) { load_json 'example_session_ended.json' }
|
93
|
+
|
94
|
+
it 'fires the handlers' do
|
95
|
+
handler.handle(request_json)
|
96
|
+
|
97
|
+
expect(handler.auths.count).to eq 1
|
98
|
+
expect(handler.intents.count).to eq 0
|
99
|
+
expect(handler.ends.count).to eq 1
|
100
|
+
expect(handler.starts.count).to eq 0
|
101
|
+
expect(handler.launch.count).to eq 0
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe 'with an application_id set' do
|
106
|
+
|
107
|
+
let(:handler) { TestHandler.new({application_id: 'amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe'}) }
|
108
|
+
|
109
|
+
describe 'with a valid app id in request' do
|
110
|
+
let(:request_json) { load_json 'example_session_ended.json' }
|
111
|
+
|
112
|
+
it 'fires the handlers' do
|
113
|
+
handler.handle(request_json)
|
114
|
+
|
115
|
+
expect(handler.auths.count).to eq 1
|
116
|
+
expect(handler.intents.count).to eq 0
|
117
|
+
expect(handler.ends.count).to eq 1
|
118
|
+
expect(handler.starts.count).to eq 0
|
119
|
+
expect(handler.launch.count).to eq 0
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe 'with an invalid app id in request' do
|
124
|
+
let(:request_json) do
|
125
|
+
json = load_fixture 'example_intent.json'
|
126
|
+
json['session']['application']['applicationId'] = 'broke'
|
127
|
+
Oj.dump(json)
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'fires the handlers' do
|
131
|
+
expect { handler.handle(request_json) }.to raise_error AlexaSkillsRuby::InvalidApplicationId
|
132
|
+
|
133
|
+
expect(handler.auths.count).to eq 1
|
134
|
+
expect(handler.intents.count).to eq 0
|
135
|
+
expect(handler.ends.count).to eq 0
|
136
|
+
expect(handler.starts.count).to eq 0
|
137
|
+
expect(handler.launch.count).to eq 0
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe AlexaSkillsRuby::JsonObject do
|
4
|
+
|
5
|
+
class TestJsonObject < AlexaSkillsRuby::JsonObject
|
6
|
+
attributes :name, :id
|
7
|
+
json_object_attribute :attr1, AlexaSkillsRuby::JsonObjects::User
|
8
|
+
end
|
9
|
+
|
10
|
+
class ChildTestJsonObject < TestJsonObject
|
11
|
+
attribute :another_field
|
12
|
+
json_object_attribute :attr2, AlexaSkillsRuby::JsonObjects::User
|
13
|
+
end
|
14
|
+
|
15
|
+
class OtherTestJsonObject < AlexaSkillsRuby::JsonObject
|
16
|
+
json_object_attribute :attr3, AlexaSkillsRuby::JsonObjects::User
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '.json_object_attribute' do
|
20
|
+
|
21
|
+
it 'should keep separate lists for each type' do
|
22
|
+
expect(TestJsonObject._json_object_properties.keys).to contain_exactly :attr1
|
23
|
+
expect(ChildTestJsonObject._json_object_properties.keys).to contain_exactly :attr1, :attr2
|
24
|
+
expect(OtherTestJsonObject._json_object_properties.keys).to contain_exactly :attr3
|
25
|
+
|
26
|
+
expect(TestJsonObject._properties).to contain_exactly :name, :id
|
27
|
+
expect(ChildTestJsonObject._properties).to contain_exactly :name, :id, :another_field
|
28
|
+
expect(OtherTestJsonObject._properties.length).to eq 0
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'serialization' do
|
34
|
+
|
35
|
+
it 'serializes entities' do
|
36
|
+
json_object = TestJsonObject.new
|
37
|
+
json_object.attr1 = AlexaSkillsRuby::JsonObjects::User.new
|
38
|
+
json_object.attr1.user_id = 5
|
39
|
+
json_object.attr1.access_token = 'token'
|
40
|
+
json_object.name = 'name'
|
41
|
+
json_object.id = 1
|
42
|
+
|
43
|
+
json = json_object.as_json
|
44
|
+
expect(json).to eq({ 'attr1' => { 'userId' => 5, 'accessToken' => 'token'}, 'name' => 'name', 'id' => 1 })
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'deserialization' do
|
50
|
+
it 'populates the objects' do
|
51
|
+
json = { attr1: { id: 5, access_token: 'token'}, name: 'name', id: 1 }
|
52
|
+
json_object = TestJsonObject.new(json)
|
53
|
+
expect(json_object.name).to eq 'name'
|
54
|
+
expect(json_object.attr1).to be_a AlexaSkillsRuby::JsonObjects::User
|
55
|
+
expect(json_object.attr1.access_token).to eq 'token'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe AlexaSkillsRuby::JsonObjects::SkillsRequest do
|
4
|
+
|
5
|
+
let(:launch_request_json) do
|
6
|
+
load_fixture 'example_launch.json'
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:intent_request_json) do
|
10
|
+
load_fixture 'example_intent.json'
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:session_ended_request_json) do
|
14
|
+
load_fixture 'example_session_ended.json'
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'constructs a launch request' do
|
18
|
+
r = AlexaSkillsRuby::JsonObjects::SkillsRequest.new(launch_request_json)
|
19
|
+
expect(r).not_to be_nil
|
20
|
+
expect(r.version).to eq '1.0'
|
21
|
+
expect(r.session).to be_a AlexaSkillsRuby::JsonObjects::Session
|
22
|
+
expect(r.session.new).to eq true
|
23
|
+
expect(r.session.session_id).to eq 'amzn1.echo-api.session.0000000-0000-0000-0000-00000000000'
|
24
|
+
expect(r.session.application).to be_a AlexaSkillsRuby::JsonObjects::Application
|
25
|
+
expect(r.session.application.application_id).to eq 'amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe'
|
26
|
+
expect(r.session.attributes).to eq({})
|
27
|
+
expect(r.session.user).to be_a AlexaSkillsRuby::JsonObjects::User
|
28
|
+
expect(r.session.user.user_id).to eq 'amzn1.account.AM3B00000000000000000000000'
|
29
|
+
expect(r.request).to be_a AlexaSkillsRuby::JsonObjects::LaunchRequest
|
30
|
+
expect(r.request.type).to eq 'LaunchRequest'
|
31
|
+
expect(r.request.request_id).to eq 'amzn1.echo-api.request.0000000-0000-0000-0000-00000000000'
|
32
|
+
expect(r.request.timestamp).to eq '2015-05-13T12:34:56Z'
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'constructs an intent request' do
|
36
|
+
r = AlexaSkillsRuby::JsonObjects::SkillsRequest.new(intent_request_json)
|
37
|
+
expect(r.request).to be_a AlexaSkillsRuby::JsonObjects::IntentRequest
|
38
|
+
expect(r.request.type).to eq 'IntentRequest'
|
39
|
+
expect(r.request.request_id).to eq 'amzn1.echo-api.request.0000000-0000-0000-0000-00000000000'
|
40
|
+
expect(r.request.timestamp).to eq '2015-05-13T12:34:56Z'
|
41
|
+
expect(r.request.intent).to be_a AlexaSkillsRuby::JsonObjects::Intent
|
42
|
+
expect(r.request.intent.name).to eq 'GetZodiacHoroscopeIntent'
|
43
|
+
expect(r.request.intent.slots).to be_a Hash
|
44
|
+
expect(r.request.intent.slots['ZodiacSign']).to eq('virgo')
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'constructs a session ended request' do
|
48
|
+
r = AlexaSkillsRuby::JsonObjects::SkillsRequest.new(session_ended_request_json)
|
49
|
+
expect(r.request).to be_a AlexaSkillsRuby::JsonObjects::SessionEndedRequest
|
50
|
+
expect(r.request.type).to eq 'SessionEndedRequest'
|
51
|
+
expect(r.request.request_id).to eq 'amzn1.echo-api.request.0000000-0000-0000-0000-00000000000'
|
52
|
+
expect(r.request.timestamp).to eq '2015-05-13T12:34:56Z'
|
53
|
+
expect(r.request.reason).to eq 'USER_INITIATED'
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe AlexaSkillsRuby::JsonObjects::SkillsResponse do
|
4
|
+
|
5
|
+
let(:response_json) do
|
6
|
+
{
|
7
|
+
'version' => "1.0",
|
8
|
+
'sessionAttributes' => {
|
9
|
+
'supportedHoriscopePeriods' => {
|
10
|
+
'daily' => true,
|
11
|
+
'weekly' => false,
|
12
|
+
'monthly' => false
|
13
|
+
}
|
14
|
+
},
|
15
|
+
'response' => {
|
16
|
+
'outputSpeech' => {
|
17
|
+
'type' => "PlainText",
|
18
|
+
'text' => "Today will provide you a new learning opportunity. Stick with it and the possibilities will be endless. Can I help you with anything else?"
|
19
|
+
},
|
20
|
+
'card' => {
|
21
|
+
'type' => "Simple",
|
22
|
+
'title' => "Horoscope",
|
23
|
+
'content' => "Today will provide you a new learning opportunity. Stick with it and the possibilities will be endless."
|
24
|
+
},
|
25
|
+
'reprompt' => {
|
26
|
+
'outputSpeech' => {
|
27
|
+
'type' => "PlainText",
|
28
|
+
'text' => "Can I help you with anything else?"
|
29
|
+
}
|
30
|
+
},
|
31
|
+
'shouldEndSession' => false
|
32
|
+
}
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'generates example json' do
|
37
|
+
sr = AlexaSkillsRuby::JsonObjects::SkillsResponse.new
|
38
|
+
r = sr.response
|
39
|
+
sr.session_attributes = {'supportedHoriscopePeriods' => {'daily' => true, 'weekly' => false, 'monthly' => false}}
|
40
|
+
r.set_output_speech_text("Today will provide you a new learning opportunity. Stick with it and the possibilities will be endless. Can I help you with anything else?")
|
41
|
+
r.set_simple_card('Horoscope', 'Today will provide you a new learning opportunity. Stick with it and the possibilities will be endless.')
|
42
|
+
r.set_reprompt_speech_text('Can I help you with anything else?')
|
43
|
+
r.should_end_session = false
|
44
|
+
|
45
|
+
expect(sr.as_json).to eq response_json
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
metadata
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: alexa_skills_ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.5
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dan Elbert
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-04-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: multi_json
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 3.4.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 3.4.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: oj
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 2.10.2
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 2.10.2
|
97
|
+
description:
|
98
|
+
email:
|
99
|
+
- dan.elbert@gmail.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- Gemfile
|
106
|
+
- LICENSE
|
107
|
+
- README.md
|
108
|
+
- Rakefile
|
109
|
+
- alexa_skills_ruby.gemspec
|
110
|
+
- lib/alexa_skills_ruby.rb
|
111
|
+
- lib/alexa_skills_ruby/errors.rb
|
112
|
+
- lib/alexa_skills_ruby/handler.rb
|
113
|
+
- lib/alexa_skills_ruby/json_object.rb
|
114
|
+
- lib/alexa_skills_ruby/json_objects/application.rb
|
115
|
+
- lib/alexa_skills_ruby/json_objects/base_request.rb
|
116
|
+
- lib/alexa_skills_ruby/json_objects/card.rb
|
117
|
+
- lib/alexa_skills_ruby/json_objects/image.rb
|
118
|
+
- lib/alexa_skills_ruby/json_objects/intent.rb
|
119
|
+
- lib/alexa_skills_ruby/json_objects/intent_request.rb
|
120
|
+
- lib/alexa_skills_ruby/json_objects/launch_request.rb
|
121
|
+
- lib/alexa_skills_ruby/json_objects/output_speech.rb
|
122
|
+
- lib/alexa_skills_ruby/json_objects/reprompt.rb
|
123
|
+
- lib/alexa_skills_ruby/json_objects/response.rb
|
124
|
+
- lib/alexa_skills_ruby/json_objects/session.rb
|
125
|
+
- lib/alexa_skills_ruby/json_objects/session_ended_request.rb
|
126
|
+
- lib/alexa_skills_ruby/json_objects/skills_request.rb
|
127
|
+
- lib/alexa_skills_ruby/json_objects/skills_response.rb
|
128
|
+
- lib/alexa_skills_ruby/json_objects/user.rb
|
129
|
+
- lib/alexa_skills_ruby/version.rb
|
130
|
+
- spec/fixtures/example_intent.json
|
131
|
+
- spec/fixtures/example_launch.json
|
132
|
+
- spec/fixtures/example_response.json
|
133
|
+
- spec/fixtures/example_session_ended.json
|
134
|
+
- spec/spec_helper.rb
|
135
|
+
- spec/support/fixture_support.rb
|
136
|
+
- spec/unit/handler_spec.rb
|
137
|
+
- spec/unit/json_object_spec.rb
|
138
|
+
- spec/unit/json_objects/skills_request_spec.rb
|
139
|
+
- spec/unit/json_objects/skills_response_spec.rb
|
140
|
+
homepage: https://github.com/DanElbert/alexa_skills_ruby
|
141
|
+
licenses: []
|
142
|
+
metadata: {}
|
143
|
+
post_install_message:
|
144
|
+
rdoc_options: []
|
145
|
+
require_paths:
|
146
|
+
- lib
|
147
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
|
+
requirements:
|
154
|
+
- - ">="
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: '0'
|
157
|
+
requirements: []
|
158
|
+
rubyforge_project:
|
159
|
+
rubygems_version: 2.4.6
|
160
|
+
signing_key:
|
161
|
+
specification_version: 4
|
162
|
+
summary: Simple library to interface with the Alexa Skills Kit
|
163
|
+
test_files:
|
164
|
+
- spec/fixtures/example_intent.json
|
165
|
+
- spec/fixtures/example_launch.json
|
166
|
+
- spec/fixtures/example_response.json
|
167
|
+
- spec/fixtures/example_session_ended.json
|
168
|
+
- spec/spec_helper.rb
|
169
|
+
- spec/support/fixture_support.rb
|
170
|
+
- spec/unit/handler_spec.rb
|
171
|
+
- spec/unit/json_object_spec.rb
|
172
|
+
- spec/unit/json_objects/skills_request_spec.rb
|
173
|
+
- spec/unit/json_objects/skills_response_spec.rb
|