alexa_web_service 0.0.6 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3430dcd433c560a334840529c3ecb341836158d9
4
- data.tar.gz: a58146e5d3509a760883f277e4ae8733d70b7f19
3
+ metadata.gz: 4e77c95bba2bc9c56617f050c1579f572e76450c
4
+ data.tar.gz: 04ed856e3976cc87dcc15957bc27a4101c032fe1
5
5
  SHA512:
6
- metadata.gz: ac7eb3ef3827e29692f5fad90e08df2a0ed7e533dd5f355dc5e8a27ae669371df12df02cdd5f1234025df9335abf3e26f583009af357ac11920b3cfa4bef8739
7
- data.tar.gz: fd580581d53ba5632d11ec9aee5116623e6947666cd47451301e9d957e3d666d5a7e189830c87ccbf26632f44f54738153309e1640bfa63f380b5f0f8cbdabf5
6
+ metadata.gz: a6d032a7f83d9a97043165a8601cac3781280d22b37822a816597f19ef9b5136dfebfc7a7bebc1aad7a6447c0b50d488eed899bee629058e78f7e064f0420d4f
7
+ data.tar.gz: 460410d8ae38d6b3eddfdf90f9c58c64f6045f1344f8cbad40a93b7914a180349808b21484f9a414e437f9ad60dbcad8f11459e429c11dbb99adc58d3224434e
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in alexa_web_service.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,41 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ alexa_web_service (1.0.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.2.5)
10
+ httparty (0.15.7)
11
+ multi_xml (>= 0.5.2)
12
+ json (2.1.0)
13
+ multi_xml (0.6.0)
14
+ rake (10.5.0)
15
+ rspec (3.5.0)
16
+ rspec-core (~> 3.5.0)
17
+ rspec-expectations (~> 3.5.0)
18
+ rspec-mocks (~> 3.5.0)
19
+ rspec-core (3.5.2)
20
+ rspec-support (~> 3.5.0)
21
+ rspec-expectations (3.5.0)
22
+ diff-lcs (>= 1.2.0, < 2.0)
23
+ rspec-support (~> 3.5.0)
24
+ rspec-mocks (3.5.0)
25
+ diff-lcs (>= 1.2.0, < 2.0)
26
+ rspec-support (~> 3.5.0)
27
+ rspec-support (3.5.0)
28
+
29
+ PLATFORMS
30
+ ruby
31
+
32
+ DEPENDENCIES
33
+ alexa_web_service!
34
+ bundler (~> 1.15)
35
+ httparty (~> 0.15.7)
36
+ json (~> 2.1, >= 2.1.0)
37
+ rake (~> 10.0)
38
+ rspec (~> 3.0)
39
+
40
+ BUNDLED WITH
41
+ 1.16.1
data/README.md ADDED
@@ -0,0 +1,235 @@
1
+ # AlexaWebService
2
+
3
+ Framework for building an Alexa skill.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'alexa_web_service'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install alexa_web_service
20
+
21
+ ## Usage ##
22
+
23
+ The Alexa Web Service gem handles the JSON requests and responses that constitute an Alexa "Skill."
24
+ For general information on creating an Alexa skill as a web service, look here:
25
+ https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interface-reference#Introduction
26
+
27
+ Alexa will send your web service JSON in an HTTP POST request, like so:
28
+
29
+ ````Ruby
30
+ {
31
+ "session": {
32
+ "sessionId": "SessionId.abc12d34-12ab-1abc-111-a12c3456d7ef9",
33
+ "application": {
34
+ "applicationId": "amzn1.echo-sdk-ams.app.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
35
+ },
36
+ "attributes": {},
37
+ "user": {
38
+ "userId": "amzn1.account.AHHLP1234ABC5DEFG6HIJK7XLMN"
39
+ },
40
+ "new": true
41
+ },
42
+ "request": {
43
+ "type": "LaunchRequest",
44
+ "requestId": "EdwRequestId.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
45
+ "timestamp": "2016-06-17T21:07:57Z",
46
+ "locale": "en-US"
47
+ },
48
+ "version": "1.0"
49
+ }
50
+ ````
51
+
52
+ #### Verify: Verify the Alexa request ####
53
+
54
+ The Alexa Web Service framework will automatically verify that the request comes from Amazon, as outlined [here](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/developing-an-alexa-skill-as-a-web-service)
55
+
56
+ The AlexaVerify class takes two parameters: the request body sent by the client, and the raw environment hash.
57
+ So if you're setting up a Sinatra server, you can verify the request like so:
58
+
59
+ ````Ruby
60
+ # If the request body has been read, like in the Eight Ball example,
61
+ # you need to rewind it.
62
+ request.body.rewind
63
+
64
+ # Verify the request.
65
+ verified = AlexaWebService::Verify.new(request.env, request.body.read).verify_request
66
+ halt 400, "#{verified}" unless verified == "OK"
67
+ ````
68
+
69
+ #### Request: Handling the request from Alexa ####
70
+
71
+ Create an instance of the AlexaRequest class to provide some convenience methods for handling the JSON request:
72
+
73
+ ````Ruby
74
+ @echo_request = AlexaWebService::Request.new(request_json)
75
+
76
+ @echo_request.intent_name
77
+ @echo_request.slots
78
+ @echo_request.slots.myslot
79
+ @echo_request.launch_request?
80
+ @echo_request.intent_request?
81
+ @echo_request.session_ended_request?
82
+ @echo_request.session_new?
83
+ ````
84
+
85
+ Your skill provides different responses (see next section) depending on the the type/name/slot values of the request:
86
+
87
+ ````Ruby
88
+ if @echo_request.launch_request
89
+ # have alexa say hello
90
+ elsif @echo_request.intent_name == "InformationRequest"
91
+ # ask use for what kind of information she wants
92
+ elsif @echo_request.slots.time
93
+ # tell user the time
94
+ end
95
+ ````
96
+
97
+ (Take a look at eight_ball.rb for some further examples.)
98
+
99
+
100
+ #### Response: Respond to Alexa requests ####
101
+
102
+ The AlexaResponse class generates the proper JSON to make Alexa responses.
103
+
104
+ Create a new response object:
105
+
106
+ ````response = AlexaWebService::Response.new````
107
+
108
+ Then, define the response attributes:
109
+
110
+ ````Ruby
111
+ response.end_session = true
112
+ response.spoken_response = "This is what Alexa will say to you"
113
+ response.reprompt_text = "This is what she'll say if she doesn't hear your response the first time."
114
+ ````
115
+
116
+ You can then send the response back to Alexa with the following command:
117
+
118
+
119
+ ````Ruby
120
+ response.without_card.to_json
121
+ ````
122
+
123
+ So, putting the AlexaRequest and AlexaResponse together:
124
+
125
+ ````Ruby
126
+ response = AlexaWebService::Response.new
127
+
128
+ if @echo_request.launch_request
129
+ response.spoken_response = "Hello user"
130
+ response.end_session = true
131
+ end
132
+
133
+ response.without_card.to_json
134
+ ````
135
+
136
+ You can use [SSML](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference):
137
+
138
+ ````Ruby
139
+ response.speech_type = "SSML"
140
+ response.text_type = "ssml"
141
+ response.spoken_response = "<speak>Here is a word spelled out: <say-as interpret-as="spell-out">hello</say-as></speak>"
142
+ ````
143
+
144
+ Alexa uses a "session attribute" to persist data within a session. (It's the empty "attributes" hash in the sample JSON request above.) The #add_attribute adds key:value pairs to that attributes hash.
145
+
146
+ ````Ruby
147
+ response.add_attribute("favorite_color", "blue" )
148
+ ````
149
+ ### Adding a Directive ###
150
+ AlexaWebService supports directives: [hint and display directives](https://developer.amazon.com/docs/custom-skills/display-interface-reference.html) (for Alexa devices with screens), and [progresssive response](https://developer.amazon.com/docs/custom-skills/send-the-user-a-progressive-response.html). They work a little differently.
151
+
152
+ *Display Directive*
153
+ Please see the Amazon docs. Display Directives are a bit involved.
154
+ First, create the directive:
155
+ ````ruby
156
+ display = AlexaWebService::DisplayDirective.new(
157
+ type: "Body Template Type", token: "Your Token", title: "Your Title"
158
+ )
159
+ display.add_text(primary_text: "first text", secondary_text: "second_text", tertiary_text: "third text")
160
+ display.add_background_image("title", url)
161
+ display.add__image("title", url)
162
+ ````
163
+ then, add it to your response:
164
+ ````
165
+ response.add_directive(display.directive)
166
+ ````
167
+ *Hint Directive*
168
+ ````
169
+ hint = AlexaWebService::HintDirective.new("Buy low, sell high!")
170
+ response.add_directive(hint.directive)
171
+ ````
172
+ *Progressive Response*
173
+ These are a bit different than other directives. They are not sent with your response, but are sent before. They take two parameters, the entire request object, and the text you'd like Alexa to speak.
174
+ ````
175
+ progressive_response = AlexaWebService::ProgressiveResponse.new(request, "Hang on, looking up information.")
176
+ ````
177
+ Then send it....
178
+ ````
179
+ progressive_response.post
180
+ ````
181
+
182
+
183
+ ### Sending a Card ###
184
+
185
+ You can also [send a card](https://developer.amazon.com/docs/custom-skills/include-a-card-in-your-skills-response.html) to the Alexa app:
186
+ AlexaWebService supports four kinds of cards:
187
+ - Plain Text
188
+ - Image
189
+ - Linking
190
+ - Permissions
191
+
192
+ First, create a card:
193
+ ````
194
+ card = AlexaWebService::Card.new
195
+ ````
196
+
197
+ Then add the card attributes you want (text, image, or permissions if sending a permissions card):
198
+ ````Ruby
199
+ card.title = "My Alexa Card"
200
+ card.content "Formating is really limited to: \nline breaks"
201
+ card.small_image = "https://your_small_image_url.jpg"
202
+ card.large_image = "https://your_large_image_url.jpg"
203
+ ````
204
+ Finally, add the card to your response, specifying the kind of card you created:
205
+ ````
206
+ response.add_card(card.with_image)
207
+ ````
208
+ other possibilities:
209
+ ````
210
+ # text only
211
+ response.add_card(card.with_text)
212
+
213
+ # permissions
214
+ response.add_card(card.with_permissions)
215
+ ````
216
+ If you create a skill that uses [account linking](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/linking-an-alexa-user-with-a-user-in-your-system)
217
+ ````
218
+ # linking
219
+ response.add_card(card.linking)
220
+ ````
221
+ Finally, post your response
222
+
223
+ ````
224
+ response.post
225
+ ````
226
+
227
+
228
+ ## Contributing
229
+
230
+ 1. Fork it ( https://github.com/[my-github-username]/alexa_web_service/fork )
231
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
232
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
233
+ 4. Push to the branch (`git push origin my-new-feature`)
234
+ 5. Create a new Pull Request
235
+
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
@@ -0,0 +1,39 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "alexa_web_service/version"
5
+
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "alexa_web_service"
9
+ spec.version = AlexaWebService::VERSION
10
+ spec.authors = ["sarkonovich"]
11
+ spec.email = ["arkonovs @ reed. edu"]
12
+
13
+ spec.summary = "A framework to handle the JSON request/responses for an Alexa skill"
14
+ spec.description = "A framework to handle and verify the JSON request/responses for an Alexa skill"
15
+ spec.homepage = "https://github.com/sarkonovich/Alexa-Web-Service"
16
+ spec.license = 'MIT'
17
+
18
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
19
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
20
+ # if spec.respond_to?(:metadata)
21
+ # spec.metadata["allowed_push_host"] = "http://mygemserver.com"
22
+ # else
23
+ # raise "RubyGems 2.0 or newer is required to protect against " \
24
+ # "public gem pushes."
25
+ # end
26
+
27
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
28
+ f.match(%r{^(test|spec|features)/})
29
+ end
30
+ spec.bindir = "exe"
31
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
+ spec.require_paths = ["lib"]
33
+
34
+ spec.add_development_dependency "bundler", "~> 1.15"
35
+ spec.add_development_dependency "rake", "~> 10.0"
36
+ spec.add_development_dependency "rspec", "~> 3.0"
37
+ spec.add_development_dependency "httparty", "~> 0.15.7"
38
+ spec.add_development_dependency "json", '~> 2.1', '>= 2.1.0'
39
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "alexa_web_service"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -1,7 +1,10 @@
1
- require 'alexa_web_service/version'
2
- require 'alexa_web_service/alexa_response'
3
- require 'alexa_web_service/alexa_request'
4
- require 'alexa_web_service/alexa_verify'
1
+ require_relative 'alexa_web_service/display_directive'
2
+ require_relative 'alexa_web_service/hint_directive'
3
+ require_relative 'alexa_web_service/progressive_response'
4
+ require_relative 'alexa_web_service/request'
5
+ require_relative 'alexa_web_service/response'
6
+ require_relative 'alexa_web_service/verify'
7
+ require_relative 'alexa_web_service/card'
5
8
 
6
9
  module AlexaWebService
7
10
  end
@@ -0,0 +1,54 @@
1
+ module AlexaWebService
2
+ class Card
3
+ attr_accessor :title, :content, :small_image, :large_image, :permissions
4
+
5
+ def initialize(type = 'text_card')
6
+ @title = ''
7
+ @content = ''
8
+ @small_image = nil
9
+ @large_image = nil
10
+ @type = type
11
+ @permissions = []
12
+ end
13
+
14
+ def with_image
15
+ {
16
+ "type": "Standard",
17
+ "title": title,
18
+ "text": content,
19
+ "image": {
20
+ "smallImageUrl": small_image,
21
+ "largeImageUrl": large_image
22
+ }
23
+ }
24
+ end
25
+
26
+ def with_text
27
+ {
28
+ "type": "Simple",
29
+ "title": title,
30
+ "content": content
31
+ }
32
+ end
33
+
34
+ def linking
35
+ {"type": "LinkAccount"}
36
+ end
37
+
38
+ # Will only return permissions requested in skill configuration
39
+ # Possible values for permissions:
40
+ # write for notifications: "write::alexa:devices:all:notifications:standard"
41
+ # read for full address: "read::alexa:device:all:address"
42
+ # read for restricted address: "read::alexa:device:all:address:country_and_postal_code"
43
+
44
+ def add_permission(permission)
45
+ self.permissions << permission
46
+ end
47
+
48
+ def with_permission
49
+ {
50
+ "type": "AskForPermissionsConsent", "permissions": permissions
51
+ }
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,73 @@
1
+
2
+ module AlexaWebService
3
+ class DisplayDirective
4
+ attr_accessor :directive
5
+
6
+ def initialize(type: "BodyTemplate1", token: "", back_button: "VISIBLE", title: "")
7
+ @directive = {
8
+ "type": "Display.RenderTemplate",
9
+ "template": {
10
+ "type": type,
11
+ "token": token,
12
+ "backButton": back_button,
13
+ "backgroundImage": image_object,
14
+ "title": title,
15
+ "image": image_object,
16
+ "textContent": {}
17
+ }
18
+ }
19
+ end
20
+
21
+ def image_object(content_description = '', url = '', size = 'X_SMALL')
22
+ {
23
+ "contentDescription": content_description,
24
+ "sources": [
25
+ {
26
+ "url": url,
27
+ "size": size
28
+ }
29
+ ]
30
+ }
31
+ end
32
+
33
+ def add_image(content_description, url, size = 'X_SMALL')
34
+ @directive[:template][:image] = image_object(content_description, url, size = 'X_SMALL')
35
+ end
36
+
37
+ def add_background_image(content_description, url, size = 'X_SMALL')
38
+ @directive[:template][:backgroundImage] = image_object(content_description, url, size = 'X_SMALL')
39
+ end
40
+
41
+ def text_object(primary_text: nil, secondary_text: nil, tertiary_text: nil)
42
+ {
43
+ "primaryText": {
44
+ "text": primary_text,
45
+ "type": "RichText"
46
+ },
47
+ "secondaryText": {
48
+ "text": secondary_text,
49
+ "type": "RichText"
50
+ },
51
+ "tertiaryText": {
52
+ "text": tertiary_text,
53
+ "type": "RichText"
54
+ }
55
+ }
56
+ end
57
+
58
+ def add_text(primary_text:, secondary_text: nil, tertiary_text: nil)
59
+ @directive[:template][:textContent] = text_object(primary_text: primary_text, secondary_text: secondary_text, tertiary_text: tertiary_text)
60
+ end
61
+
62
+ # To create Show lists, first create image and text objects and then add show list item.
63
+ def add_list_item(token: '', image_object: {}, text_object: {})
64
+ item = {
65
+ "token": token,
66
+ "image": image_object,
67
+ "textContent": text_object
68
+ }
69
+ @directive[:template][:listItems] ||= []
70
+ @directive[:template][:listItems] << item
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,15 @@
1
+ module AlexaWebService
2
+ class HintDirective
3
+ attr_accessor :directive
4
+
5
+ def initialize(hint)
6
+ @directive = {
7
+ "type": "Hint",
8
+ "hint": {
9
+ "type": "PlainText",
10
+ "text": hint
11
+ }
12
+ }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,39 @@
1
+ require 'httparty'
2
+
3
+ module AlexaWebService
4
+ class ProgressiveResponse
5
+ attr_accessor :speech
6
+ attr_reader :directive, :request
7
+
8
+ def initialize(request, speech)
9
+ @request = request
10
+ @speech = speech
11
+ @directive = {
12
+ "header"=> {
13
+ "requestId"=>request.request_id
14
+ },
15
+ "directive"=> {
16
+ "type"=>"VoicePlayer.Speak",
17
+ "speech"=>speech
18
+ }
19
+ }
20
+ end
21
+
22
+ def url
23
+ if request.api_endpoint
24
+ request.api_endpoint + "/v1/directives"
25
+ end
26
+ end
27
+
28
+ def headers
29
+ {
30
+ "Authorization" => "Bearer #{request.api_access_token}",
31
+ "Content-Type" => "application/json"
32
+ }
33
+ end
34
+
35
+ def post
36
+ HTTParty.post(url, :headers=>headers, :body=>self.directive.to_json)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,80 @@
1
+ module AlexaWebService
2
+ class Request
3
+ attr_reader :request_hash, :api_access_token, :api_endpoint, :device_id,
4
+ :request_id, :request_type, :timestamp, :session_new, :user_id,
5
+ :access_token, :application_id, :intent_name, :slots
6
+
7
+ attr_accessor :attributes
8
+
9
+ def initialize(request_hash)
10
+ @request_hash = request_hash
11
+ @api_access_token = request_hash["context"]["System"]["apiAccessToken"]
12
+ @api_endpoint = request_hash["context"]["System"]["apiEndpoint"]
13
+ @device_id = request_hash["context"]["System"]["device"]["deviceId"]
14
+ @request_id = request_hash["request"]["requestId"]
15
+ @request_type = request_hash["request"]["type"]
16
+ @timestamp = request_hash["request"]["timestamp"]
17
+ @session_new = request_hash["session"]["new"]
18
+ @user_id = request_hash["session"]["user"]["userId"]
19
+ @access_token = request_hash["session"]["user"]["accessToken"]
20
+ @application_id = request_hash["session"]["application"]["applicationId"]
21
+ @intent_name = get_intent_name
22
+ @slots = get_slots
23
+ @attributes = get_attributes
24
+ end
25
+
26
+ def filled_slots
27
+ @slots.select { |slot| slot != nil} rescue []
28
+ end
29
+
30
+ def intent_request?
31
+ request_type == "IntentRequest"
32
+ end
33
+
34
+ def launch_request?
35
+ request_type == "LaunchRequest"
36
+ end
37
+
38
+ def slot_hash
39
+ if request_hash["request"]["intent"]
40
+ request_hash["request"]["intent"]["slots"]
41
+ end
42
+ end
43
+
44
+ def session_ended_request?
45
+ request_type == "SessionEndedRequest"
46
+ end
47
+
48
+ def session_new?
49
+ session_new
50
+ end
51
+
52
+
53
+ private
54
+ def get_intent_name
55
+ if request_hash["request"]["intent"]
56
+ request_hash["request"]["intent"]["name"]
57
+ end
58
+ end
59
+
60
+ def get_slots
61
+ if request_hash["request"]["intent"]
62
+ build_struct(request_hash["request"]["intent"]["slots"])
63
+ end
64
+ end
65
+
66
+ def get_attributes
67
+ request_hash["session"]["attributes"] ? request_hash["session"]["attributes"] : {}
68
+ end
69
+
70
+ def build_struct(hash)
71
+ if hash.nil? || hash.empty?
72
+ nil
73
+ else
74
+ slot_names = hash.keys.map {|k| k.to_sym.downcase }
75
+ slot_values = hash.values.map { |v| v["value"] }
76
+ Struct.new(*slot_names).new(*slot_values)
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,52 @@
1
+ module AlexaWebService
2
+ class Response
3
+ attr_accessor :session_attributes, :spoken_response, :card,
4
+ :reprompt_text, :end_session, :speech_type,
5
+ :text_type, :directives
6
+
7
+ def initialize
8
+ @session_attributes = {}
9
+ @speech_type = "PlainText"
10
+ @spoken_response = ''
11
+ @reprompt_text = ''
12
+ @text_type = "text"
13
+ @end_session = 'true'
14
+ @card = nil
15
+ @directives = []
16
+ end
17
+
18
+ def add_attribute(key, value)
19
+ @session_attributes.merge!(key => value)
20
+ end
21
+
22
+ def add_directive(directive)
23
+ self.directives << directive if $display_support == true
24
+ end
25
+
26
+ def add_card(card)
27
+ self.card = card
28
+ end
29
+
30
+ def post
31
+ {
32
+ "version": "1.0",
33
+ "sessionAttributes": @session_attributes,
34
+ "response": {
35
+ "outputSpeech": {
36
+ "type": speech_type,
37
+ "#{text_type}": spoken_response
38
+ },
39
+ "card": card,
40
+ "reprompt": {
41
+ "outputSpeech": {
42
+ "type": speech_type,
43
+ "text": reprompt_text
44
+ }
45
+ },
46
+ "directives": @directives,
47
+ "shouldEndSession": end_session
48
+ }
49
+ }.to_json
50
+ end
51
+ end
52
+ end
@@ -1,5 +1,5 @@
1
1
  module AlexaWebService
2
- class AlexaVerify
2
+ class Verify
3
3
 
4
4
  def initialize(request_env, request_body)
5
5
  @request_body = request_body
@@ -1,3 +1,3 @@
1
1
  module AlexaWebService
2
- VERSION = "0.0.6"
2
+ VERSION = "1.0.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alexa_web_service
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - sarkonovich
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-07-07 00:00:00.000000000 Z
11
+ date: 2018-02-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.10'
19
+ version: '1.15'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.10'
26
+ version: '1.15'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,40 +38,54 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: httparty
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: 0.13.5
48
- type: :runtime
61
+ version: 0.15.7
62
+ type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: 0.13.5
68
+ version: 0.15.7
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: json
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - "~>"
60
74
  - !ruby/object:Gem::Version
61
- version: '1.8'
75
+ version: '2.1'
62
76
  - - ">="
63
77
  - !ruby/object:Gem::Version
64
- version: 1.8.3
65
- type: :runtime
78
+ version: 2.1.0
79
+ type: :development
66
80
  prerelease: false
67
81
  version_requirements: !ruby/object:Gem::Requirement
68
82
  requirements:
69
83
  - - "~>"
70
84
  - !ruby/object:Gem::Version
71
- version: '1.8'
85
+ version: '2.1'
72
86
  - - ">="
73
87
  - !ruby/object:Gem::Version
74
- version: 1.8.3
88
+ version: 2.1.0
75
89
  description: A framework to handle and verify the JSON request/responses for an Alexa
76
90
  skill
77
91
  email:
@@ -80,10 +94,22 @@ executables: []
80
94
  extensions: []
81
95
  extra_rdoc_files: []
82
96
  files:
97
+ - ".gitignore"
98
+ - Gemfile
99
+ - Gemfile.lock
100
+ - README.md
101
+ - Rakefile
102
+ - alexa_web_service.gemspec
103
+ - bin/console
104
+ - bin/setup
83
105
  - lib/alexa_web_service.rb
84
- - lib/alexa_web_service/alexa_request.rb
85
- - lib/alexa_web_service/alexa_response.rb
86
- - lib/alexa_web_service/alexa_verify.rb
106
+ - lib/alexa_web_service/card.rb
107
+ - lib/alexa_web_service/display_directive.rb
108
+ - lib/alexa_web_service/hint_directive.rb
109
+ - lib/alexa_web_service/progressive_response.rb
110
+ - lib/alexa_web_service/request.rb
111
+ - lib/alexa_web_service/response.rb
112
+ - lib/alexa_web_service/verify.rb
87
113
  - lib/alexa_web_service/version.rb
88
114
  homepage: https://github.com/sarkonovich/Alexa-Web-Service
89
115
  licenses:
@@ -97,7 +123,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
97
123
  requirements:
98
124
  - - ">="
99
125
  - !ruby/object:Gem::Version
100
- version: 2.0.0
126
+ version: '0'
101
127
  required_rubygems_version: !ruby/object:Gem::Requirement
102
128
  requirements:
103
129
  - - ">="
@@ -1,54 +0,0 @@
1
- module AlexaWebService
2
- class AlexaRequest
3
- attr_reader :intent_name, :slots, :timestamp, :request_type, :session_new, :user_id, :access_token, :application_id
4
- attr_accessor :attributes
5
- alias :session_new? :session_new
6
-
7
- def initialize(response_hash)
8
- session = response_hash["session"]
9
- request = response_hash["request"]
10
- if session
11
- @attributes = session["attributes"] ? session["attributes"] : {}
12
- @user_id = session["user"]["userId"] if session["user"]
13
- @access_token = session["user"]["accessToken"] if session["user"]
14
- @application_id = session["application"]["applicationId"] if session["application"]
15
- end
16
-
17
- if request
18
- @request_type = request["type"]
19
- @timestamp = request["timestamp"]
20
- @session_new = request["new"]
21
-
22
- if request["intent"]
23
- @intent_name = request["intent"]["name"] if request["intent"]
24
- @slots = build_struct(request["intent"]["slots"]) if request["intent"]
25
- end
26
- end
27
- end
28
-
29
- def filled_slots
30
- @slots.select { |slot| slot != nil} rescue []
31
- end
32
-
33
- def intent_request?
34
- request_type == "IntentRequest"
35
- end
36
-
37
- def launch_request?
38
- request_type == "LaunchRequest"
39
- end
40
-
41
- def session_ended_request?
42
- request_type == "SessionEndedRequest"
43
- end
44
-
45
- private
46
- def build_struct(hash)
47
- unless hash.nil?
48
- slot_names = hash.keys.map {|k| k.to_sym.downcase }
49
- slot_values = hash.values.map { |v| v["value"] }
50
- Struct.new(*slot_names).new(*slot_values)
51
- end
52
- end
53
- end
54
- end
@@ -1,57 +0,0 @@
1
- module AlexaWebService
2
- class Response
3
- attr_accessor :session_attributes, :spoken_response, :card_title, :card_content, :reprompt_text, :end_session, :speech_type, :text_type
4
- def initialize(params={})
5
- @session_attributes = params[:session_attributes] || {}
6
- @speech_type = params[:speech_type] || "PlainText"
7
- @spoken_response = params[:spoken_response] || nil
8
- @card_title = params[:card_title] || nil
9
- @card_content = params[:card_content] || nil
10
- @reprompt_text = params[:reprompt_text] || nil
11
- @text_type = params[:text_type] || "text"
12
- @end_session = params[:end_session] || true
13
- end
14
-
15
- def add_attribute(key, value)
16
- @session_attributes.merge!(key => value)
17
- end
18
-
19
- def append_attribute(key, value)
20
- @session_attributes[key] << value if @session_attributes[key] != nil
21
- end
22
-
23
- def with_card
24
- {
25
- "version" => "1.0",
26
- "sessionAttributes" =>
27
- @session_attributes,
28
- "response" => {
29
- "outputSpeech" => {
30
- "type" => speech_type,
31
- "#{text_type}" => spoken_response
32
- },
33
- "card" => {
34
- "type" => "Simple",
35
- "title" => card_title,
36
- "content" => card_content
37
- },
38
- "reprompt" => {
39
- "outputSpeech" => {
40
- "type" => speech_type,
41
- "text" => reprompt_text
42
- }
43
- },
44
- "shouldEndSession" => end_session
45
- }
46
- }
47
- end
48
-
49
- def link_card
50
- self.with_card.tap { |hs| hs["response"]["card"] = {"type" => "LinkAccount"} }
51
- end
52
-
53
- def without_card
54
- self.with_card.tap { |hs| hs["response"].delete("card") }
55
- end
56
- end
57
- end