alexa_toolbox 1.0.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 410e7ebcc29c183541f1c4d5ad5b13e898ca1263
4
+ data.tar.gz: 3507752cb6aa7791bf0c99db20fd00ceaf063e7a
5
+ SHA512:
6
+ metadata.gz: a21accae38d9aad6543ace3ab03eddd6d327b88999aee89c87b8e3deeba4b5a32b7ab03de1413022ebe0da3cbb0631ff58d5bf9a10955ca39a9fa77ef6a6cbb8
7
+ data.tar.gz: 56918a9a6c88a5b562e5514b2e0b80dbbdc779ddc8c0869ef28696fbd9e5abda5e196c2889c17bafce50198bb64ed44ed21467d3a067f7d3bb60f211b7cbc488
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in alexa_toolbox.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,38 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ alexa_toolbox (1.0.0)
5
+ bundler (~> 1.14)
6
+ deep_merge
7
+ rake
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ deep_merge (1.1.1)
13
+ diff-lcs (1.3)
14
+ rake (12.0.0)
15
+ rspec (3.6.0)
16
+ rspec-core (~> 3.6.0)
17
+ rspec-expectations (~> 3.6.0)
18
+ rspec-mocks (~> 3.6.0)
19
+ rspec-core (3.6.0)
20
+ rspec-support (~> 3.6.0)
21
+ rspec-expectations (3.6.0)
22
+ diff-lcs (>= 1.2.0, < 2.0)
23
+ rspec-support (~> 3.6.0)
24
+ rspec-mocks (3.6.0)
25
+ diff-lcs (>= 1.2.0, < 2.0)
26
+ rspec-support (~> 3.6.0)
27
+ rspec-support (3.6.0)
28
+
29
+ PLATFORMS
30
+ ruby
31
+
32
+ DEPENDENCIES
33
+ alexa_toolbox!
34
+ rspec (~> 3.6, >= 3.6.0)
35
+ rspec-mocks (~> 3.6, >= 3.6.0)
36
+
37
+ BUNDLED WITH
38
+ 1.14.6
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2017 Paul McMahon
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,169 @@
1
+ # AlexaToolbox
2
+
3
+ This gem implements a full suite of tools for deploying applications for Amazon's Alexa.
4
+
5
+ ## Installation
6
+
7
+ ### For Ruby Projects:
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'alexa_toolbox'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install alexa_toolbox
22
+
23
+ ## Usage
24
+
25
+ This Gem provides methods to create and handle requests, create response objects, and miscellaneous support functions for Alexa skills.
26
+
27
+ ### Requests
28
+
29
+ [Amazon Request Documentation](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interface-reference#request-format)
30
+
31
+ #### Handling Request JSON:
32
+
33
+ ```ruby
34
+ require 'alexa_toolbox'
35
+ request = AlexaToolbox::Request.new(params,{ :application_id => 'YOUR_APP_ID' })
36
+ # params variable is json request retrieved by server (default is params in Ruby on Rails)
37
+ # request application IDs are checked vs your application ID to ensure they are valid requests as per Amazon's guidelines
38
+ ```
39
+ #### Check Request Validity:
40
+
41
+ You should always check request validity as per Amazon's guidelines
42
+ [Amazon Guidelines](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/handling-requests-sent-by-alexa#verifying-that-the-request-is-intended-for-your-service)
43
+
44
+ ```ruby
45
+ require 'alexa_toolbox'
46
+ request = AlexaToolbox::Request.new(params,{ :application_id => 'YOUR_APP_ID' })
47
+ if !request.valid?
48
+ # return 500 status
49
+ end
50
+ ```
51
+ #### Getting Information From the Request
52
+
53
+ ```ruby
54
+ require 'alexa_toolbox'
55
+ request = AlexaToolbox::Request.new(params,{ :application_id => 'YOUR_APP_ID' })
56
+
57
+ request.type
58
+ # Returns request type:
59
+ # LaunchRequest
60
+ # IntentRequest
61
+ # SessionEndedRequest
62
+ # AudioPlayer
63
+ # PlaybackController
64
+ # System.ExceptionEncountered
65
+
66
+ # Check if new session
67
+ request.session.new?
68
+ # Get sessionId
69
+ request.session.session_id
70
+ # Get userId
71
+ request.session.user_id
72
+ ```
73
+
74
+ #### Utilizing Request Hash
75
+
76
+ If you are more comfortable navigating the request hash and are familiar with the setup you can still acces it.
77
+
78
+ ```ruby
79
+ require 'alexa_toolbox'
80
+ request = AlexaToolbox::Request.new(params,{ :application_id => 'YOUR_APP_ID' })
81
+
82
+ # Get Session
83
+ request.json[:session]
84
+ # Get sessionId
85
+ request.json[:session][:sessionId]
86
+ ```
87
+
88
+ #### Utilizing Address Consent
89
+
90
+ [Alexa Documentation on Address Data](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/device-address-api)
91
+
92
+ If you want to access the user's address, you'll first require their permission and then you'll receive a consent token and deviceId in the request.
93
+ Once you have those, you will need to utilize Amazon's API to retrieve the address data. (Supporting feature a WIP.)
94
+
95
+ ```ruby
96
+ require 'alexa_toolbox'
97
+ request = AlexaToolbox::Request.new(params,{ :application_id => 'YOUR_APP_ID' })
98
+
99
+ consent_token = request.session.consent_token
100
+ device_id = request.session.device_id
101
+ ```
102
+
103
+
104
+ ### Responses
105
+
106
+ [Amazon Response Documentation](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interface-reference#response-format)
107
+
108
+ #### Simple Response Object Example:
109
+
110
+ ```ruby
111
+ require 'alexa_toolbox'
112
+ response = AlexaToolbox::Response.new
113
+ response.add_speech('Creating a response is so easy!')
114
+ response.build_response
115
+ ```
116
+
117
+ #### If you want to utilize SSML (will add speak tags if you forget!):
118
+
119
+ ```ruby
120
+ require 'alexa_toolbox'
121
+ response = AlexaToolbox::Response.new
122
+ response.add_speech('Creating a response is so easy!',true)
123
+ # or
124
+ # response.add_speech('<speak>Creating a response is so easy!</speak>',true)
125
+ response.build_response
126
+ ```
127
+
128
+ #### To add a card to your response:
129
+
130
+ ```ruby
131
+ require 'alexa_toolbox'
132
+ response = AlexaToolbox::Response.new
133
+ # add_card(type,title,subtitle,content)
134
+ # or
135
+ # add_hash_card({ :type => type, :title => title, :subtitle => subtitle, :content => content })
136
+ response.add_card("PlainText","Card Title","Card Subtitle","This card should have some interesting content for your user.")
137
+ response.build_response
138
+ ```
139
+
140
+ #### Will generate a valid outputspeech response in JSON format:
141
+
142
+ ```JSON
143
+ {
144
+ "version": "1.0",
145
+ "response": {
146
+ "outputSpeech": {
147
+ "type": "PlainText",
148
+ "text": "Ruby is running ready!"
149
+ },
150
+ "shouldEndSession": true
151
+ }
152
+ }
153
+ ```
154
+
155
+ ## Troubleshooting
156
+
157
+
158
+ ## Contributing
159
+
160
+ 1. Fork it
161
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
162
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
163
+ 4. Push to the branch (`git push origin my-new-feature`)
164
+ 5. Create a new Pull Request
165
+
166
+ Please make sure to write specs for any new features!
167
+
168
+ # Team Members
169
+ * "Paul McMahon" <colpan@sircolpaniusjackson.com>
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,106 @@
1
+ module AlexaToolbox
2
+ # Handles the retrieving address information about a device.
3
+ class Address
4
+ require 'net/http'
5
+ attr_reader :json
6
+ attr_accessor :consent_token, :device_id, :full_address, :app_location
7
+
8
+ def initialize (consent_token = nil, device_id = nil, app_location = "US", full_address = false)
9
+ @consent_token = consent_token
10
+ @device_id = device_id
11
+ @country_code = nil
12
+ @postal_code = nil
13
+ @city = nil
14
+ @state_or_region = nil
15
+ @address_line_1 = nil
16
+ @address_line_2 = nil
17
+ @address_line_3 = nil
18
+ @district_or_county = nil
19
+ @status = nil
20
+ @full_address = full_address
21
+ @app_location = app_location
22
+ @json = nil
23
+ end
24
+
25
+ def add_request(request)
26
+ @consent_token = request.session.consent_token
27
+ @device_id = request.session.device_id
28
+ end
29
+
30
+ def add_token(token)
31
+ @consent_token = token
32
+ end
33
+
34
+ def add_device(device)
35
+ @device_id = device
36
+ end
37
+
38
+ def retrieve_full_address(consent_token = nil, device_id = nil)
39
+ token = consent_token.nil? ? @consent_token : consent_token
40
+ device = device_id.nil? ? @device_id : device_id
41
+ if !token.nil? && !device.nil?
42
+ if self.base_uri.nil?
43
+ raise ArgumentError, 'Invalid Request, Invalid app_location set'
44
+ else
45
+ full_uri = self.base_uri + "/v1/devices/" + device + "/settings/address"
46
+ self.execute_request(full_uri,token)
47
+ end
48
+ else
49
+ raise ArgumentError, 'Invalid Request, No Token or Device'
50
+ end
51
+ end
52
+
53
+ def retrieve_partial_address(consent_token = nil, device_id = nil)
54
+ token = consent_token.nil? ? @consent_token : consent_token
55
+ device = device_id.nil? ? @device_id : device_id
56
+ if !token.nil? && !device.nil?
57
+ if self.base_uri.nil?
58
+ raise ArgumentError, 'Invalid Request, Invalid app_location set'
59
+ else
60
+ full_uri = self.base_uri + "/v1/devices/" + device + "/settings/address/countryAndPostalCode"
61
+ self.execute_request(full_uri,token)
62
+ end
63
+ else
64
+ raise ArgumentError, 'Invalid Request, No Token or Device'
65
+ end
66
+ end
67
+
68
+ def execute_request(endpoint,token)
69
+ uri = URI(endpoint)
70
+
71
+ Net::HTTP.start(uri.hostname, uri.port, :use_ssl => uri.scheme == 'https') do |http|
72
+ request = Net::HTTP::Get.new(uri)
73
+ request['Authorization'] = token
74
+
75
+ response = http.request(request)
76
+ self.status = response.code
77
+ self.json = response.body
78
+ if response.code == 200
79
+ res_body = response.body
80
+ @country_code = res_body.key?("countryCode") ? res_body["countryCode"] : self.country_code
81
+ @postal_code = res_body.key?("postalCode") ? res_body["postalCode"] : self.postal_code
82
+ @city = res_body.key?("city") ? res_body["city"] : self.city
83
+ @state_or_region = res_body.key?("stateOrRegion") ? res_body["stateOrRegion"] : self.state_or_region
84
+ @address_line_1 = res_body.key?("addressLine1") ? res_body["addressLine1"] : self.address_line_1
85
+ @address_line_2 = res_body.key?("addressLine2") ? res_body["addressLine2"] : self.address_line_2
86
+ @address_line_3 = res_body.key?("addressLine3") ? res_body["addressLine3"] : self.address_line_3
87
+ @district_or_county = res_body.key?("districtOrCounty") ? res_body["districtOrCounty"] : self.district_or_county
88
+ else
89
+ end
90
+ end
91
+ end
92
+
93
+ def base_uri
94
+ case self.app_location
95
+ when "US"
96
+ return "https://api.amazonalexa.com"
97
+ when "UK"
98
+ return "https://api.eu.amazonalexa.com"
99
+ when "DE"
100
+ return "https://api.eu.amazonalexa.com"
101
+ else
102
+ return nil
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,16 @@
1
+ module AlexaToolbox
2
+ # Handles the audioplayer object in requests.
3
+ class AudioPlayer
4
+ attr_reader :type, :offset_in_milliseconds, :token, :current_playback_state, :error, :json
5
+
6
+ def initialize (audioplayer)
7
+ raise ArgumentError, 'Invalid AudioPlayer' if !audioplayer.key?(:type) && audioplayer[:type][0..10] != "AudioPlayer"
8
+ @type = audioplayer[:type][12..-1]
9
+ @offset_in_milliseconds = audioplayer[:offsetInMilliseconds]
10
+ @token = audioplayer[:token]
11
+ @current_playback_state = audioplayer[:currentPlaybackState]
12
+ @json = audioplayer
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ module AlexaToolbox
2
+ # Handles the session object in requests.
3
+ class Context
4
+ require 'alexa_toolbox/audioplayer'
5
+ attr_reader :audioplayer, :system, :json
6
+
7
+ def initialize (context)
8
+ raise ArgumentError, 'Invalid Context' if false
9
+ @system = context[:System]
10
+ @audioplayer = context.key?(:AudioPlayer) ? AlexaToolbox::AudioPlayer.new(context[:AudioPlayer]) : nil
11
+ @json = context
12
+ end
13
+
14
+ def application_id
15
+ return self.system[:application][:applicationId]
16
+ end
17
+
18
+ def user_id
19
+ return self.system[:user][:userId]
20
+ end
21
+
22
+ def device_id
23
+ return self.system[:device][:deviceId]
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ module AlexaToolbox
2
+ # Handles the intent object in requests.
3
+ class Intent
4
+ attr_reader :name, :confirmation_status, :json
5
+
6
+ def initialize (intent)
7
+ raise ArgumentError, 'Invalid Intent' if intent[:name].empty?
8
+ @name = intent[:name]
9
+ @confirmation_status = intent[:confirmationStatus]
10
+ @json = intent
11
+ end
12
+
13
+ def has_slots?
14
+ return self.slots != {}
15
+ end
16
+
17
+ def slots
18
+ return self.json[:slots]
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,59 @@
1
+ module AlexaToolbox
2
+ # Echo can send 3 types of requests
3
+ # - LaunchRequest: The app was launched using phrasing such as 'Alexa open ______'.
4
+ # - IntentRequest: An intent was requested.
5
+ # - SessionEndedRequest: Session was closed either by user or timeout.
6
+
7
+ class Request
8
+ require 'json'
9
+ require 'deep_merge'
10
+ require 'alexa_toolbox/session'
11
+ require 'alexa_toolbox/intent'
12
+ require 'alexa_toolbox/audioplayer'
13
+ require 'alexa_toolbox/context'
14
+ attr_reader :version, :session, :json, :options, :request_id, :locale, :type, :intent, :audioplayer, :error, :cause, :context
15
+
16
+ def self.default_options
17
+ @default_options ||= {
18
+ :application_id => ''
19
+ }
20
+ end
21
+
22
+ def initialize(json_request, options = {})
23
+ options = options.deep_merge(self.class.default_options)
24
+ @options = options
25
+
26
+ @request_id = json_request[:request][:requestId]
27
+ raise ArgumentError, 'Request ID not present' if @request_id.nil?
28
+ @version = json_request[:version]
29
+ @locale = json_request[:request][:locale]
30
+ @error = json_request[:request][:error]
31
+ @cause = json_request[:request][:cause]
32
+ @json = json_request
33
+ @type = json_request[:request][:type][0..10] == "AudioPlayer" ? "AudioPlayer" : json_request[:request][:type]
34
+
35
+ @intent = @type == "IntentRequest" ? AlexaToolbox::Intent.new(json_request[:request][:intent]) : nil
36
+ @audioplayer = @type == "AudioPlayer" ? AlexaToolbox::AudioPlayer.new(json_request[:request]) : nil
37
+ @session = json_request.key?(:session) ? AlexaToolbox::Session.new(json_request[:session]) : nil
38
+ @context = json_request.key?(:context) ? AlexaToolbox::Context.new(json_request[:context]) : nil
39
+ end
40
+
41
+ def valid?
42
+ self.options[:application_id] && ((!self.session.nil? && self.options[:application_id] == self.session.application_id) || (!self.context.nil? && self.options[:application_id] == self.context.application_id))
43
+ end
44
+
45
+ def user_terminated?
46
+ if self.type != "SessionEndedRequest"
47
+ return nil
48
+ end
49
+ return self.json[:request][:reason] == "USER_INITIATED"
50
+ end
51
+ end
52
+
53
+ # Builds a new request for Alexa, primarily for testing purposes
54
+ def self.build_request(json_request, application_id = "")
55
+ json_request = self.transform_keys_to_symbols(json_request)
56
+ raise ArgumentError, 'Invalid Alexa Request. Missing session, request, version, or application id.' unless AlexaToolbox.valid_alexa?(json_request)
57
+ Request.new(json_request,{ :application_id => application_id })
58
+ end
59
+ end
@@ -0,0 +1,161 @@
1
+ module AlexaToolbox
2
+ class Response
3
+ require 'json'
4
+ attr_reader :version, :reprompt, :speech, :response, :session_attributes, :card
5
+ attr_accessor :player_response, :session_end
6
+
7
+ # Every response will have a version, response, and shouldEndSession
8
+ def initialize(player_response = false, ssml = false, version = '1.0')
9
+ @session_attributes = Hash.new
10
+ @version = version
11
+ @directives = []
12
+ @player_response = player_response
13
+ @ssml = ssml
14
+ @session_end = true
15
+ @reprompt = nil
16
+ @speech = nil
17
+ end
18
+
19
+ # Adds a key,value pair to the session object.
20
+ def add_session_attribute(key, value)
21
+ @session_attributes[key.to_sym] = AlexaToolbox.transform_keys_to_symbols(value)
22
+ end
23
+
24
+ def add_speech(speech_text, ssml = nil)
25
+ ssml = ssml.nil? ? @ssml : ssml
26
+ if ssml
27
+ @speech = { :type => 'SSML', :ssml => check_ssml(speech_text) }
28
+ else
29
+ @speech = { :type => 'PlainText', :text => speech_text }
30
+ end
31
+ end
32
+
33
+ def add_plain_speech(speech_text)
34
+ @speech = { :type => 'PlainText', :text => speech_text }
35
+ end
36
+
37
+ def add_ssml_speech(speech_text)
38
+ @speech = { :type => 'SSML', :ssml => check_ssml(speech_text) }
39
+ end
40
+
41
+ def add_reprompt(speech_text, ssml = nil)
42
+ ssml = ssml.nil? ? @ssml : ssml
43
+ if ssml
44
+ @reprompt = { "outputSpeech" => { :type => 'SSML', :ssml => check_ssml(speech_text) } }
45
+ else
46
+ @reprompt = { "outputSpeech" => { :type => 'PlainText', :text => speech_text } }
47
+ end
48
+ end
49
+
50
+ def add_ssml_reprompt(speech_text)
51
+ @reprompt = { "outputSpeech" => { :type => 'SSML', :ssml => check_ssml(speech_text) } }
52
+ end
53
+
54
+ def add_audio_play_directive(url, play_behavior = '', token = '', expected_previous_token = '', offset = 0)
55
+ directive = {
56
+ 'type' => 'AudioPlayer.Play',
57
+ 'playBehavior' => play_behavior,
58
+ 'audioItem' => {
59
+ 'stream' => {
60
+ 'token' => token,
61
+ 'url' => url,
62
+ 'offsetInMilliseconds' => offset
63
+ }
64
+ }
65
+ }
66
+ directive['audioItem']['stream']['expectedPreviousToken'] = expected_previous_token if play_behavior == "ENQUEUE"
67
+ @directives << directive
68
+ end
69
+
70
+ def add_audio_clear_directive(clear_all = false)
71
+ @directives << {
72
+ 'type' => 'AudioPlayer.ClearQueue',
73
+ 'clearBehavior' => clear_all ? "CLEAR_ALL" : "CLEAR_ENQUEUED"
74
+ }
75
+ end
76
+
77
+ def add_audio_stop_directive
78
+ @directives << {
79
+ 'type' => 'AudioPlayer.Stop'
80
+ }
81
+ end
82
+
83
+ # "type": "string",
84
+ # "title": "string",
85
+ # "content": "string"
86
+ # Standard uses :text instead of :content
87
+ def add_card(type = nil, title = nil, content = nil, smallImageUrl = nil, largeImageUrl = nil)
88
+ @card = Hash.new
89
+ @card[:type] = type.nil? ? 'Simple' : type
90
+ if @card[:type] != "LinkAccount"
91
+ @card[:title] = title unless title.nil?
92
+ @card[:type] = 'Simple' if smallImageUrl.nil? && largeImageUrl.nil?
93
+ if @card[:type] == 'Simple'
94
+ @card[:content] = content unless content.nil?
95
+ else
96
+ @card[:text] = content unless content.nil?
97
+ @card[:image] = {
98
+ :smallImageUrl => smallImageUrl,
99
+ :largeImageUrl => largeImageUrl
100
+ }
101
+ end
102
+ end
103
+ end
104
+
105
+ # Add Permission Card for Location Information
106
+ def add_permission_card(full_address = false)
107
+ @card = Hash.new
108
+ @card[:type] = 'AskForPermissionsConsent'
109
+ permission = full_address ? "read::alexa:device:all:address" : "read::alexa:device:all:address:country_and_postal_code"
110
+ @card[:permissions] = [permission]
111
+ end
112
+
113
+ # Add a card as a single hash
114
+ def add_hash_card(card)
115
+ card[:type] = 'Simple' if card[:type].nil?
116
+ @card = card
117
+ end
118
+
119
+ # The response object as hash (with outputspeech, cards and session end)
120
+ def build_standard_response_object(session_end = true)
121
+ @response = Hash.new
122
+ @response[:outputSpeech] = @speech unless @speech.nil?
123
+ @response[:directives] = @directives unless @directives.empty?
124
+ @response[:card] = @card unless @card.nil?
125
+ @response[:reprompt] = @reprompt unless @reprompt.nil?
126
+ @response[:shouldEndSession] = session_end
127
+ @response
128
+ end
129
+
130
+ # For Responses to AudioPlayer or PlaybackController Requests
131
+ # Cannot Include: outputSpeech, card, reprompt, shouldEndSession
132
+ def build_player_response_object(session_end = true)
133
+ @response = Hash.new
134
+ @response[:directives] = @directives unless @directives.empty?
135
+ @response
136
+ end
137
+
138
+ # Builds a response object, can be json or hash if json is false
139
+ def build_response(session_end = nil, player_response = nil, json = true)
140
+ is_player_response = player_response.nil? ? @player_response : player_response
141
+ end_session = session_end.nil? ? @session_end : session_end
142
+ response = Hash.new
143
+ if is_player_response
144
+ response_object = build_player_response_object(end_session)
145
+ else
146
+ response_object = build_standard_response_object(end_session)
147
+ response[:sessionAttributes] = @session_attributes unless @session_attributes.empty?
148
+ end
149
+ response[:version] = @version
150
+ response[:response] = response_object
151
+ json ? JSON.parse(response.to_json) : response
152
+ end
153
+
154
+ private
155
+
156
+ def check_ssml(ssml_string)
157
+ ssml_string = ssml_string.strip[0..6] == "<speak>" ? ssml_string : "<speak>" + ssml_string
158
+ ssml_string.strip[-8..1] == "</speak>" ? ssml_string : ssml_string + "</speak>"
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,61 @@
1
+ module AlexaToolbox
2
+ # Handles the session object in requests.
3
+ class Session
4
+ attr_reader :new, :session_id, :attributes, :user, :application_id, :device
5
+
6
+ def initialize (session)
7
+ raise ArgumentError, 'Invalid Session' if session.nil? || session[:new].nil? || session[:sessionId].nil?
8
+ @new = session[:new]
9
+ @session_id = session[:sessionId]
10
+ @attributes = session[:attributes].nil? ? Hash.new : session[:attributes]
11
+ @user = session[:user]
12
+ @application_id = session[:application][:applicationId]
13
+ @device = session[:device]
14
+ end
15
+
16
+ # Checks whether this is a new session
17
+ def new?
18
+ @new
19
+ end
20
+
21
+ # Checks if user is defined
22
+ def user_defined?
23
+ !@user.nil? || !@user[:userId].nil?
24
+ end
25
+
26
+ # Returns user's id
27
+ def user_id
28
+ @user[:userId] if @user
29
+ end
30
+
31
+ def access_token?
32
+ @user.key?(:accessToken) && !@user[:accessToken].empty?
33
+ end
34
+
35
+ # Returns user's access token if provided
36
+ def access_token
37
+ @user[:accessToken] if @user
38
+ end
39
+
40
+ def consent_token?
41
+ @user.key?(:permissions) && @user[:permissions].key?(:consentToken) && !@user[:permissions][:consentToken].empty?
42
+ end
43
+
44
+ def consent_token
45
+ @user[:permissions][:consentToken] if @user && @user.key?(:permissions) && @user[:permissions].key?(:consentToken)
46
+ end
47
+
48
+ def device_id
49
+ @device[:deviceId]
50
+ end
51
+
52
+ def supported_interfaces
53
+ @device[:supportedInterfaces]
54
+ end
55
+
56
+ # Check to see if attributes are present.
57
+ def has_attributes?
58
+ !@attributes.empty?
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,3 @@
1
+ module AlexaToolbox
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,28 @@
1
+ require 'alexa_toolbox/request'
2
+ require 'alexa_toolbox/version'
3
+ require 'alexa_toolbox/response'
4
+ require 'alexa_toolbox/address'
5
+
6
+ module AlexaToolbox
7
+ # Prints a JSON object.
8
+ def self.print_json(json)
9
+ p json
10
+ end
11
+
12
+ # Prints the Gem version.
13
+ def self.print_version
14
+ p AlexaToolbox::VERSION
15
+ end
16
+
17
+ # Returns true if all the Alexa objects are set.
18
+ def self.valid_alexa?(request_json)
19
+ !request_json.nil? && !request_json[:version].nil? && !request_json[:request].nil?
20
+ end
21
+
22
+ # Take keys of hash and transform those to a symbols
23
+ def self.transform_keys_to_symbols(input)
24
+ return input if not input.is_a?(Hash)
25
+ hash = input.inject({}){|store,(key,val)| store[key.to_sym] = self.transform_keys_to_symbols(val); store}
26
+ return hash
27
+ end
28
+ end
metadata ADDED
@@ -0,0 +1,140 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: alexa_toolbox
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Paul McMahon
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.14'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.14'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: deep_merge
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
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: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.6'
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 3.6.0
65
+ type: :development
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - "~>"
70
+ - !ruby/object:Gem::Version
71
+ version: '3.6'
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 3.6.0
75
+ - !ruby/object:Gem::Dependency
76
+ name: rspec-mocks
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '3.6'
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 3.6.0
85
+ type: :development
86
+ prerelease: false
87
+ version_requirements: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - "~>"
90
+ - !ruby/object:Gem::Version
91
+ version: '3.6'
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: 3.6.0
95
+ description: Full top to bottom toolbox for creating a custom Alexa skill.
96
+ email:
97
+ - colpan@sircolpaniusjackson.com
98
+ executables: []
99
+ extensions: []
100
+ extra_rdoc_files: []
101
+ files:
102
+ - Gemfile
103
+ - Gemfile.lock
104
+ - LICENSE.txt
105
+ - README.md
106
+ - Rakefile
107
+ - lib/alexa_toolbox.rb
108
+ - lib/alexa_toolbox/address.rb
109
+ - lib/alexa_toolbox/audioplayer.rb
110
+ - lib/alexa_toolbox/context.rb
111
+ - lib/alexa_toolbox/intent.rb
112
+ - lib/alexa_toolbox/request.rb
113
+ - lib/alexa_toolbox/response.rb
114
+ - lib/alexa_toolbox/session.rb
115
+ - lib/alexa_toolbox/version.rb
116
+ homepage: https://github.com/colpan/alexa-toolbox
117
+ licenses:
118
+ - MIT
119
+ metadata: {}
120
+ post_install_message:
121
+ rdoc_options: []
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ requirements: []
135
+ rubyforge_project:
136
+ rubygems_version: 2.4.5.1
137
+ signing_key:
138
+ specification_version: 4
139
+ summary: Full top to bottom toolbox for creating a custom Alexa skill.
140
+ test_files: []