alexa_ruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 93ed501db9265d681f6b82b67eefff6879c60cdd
4
+ data.tar.gz: 62dcf0154f9e5dc67d091f45d0bff9ccef19ebfa
5
+ SHA512:
6
+ metadata.gz: d771952eb751937874abe1f2143b0e3d029ebd19b0c058fd91e23fadc70f0bf61673ba2ed330ef7dee57fd2dd63202349cbfb925ffeb86b95697946b1a6668b2
7
+ data.tar.gz: '0082c8ee544e27754be23a0132e7ddeb42924840e19684182891d6094325bb56c1300624d418d876d2fbb9fc86279a4fd6e9bdb4facea0daa2cf73207b5ec703'
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+ ruby '2.3.4'
3
+
4
+ # Specify your gem's dependencies in alexa_rubykit.gemspec
5
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,41 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ alexa_ruby (0.0.0)
5
+ bundler (~> 1.7)
6
+ oj (~> 3.0)
7
+ rake
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ diff-lcs (1.3)
13
+ oj (3.0.10)
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_ruby!
34
+ rspec (~> 3.2, >= 3.2.0)
35
+ rspec-mocks (~> 3.2, >= 3.2.0)
36
+
37
+ RUBY VERSION
38
+ ruby 2.3.4p301
39
+
40
+ BUNDLED WITH
41
+ 1.15.0
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Damian Finol
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,5 @@
1
+ # AlexaRuby
2
+
3
+ [![Build Status](https://travis-ci.org/mulev/alexa-ruby.svg?branch=master)](https://travis-ci.org/mulev/alexa-ruby)
4
+
5
+ Originally forked from damianFC's AlexaRubykit, this gem implements a back-end service for interaction with Amazon Alexa API.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new
5
+
6
+ task :default => [:spec]
@@ -0,0 +1,60 @@
1
+ module AlexaRuby
2
+ class IntentRequest < Request
3
+ attr_accessor :intent, :name, :slots
4
+
5
+ # We still don't know if all of the parameters in the request are required.
6
+ # Checking for the presence of intent on an IntentRequest.
7
+ def initialize(json_request)
8
+ super
9
+ @intent = json_request['request']['intent']
10
+ raise ArgumentError, 'Intent should exist on an IntentRequest' if @intent.nil?
11
+ @type = 'INTENT_REQUEST'
12
+ @name = @intent['name']
13
+ @slots = @intent['slots']
14
+ end
15
+
16
+ # Takes a Hash object.
17
+ def add_hash_slots(slots)
18
+ raise ArgumentError, 'Slots can\'t be empty'
19
+ slots.each do |slot|
20
+ @slots[:slot[:name]] = Slot.new(slot[:name], slot[:value])
21
+ end
22
+ @slots
23
+ end
24
+
25
+ # Takes a JSON Object and symbolizes its keys.
26
+ def add_slots(slots)
27
+ slot_hash = AlexaRuby.transform_keys_to_symbols(value)
28
+ add_hash_slots(slot_hash)
29
+ end
30
+
31
+ # Adds a slot from a name and a value.
32
+ def add_slot(name, value)
33
+ slot = Slot.new(name, value)
34
+ @slots[:name] = slot
35
+ slot
36
+ end
37
+
38
+ # Outputs the Intent Name, request Id and slot information.
39
+ def to_s
40
+ "IntentRequest: #{name} requestID: #{request_id} Slots: #{slots}"
41
+ end
42
+ end
43
+
44
+ # Class that encapsulates each slot.
45
+ class Slot
46
+ attr_accessor :name, :value
47
+
48
+ # Each slot has a name and a value.
49
+ def initialize(name, value)
50
+ raise ArgumentError, 'Need a name and a value' if name.nil? || value.nil?
51
+ @name = name
52
+ @value = value
53
+ end
54
+
55
+ # Outputs Slot name and value.
56
+ def to_s
57
+ "Slot Name: #{name}, Value: #{value}"
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,15 @@
1
+ module AlexaRuby
2
+ class LaunchRequest < Request
3
+ # We still don't know if all of the parameters in the request are required.
4
+ # Checking for the presence of intent on an IntentRequest.
5
+ def initialize(json_request)
6
+ super
7
+ @type = 'LAUNCH_REQUEST'
8
+ end
9
+
10
+ # Outputs the launch requestID.
11
+ def to_s
12
+ "LaunchRequest requestID: #{request_id}"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,47 @@
1
+ module AlexaRuby
2
+ # Echo can send 3 types of requests
3
+ # - LaunchRequest: The start of the app.
4
+ # - IntentRequest: The intent of the app.
5
+ # - SessionEndedRequest: Session has ended.
6
+ class Request
7
+ require 'json'
8
+ require 'alexa_ruby/session'
9
+ attr_accessor :version, :type, :session, :json # global
10
+ attr_accessor :request_id, :locale # on request
11
+
12
+ def initialize(json_request)
13
+ @request_id = json_request['request']['requestId']
14
+ raise ArgumentError, 'Request ID should exist on all Requests' if @request_id.nil?
15
+ @version = json_request['version']
16
+ @locale = json_request['request']['locale']
17
+ @json = json_request
18
+
19
+ # TODO: We probably need better session handling.
20
+ @session = AlexaRuby::Session.new(json_request['session'])
21
+ end
22
+ end
23
+
24
+ # Builds a new request for Alexa.
25
+ def self.build_request(json_request)
26
+ raise ArgumentError, 'Invalid Alexa Request.' unless AlexaRuby.valid_alexa?(json_request)
27
+ @request = nil
28
+ case json_request['request']['type']
29
+ when /Launch/
30
+ @request = LaunchRequest.new(json_request)
31
+ when /Intent/
32
+ @request = IntentRequest.new(json_request)
33
+ when /SessionEnded/
34
+ @request = SessionEndedRequest.new(json_request)
35
+ else
36
+ raise ArgumentError, 'Invalid Request Type.'
37
+ end
38
+ @request
39
+ end
40
+
41
+ # Take keys of hash and transform those to a symbols
42
+ def self.transform_keys_to_symbols(value)
43
+ return value if not value.is_a?(Hash)
44
+ hash = value.inject({}){|memo,(k,v)| memo[k.to_sym] = self.transform_keys_to_symbols(v); memo}
45
+ return hash
46
+ end
47
+ end
@@ -0,0 +1,33 @@
1
+ module AlexaRuby
2
+ # AudioPlayer class encapsulates all Alexa audio player directives
3
+ class AudioPlayer
4
+ # Build an AudioPlayer.Play directive
5
+ #
6
+ # @param url [String] audio stream URL
7
+ # @param token [String] some token that represents the audio stream
8
+ # @param offset [Integer] the timestamp in the stream from which Alexa should begin playback
9
+ # @return [Hash] AudioPlayer.Play directive
10
+ def play_directive(url, token, offset)
11
+ {
12
+ type: 'AudioPlayer.Play',
13
+ playBehavior: 'REPLACE_ALL',
14
+ audioItem: {
15
+ stream: {
16
+ token: token,
17
+ url: url,
18
+ offsetInMilliseconds: offset
19
+ }
20
+ }
21
+ }
22
+ end
23
+
24
+ # Build AudioPlayer.Stop directive
25
+ #
26
+ # @return [Hash] AudioPlayer.Stop directive
27
+ def stop_directive
28
+ {
29
+ type: 'AudioPlayer.Stop'
30
+ }
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,130 @@
1
+ module AlexaRuby
2
+ class Response
3
+ require 'json'
4
+ require 'alexa_ruby/response/audio_player'
5
+ attr_accessor :version, :session, :response_object, :session_attributes, :speech, :reprompt, :response, :card
6
+
7
+ # Every response needs a shouldendsession and a version attribute
8
+ # We initialize version to 1.0, use add_version to set your own.
9
+ def initialize(version = '1.0')
10
+ @session_attributes = Hash.new
11
+ @version = version
12
+ @directives = []
13
+ end
14
+
15
+ # Adds a key,value pair to the session object.
16
+ def add_session_attribute(key, value)
17
+ @session_attributes[key.to_sym] = value
18
+ end
19
+
20
+ def add_speech(speech_text, ssml = false)
21
+ if ssml
22
+ @speech = { :type => 'SSML', :ssml => check_ssml(speech_text) }
23
+ else
24
+ @speech = { :type => 'PlainText', :text => speech_text }
25
+ end
26
+ @speech
27
+ end
28
+
29
+ # Add a directive to start audio playback
30
+ def start_audio_playback(url, token = '', offset = 0)
31
+ player = AudioPlayer.new
32
+ @directives = [ player.play_directive(url, token, offset) ]
33
+ end
34
+
35
+ # Add directive to stop audio playback
36
+ def stop_audio_playback
37
+ player = AudioPlayer.new
38
+ @directives = [ player.stop_directive ]
39
+ end
40
+
41
+ def add_reprompt(speech_text, ssml = false)
42
+ if ssml
43
+ @reprompt = { "outputSpeech" => { :type => 'SSML', :ssml => check_ssml(speech_text) } }
44
+ else
45
+ @reprompt = { "outputSpeech" => { :type => 'PlainText', :text => speech_text } }
46
+ end
47
+ @reprompt
48
+ end
49
+
50
+ #
51
+ #"type": "string",
52
+ # "title": "string",
53
+ # "subtitle": "string",
54
+ # "content": "string"
55
+ def add_card(type = nil, title = nil , subtitle = nil, content = nil)
56
+ # A Card must have a type which the default is Simple.
57
+ @card = Hash.new()
58
+ @card[:type] = type || 'Simple'
59
+ @card[:title] = title unless title.nil?
60
+ @card[:subtitle] = subtitle unless subtitle.nil?
61
+ @card[:content] = content unless content.nil?
62
+ @card
63
+ end
64
+
65
+ # The JSON Spec says order shouldn't matter.
66
+ def add_hash_card(card)
67
+ card[:type] = 'Simple' if card[:type].nil?
68
+ @card = card
69
+ @card
70
+ end
71
+
72
+ # Adds a speech to the object, also returns a outputspeech object.
73
+ def say_response(speech, end_session = true, ssml = false)
74
+ output_speech = add_speech(speech,ssml)
75
+ { :outputSpeech => output_speech, :shouldEndSession => end_session }
76
+ end
77
+
78
+ # Incorporates reprompt in the SDK 2015-05
79
+ def say_response_with_reprompt(speech, reprompt_speech, end_session = true, speech_ssml = false, reprompt_ssml = false)
80
+ output_speech = add_speech(speech,speech_ssml)
81
+ reprompt_speech = add_reprompt(reprompt_speech,reprompt_ssml)
82
+ { :outputSpeech => output_speech, :reprompt => reprompt_speech, :shouldEndSession => end_session }
83
+ end
84
+
85
+
86
+ # Creates a session object. We pretty much only use this in testing.
87
+ def build_session
88
+ # If it's empty assume user doesn't need session attributes.
89
+ @session_attributes = Hash.new if @session_attributes.nil?
90
+ @session = { :sessionAttributes => @session_attributes }
91
+ @session
92
+ end
93
+
94
+ # The response object (with outputspeech, cards and session end)
95
+ # Should rename this, but Amazon picked their names.
96
+ # The only mandatory field is end_session which we default to true.
97
+ def build_response_object(session_end = true)
98
+ @response = Hash.new
99
+ @response[:outputSpeech] = @speech unless @speech.nil?
100
+ @response[:directives] = @directives unless @directives.empty?
101
+ @response[:card] = @card unless @card.nil?
102
+ @response[:reprompt] = @reprompt unless session_end && @reprompt.nil?
103
+ @response[:shouldEndSession] = session_end
104
+ @response
105
+ end
106
+
107
+ # Builds a response.
108
+ # Takes the version, response and should_end_session variables and builds a JSON object.
109
+ def build_response(session_end = true)
110
+ response_object = build_response_object(session_end)
111
+ response = Hash.new
112
+ response[:version] = @version
113
+ response[:sessionAttributes] = @session_attributes unless @session_attributes.empty?
114
+ response[:response] = response_object
115
+ response.to_json
116
+ end
117
+
118
+ # Outputs the version, session object and the response object.
119
+ def to_s
120
+ "Version => #{@version}, SessionObj => #{@session}, Response => #{@response}"
121
+ end
122
+
123
+ private
124
+
125
+ def check_ssml(ssml_string)
126
+ ssml_string = ssml_string.strip[0..6] == "<speak>" ? ssml_string : "<speak>" + ssml_string
127
+ ssml_string.strip[-8..1] == "</speak>" ? ssml_string : ssml_string + "</speak>"
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,37 @@
1
+ module AlexaRuby
2
+ # Handles the session object in request.
3
+ class Session
4
+ attr_accessor :new, :session_id, :attributes, :user
5
+ def initialize (session)
6
+ raise ArgumentError, 'Invalid Session' if session.nil? || session['new'].nil? || session['sessionId'].nil?
7
+ @new = session['new']
8
+ @session_id = session['sessionId']
9
+ session['attributes'].nil? ? @attributes = Hash.new : @attributes = session['attributes']
10
+ @user = session['user']
11
+ end
12
+
13
+ # Returns whether this is a new session or not.
14
+ def new?
15
+ !!@new
16
+ end
17
+
18
+ # Returns true if a user is defined.
19
+ def user_defined?
20
+ !@user.nil? || !@user['userId'].nil?
21
+ end
22
+
23
+ # Returns the user_id.
24
+ def user_id
25
+ @user['userId'] if @user
26
+ end
27
+
28
+ def access_token
29
+ @user['accessToken'] if @user
30
+ end
31
+
32
+ # Check to see if attributes are present.
33
+ def has_attributes?
34
+ !@attributes.empty?
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,20 @@
1
+ # Session end request class.
2
+ module AlexaRuby
3
+ class SessionEndedRequest < Request
4
+ attr_accessor :reason
5
+
6
+ # TODO: Validate the reason.
7
+ # We still don't know if all of the parameters in the request are required.
8
+ # Checking for the presence of intent on an IntentRequest.
9
+ def initialize(json_request)
10
+ super
11
+ @type = 'SESSION_ENDED_REQUEST'
12
+ @reason = json_request['request']['reason']
13
+ end
14
+
15
+ # Ouputs the request_id and the reason why.
16
+ def to_s
17
+ "Session Ended for requestID: #{request_id} with reason #{reason}"
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ module AlexaRuby
2
+ VERSION = '0.1.0'.freeze
3
+ end
data/lib/alexa_ruby.rb ADDED
@@ -0,0 +1,24 @@
1
+ require 'alexa_ruby/request'
2
+ require 'alexa_ruby/version'
3
+ require 'alexa_ruby/response'
4
+ require 'alexa_ruby/intent_request'
5
+ require 'alexa_ruby/launch_request'
6
+ require 'alexa_ruby/session_ended_request'
7
+
8
+ module AlexaRuby
9
+ # Prints a JSON object.
10
+ def self.print_json(json)
11
+ p json
12
+ end
13
+
14
+ # Prints the Gem version.
15
+ def self.print_version
16
+ p AlexaRuby::VERSION
17
+ end
18
+
19
+ # Returns true if all the Alexa request objects are set.
20
+ def self.valid_alexa?(request_json)
21
+ !request_json.nil? && !request_json['session'].nil? &&
22
+ !request_json['version'].nil? && !request_json['request'].nil?
23
+ end
24
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: alexa_ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Mike Mulev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-25 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.7'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
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: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.2'
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 3.2.0
51
+ type: :development
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - "~>"
56
+ - !ruby/object:Gem::Version
57
+ version: '3.2'
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 3.2.0
61
+ - !ruby/object:Gem::Dependency
62
+ name: rspec-mocks
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '3.2'
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 3.2.0
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - "~>"
76
+ - !ruby/object:Gem::Version
77
+ version: '3.2'
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: 3.2.0
81
+ description: Ruby toolkit for Amazon Alexa API
82
+ email:
83
+ - m.mulev@gmail.com
84
+ executables: []
85
+ extensions: []
86
+ extra_rdoc_files: []
87
+ files:
88
+ - Gemfile
89
+ - Gemfile.lock
90
+ - LICENSE.txt
91
+ - README.md
92
+ - Rakefile
93
+ - lib/alexa_ruby.rb
94
+ - lib/alexa_ruby/intent_request.rb
95
+ - lib/alexa_ruby/launch_request.rb
96
+ - lib/alexa_ruby/request.rb
97
+ - lib/alexa_ruby/response.rb
98
+ - lib/alexa_ruby/response/audio_player.rb
99
+ - lib/alexa_ruby/session.rb
100
+ - lib/alexa_ruby/session_ended_request.rb
101
+ - lib/alexa_ruby/version.rb
102
+ homepage: https://github.com/mulev/alexa-ruby
103
+ licenses:
104
+ - MIT
105
+ metadata: {}
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubyforge_project:
122
+ rubygems_version: 2.6.12
123
+ signing_key:
124
+ specification_version: 4
125
+ summary: Ruby toolkit for Amazon Alexa API
126
+ test_files: []