alexa_web_service 0.0.3
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: 15993c14f7130ce1da02a8b71c75e8a07ba1b5bf
|
4
|
+
data.tar.gz: 6e735f1ab713620b33c1095702f547de001645cd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5f1616e1cd46999c686edf440934f33ba9cf95e6fabaf65151f4c94ba3a1faa96aadf58cb8c151499c8ad31f40722b12af7f93d0fad8d83658f34ec2fa823694
|
7
|
+
data.tar.gz: 2232f4c1784ba6b339e183fe98878f6f4c8c32c56f8a20d7c86a84a52e1ace4df81274a5cc4d35cc6f434795049075f66acfbafae17b15361ffef8be7b580984
|
@@ -0,0 +1,54 @@
|
|
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}
|
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
|
@@ -0,0 +1,57 @@
|
|
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
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module AlexaWebService
|
2
|
+
class AlexaVerify
|
3
|
+
|
4
|
+
def initialize(request_env, request_body)
|
5
|
+
@timestamp = JSON.parse(request_body)["request"]["timestamp"]
|
6
|
+
@url = request_env["HTTP_SIGNATURECERTCHAINURL"]
|
7
|
+
@signature = request_env["HTTP_SIGNATURE"]
|
8
|
+
@digest = OpenSSL::Digest::SHA1.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def valid_address?
|
12
|
+
valid_address = /^https:\/\/s3.amazonaws.com(:443)?\/echo.api\/.*?$/
|
13
|
+
@url == @url.match(valid_address)[0] rescue false
|
14
|
+
end
|
15
|
+
|
16
|
+
def valid_timestamp?
|
17
|
+
Time.now < DateTime.parse(@timestamp).to_time + 150 rescue false
|
18
|
+
end
|
19
|
+
|
20
|
+
def valid_certificate?(certificate)
|
21
|
+
certificate.subject.to_a.last.include?("echo-api.amazon.com") &&
|
22
|
+
Time.now.utc > certificate.not_before &&
|
23
|
+
Time.now.utc < certificate.not_after
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_certificate
|
27
|
+
begin
|
28
|
+
OpenSSL::X509::Certificate.new HTTParty.get(@url)
|
29
|
+
rescue TypeError
|
30
|
+
halt 400, "Bad Request"
|
31
|
+
rescue OpenSSL::SSL::SSLError
|
32
|
+
halt 400, "Bad Request"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def check_signature(certificate)
|
37
|
+
certificate.public_key.verify(@digest, Base64.decode64(@signature), @data) rescue false
|
38
|
+
end
|
39
|
+
|
40
|
+
def verify_request
|
41
|
+
|
42
|
+
if valid_address? && valid_timestamp?
|
43
|
+
@certificate = get_certificate
|
44
|
+
else
|
45
|
+
halt 400, "Bad Request"
|
46
|
+
end
|
47
|
+
|
48
|
+
if valid_certificate?(@certificate)
|
49
|
+
@verify = check_signature(@certificate)
|
50
|
+
else
|
51
|
+
halt 400, "Invalid Certificate"
|
52
|
+
end
|
53
|
+
|
54
|
+
if @verify
|
55
|
+
status 200
|
56
|
+
else
|
57
|
+
halt 400, "Invalid Signature"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
|
metadata
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: alexa_web_service
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- sarkonovich
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-06-27 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.10'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.10'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: httparty
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.13.5
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.13.5
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: json
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.8'
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 1.8.3
|
65
|
+
type: :runtime
|
66
|
+
prerelease: false
|
67
|
+
version_requirements: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - "~>"
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '1.8'
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 1.8.3
|
75
|
+
description: A framework to handle and verify the JSON request/responses for an Alexa
|
76
|
+
skill
|
77
|
+
email:
|
78
|
+
- arkonovs @ reed. edu
|
79
|
+
executables: []
|
80
|
+
extensions: []
|
81
|
+
extra_rdoc_files: []
|
82
|
+
files:
|
83
|
+
- 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
|
87
|
+
- lib/alexa_web_service/version.rb
|
88
|
+
homepage: https://github.com/sarkonovich/Alexa-Web-Service
|
89
|
+
licenses:
|
90
|
+
- MIT
|
91
|
+
metadata: {}
|
92
|
+
post_install_message:
|
93
|
+
rdoc_options: []
|
94
|
+
require_paths:
|
95
|
+
- lib
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: 2.0.0
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
requirements: []
|
107
|
+
rubyforge_project:
|
108
|
+
rubygems_version: 2.4.8
|
109
|
+
signing_key:
|
110
|
+
specification_version: 4
|
111
|
+
summary: A framework to handle the JSON request/responses for an Alexa skill
|
112
|
+
test_files: []
|