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,7 @@
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'
5
+
6
+ module AlexaWebService
7
+ end
@@ -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
+
@@ -0,0 +1,3 @@
1
+ module AlexaWebService
2
+ VERSION = "0.0.3"
3
+ end
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: []