wit_ruby 0.0.1

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.
@@ -0,0 +1,143 @@
1
+ ## client.rb
2
+ ## Facilitates the secure connection between the Wit servers and ruby application.
3
+ ## Quite confusing as Net::HTTP and Net::HTTPs is a messy library.
4
+ ## Do look it up if you need more help understanding!
5
+
6
+ module Wit
7
+ module REST
8
+ ## Wit::Session::Client class holds the authentication parameters and
9
+ ## handles making the HTTP requests to the Wit API. These methods should be
10
+ ## internally called and never called directly from the user.
11
+
12
+ ## An example call to instantiate client is done like this with defaults:
13
+ ##
14
+ ## => @client = Wit::Session:Client.new
15
+ ##
16
+ class Client
17
+
18
+ ## Default settings for the client connection to the Wit api.
19
+ DEFAULTS = {
20
+ :token => ENV["WIT_AI_TOKEN"],
21
+ :addr => 'api.wit.ai',
22
+ :port => 443,
23
+ :use_ssl => true,
24
+ :ssl_verify_peer => true,
25
+ :ssl_ca_file => File.dirname(__FILE__) + '/../../../conf/cacert.pem',
26
+ :timeout => 30,
27
+ :proxy_addr => nil,
28
+ :proxy_port => nil,
29
+ :proxy_user => nil,
30
+ :proxy_pass => nil,
31
+ :retry_limit => 1,
32
+ }
33
+
34
+ ## Allows for the reading of the last request, last response, and the
35
+ ## current session.
36
+ attr_reader :last_req, :last_response, :session, :last_result
37
+
38
+ ## Initialize the new instance with either the default parameters or
39
+ ## given parameters.
40
+ ## Token is either the set token in ENV["WIT_AI_TOKEN"] or given in the
41
+ ## options.
42
+ def initialize(options = {})
43
+ ## Token is overidden if given in set params.
44
+ @params = DEFAULTS.merge options
45
+ @auth_token = @params[:token].strip
46
+ setup_conn
47
+ setup_session
48
+ end
49
+
50
+
51
+ ## Change the given auth token.
52
+ def change_auth(new_auth)
53
+ @auth_token = new_auth.strip
54
+ end
55
+
56
+ ## Defines each REST method for the given client. GET, PUT, POST and DELETE
57
+ [:get, :put, :post, :delete].each do |rest_method|
58
+ ## Get the given class for Net::HTTP depending on the current method.
59
+ method_rest_class = Net::HTTP.const_get rest_method.to_s.capitalize
60
+
61
+ ## Define the actual method for Wit::Session:Client
62
+ define_method rest_method do |path|#|path, params|
63
+ request = method_rest_class.new path, {"Authorization" => "Bearer #{@auth_token}"}
64
+ #request.set_form_data(params)#params if [:post, :put].include?(rest_method)
65
+ return connect_send(request)
66
+ end
67
+ end
68
+
69
+ ## Takes in a body and path and creates a net/http class and uses it to call a request to API
70
+ def request_from_result(rest, path, body)
71
+ method_rest_class = Net::HTTP.const_get rest.capitalize
72
+ refresh_request = method_rest_class.new path, {"Authorization" => "Bearer #{@auth_token}"}
73
+ refresh_request.set_form_data(body) unless body == nil
74
+ ## Connect and send it to the API server.
75
+ return connect_send(refresh_request)
76
+ end
77
+
78
+ #################################
79
+ private
80
+
81
+ ## Setup the session that allows for calling of
82
+ def setup_session
83
+ @session = Wit::REST::Session.new(self)
84
+ end
85
+
86
+ ## Used to setup a connection using Net::HTTP object when making requests
87
+ ## to the API.
88
+ def setup_conn
89
+
90
+ ## Setup connection through the @conn instance variable and proxy if
91
+ ## if given.
92
+ @conn = Net::HTTP.new(@params[:addr], @params[:port],
93
+ @params[:proxy_addr], @params[:proxy_port],
94
+ @params[:proxy_user], @params[:proxy_pass]
95
+ )
96
+ setup_ssl
97
+ ## Set timeouts
98
+ @conn.open_timeout = @params[:timeout]
99
+ @conn.read_timeout = @params[:timeout]
100
+ end
101
+
102
+ ## Setup SSL for the given connection in @conn.
103
+ def setup_ssl
104
+ @conn.use_ssl = @params[:use_ssl]
105
+ if @params[:ssl_verify_peer]
106
+ @conn.verify_mode = OpenSSL::SSL::VERIFY_PEER
107
+ @conn.ca_file = @params[:ssl_ca_file]
108
+ else
109
+ @conn.verify_mode = OpenSSL::SSL::VERIFY_NONE
110
+ end
111
+ end
112
+
113
+ ## Connect and send the given request to Wit server.
114
+ def connect_send(request)
115
+ ## Set the last request parameter
116
+ @last_req = request
117
+ ## Set the retries if necessary to send again.
118
+ left_retries = @params[:retry_limit]
119
+ ## Start sending request
120
+ begin
121
+ ## Save last response and depending on the response, return back the
122
+ ## given body as a hash.
123
+ response = @conn.request request
124
+ @last_response = response
125
+ case response.code
126
+ when "200" then save_result_and_return(request, response)
127
+ when "401" then raise Unauthorized, "Incorrect token or not set. Set ENV[\"WIT_AI_TOKEN\"] or pass into the options parameter as :token"
128
+ #else raise BadResponse, "response code: #{response.status}"
129
+ end
130
+
131
+ end
132
+ end
133
+
134
+ ## Save it into the instance last_result and return it.
135
+ def save_result_and_return(request, response)
136
+ @last_result = Wit::REST::Result.new(MultiJson.load(response.body), request.method, request.path, request.body)
137
+ return @last_result
138
+ end
139
+
140
+
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,49 @@
1
+ ## result.rb
2
+ ## Specifies class that handles the results given from each RESTful API call.
3
+
4
+
5
+ module Wit
6
+ module REST
7
+ class Result
8
+
9
+
10
+ ## Instantiates with a given hash.
11
+ def initialize(resultHash, requestRest=nil, requestPath=nil, requestBody=nil)
12
+ @originalHash = resultHash
13
+ @requestRest = requestRest
14
+ @requestPath = requestPath
15
+ @requestBody = requestBody
16
+ end
17
+
18
+ ## Returns the orginalHash instance variable.
19
+ def hash
20
+ return @originalHash
21
+ end
22
+
23
+ ## Returns the REST code from the given request
24
+ def restCode
25
+ return @requestRest
26
+ end
27
+ ## Returns the request's body
28
+ def body
29
+ return @requestBody
30
+ end
31
+
32
+ ## Returns the request's path
33
+ def path
34
+ return @requestPath
35
+ end
36
+
37
+
38
+ ## Checks if the method is one of the keys in the hash.
39
+ ## If it is then we can return the given value.
40
+ ## If not, then raise a NoMethodError.
41
+ def method_missing(possible_key, *args, &block)
42
+ @originalHash.has_key?(possible_key.to_s) ? @originalHash[possible_key.to_s] : super
43
+ end
44
+
45
+
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,94 @@
1
+ ## session.rb
2
+ ## Handles all the neccesary methods to do certain API RESTful calls.
3
+ ## Documentation from Wit for these methods - https://wit.ai/docs/api
4
+
5
+ module Wit
6
+ module REST
7
+ class Session
8
+ ## Initialize with the given client.
9
+ def initialize(client)
10
+ @client = client
11
+ end
12
+ ## GET - extracted meaning form a sentence
13
+ def send_message(message)
14
+ return @client.get("/message?q=#{message}")
15
+ end
16
+
17
+ ## POST - extract meaning from a audio file
18
+ ## Do check the certain documentation of what the specific audio file
19
+ ## should be.
20
+ def send_sound_message(sound)
21
+ end
22
+
23
+ ## GET - returns stored message for specific id.
24
+ ## TODO - possibly renaming as it is ambigious compared to send_message.
25
+ def get_message(message_id)
26
+
27
+ end
28
+
29
+ ## GET - returns either a list of intents if no id is given.
30
+ ## - returns the specific intent of the id given.
31
+ def get_intent(intent_id = nil)
32
+ end
33
+
34
+ ## TODO - look into corpus
35
+
36
+ ## GET - returns a list of available entities given this instance with the
37
+ ## given token if no id is given.
38
+ ## - returns the specific entity and its parameters with a given id.
39
+ ## TODO - notify Wit.ai to fix their documentations as there is a wrong
40
+ ## - description.
41
+ def entities(entity_id = nil)
42
+
43
+ end
44
+
45
+ ## POST - creates a new entity with the given attributes.
46
+ def create_entity(new_entity)
47
+ end
48
+
49
+ ## PUT - updates a given entity with the specific entity id.
50
+ def update_entity(entity_id)
51
+ end
52
+
53
+ ## DELETE - deletes the given entity with the entity id.
54
+ def delete_entity(entity_id)
55
+ end
56
+
57
+ ## POST - adds the possible value into the list of values for the given
58
+ ## - entity with the id.
59
+ def add_value(entity_id, new_value)
60
+
61
+ end
62
+
63
+ ## DELETE - deletes the value from the list of values in the entity with
64
+ ## - with the given value.
65
+ def delete_value(entity_id, delete_value)
66
+
67
+ end
68
+
69
+ ## POST - adds a new expression to the value of the entity.
70
+ def add_expression(entity_id, value, new_expression)
71
+
72
+ end
73
+
74
+ ## DELETE - deleetes the expression in the value of the entity.
75
+ def delete_expression(entity_id, value, expression)
76
+
77
+ end
78
+
79
+ ## Used to refresh the results from the given results.
80
+ def refresh_results(result)
81
+ ## Call client with refresh results method
82
+ return @client.request_from_result(result.restCode, result.path, result.body)
83
+ end
84
+
85
+ ## Used to refresh the last response given from the last request.
86
+ def refresh_last
87
+ last_result = @client.last_result
88
+ return @client.request_from_result(last_result.restCode, last_result.path, last_result.body)
89
+ end
90
+
91
+
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,3 @@
1
+ module Wit
2
+ VERSION = "0.0.1"
3
+ end
data/lib/wit_ruby.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'multi_json'
4
+
5
+
6
+ require "wit_ruby/version"
7
+ require "wit_ruby/rest/client"
8
+ require "wit_ruby/rest/session"
9
+ require "wit_ruby/rest/result"
@@ -0,0 +1,15 @@
1
+
2
+ require 'coveralls'
3
+ Coveralls.wear!
4
+
5
+ require 'wit_ruby'
6
+ require 'pry'
7
+
8
+ require 'webmock/rspec'
9
+ require 'vcr'
10
+
11
+ #VCR config
12
+ VCR.configure do |c|
13
+ c.cassette_library_dir = 'spec/fixtures/wit_cassettes'
14
+ c.hook_into :webmock
15
+ end
@@ -0,0 +1,63 @@
1
+ ## client_spec.rb
2
+ ## Test the functionalities of lib/wit_ruby/rest/client.rb
3
+
4
+ require 'spec_helper'
5
+
6
+ describe Wit::REST::Client do
7
+ let(:rand_auth) {"someAuth"}
8
+ let(:another_auth) {"someOtherAuth"}
9
+ let(:new_host) {"api.fakewit.ai"}
10
+ let(:new_port) {132}
11
+ let(:new_proxy) {"localhost"}
12
+ let(:new_proxy_port) {241}
13
+ let(:new_timeout) {rand(30)}
14
+ let(:new_ssl_path) {"some/ssl/path"}
15
+
16
+ it "should create a new client instance given some auth token" do
17
+ #pending("Need to instantiate the given client with a given token.")
18
+ @client = Wit::REST::Client.new(token: rand_auth)
19
+ expect(@client.instance_variable_get("@auth_token")).to eql(rand_auth)
20
+ end
21
+
22
+ it "should have the proper default connection parameters" do
23
+ @client = Wit::REST::Client.new(token: rand_auth)
24
+ @conn = @client.instance_variable_get("@conn")
25
+ expect(@conn.address).to eql("api.wit.ai")
26
+ expect(@conn.use_ssl?).to be_true
27
+
28
+ end
29
+
30
+ it "should allow the change of the current instance's auth token" do
31
+ #pending("Change the instance auth token to another")
32
+ @client = Wit::REST::Client.new(token: rand_auth)
33
+ @client.change_auth(another_auth)
34
+ expect(@client.instance_variable_get("@auth_token")).to eql(another_auth)
35
+ end
36
+
37
+ it "should allow for change of the default options and accept proxy" do
38
+ @client = Wit::REST::Client.new(token: rand_auth, addr: new_host,
39
+ port: new_port, ssl_ca_file: new_ssl_path, timeout: new_timeout,
40
+ proxy_addr: new_proxy, proxy_port: new_proxy_port)
41
+ @conn = @client.instance_variable_get("@conn")
42
+ expect(@conn.address).to eql(new_host)
43
+ expect(@conn.port).to eql(new_port)
44
+ expect(@conn.proxy?).to be_true
45
+ expect(@conn.proxy_address).to eql(new_proxy)
46
+ expect(@conn.proxy_port).to eql(new_proxy_port)
47
+ expect(@conn.open_timeout).to eql(new_timeout)
48
+ expect(@conn.read_timeout).to eql(new_timeout)
49
+ expect(@conn.ca_file).to eql(new_ssl_path)
50
+
51
+ end
52
+
53
+ it "should setup a session parameter to properly wrap API with commands" do
54
+ @client = Wit::REST::Client.new(token: rand_auth)
55
+ expect(@client.instance_variable_get("@session")).to be_true
56
+ end
57
+
58
+
59
+ it "should be able to do an API call when given a result object" do
60
+ @client = Wit::REST::Client.new(token: rand_auth)
61
+ expect(@client).to respond_to(:request_from_result)
62
+ end
63
+ end
@@ -0,0 +1,38 @@
1
+ ## result_spec.rb
2
+ ## Tests functionalities of lib/wit_ruby/rest/result.rb
3
+ require 'spec_helper'
4
+
5
+ describe Wit::REST::Result do
6
+ let(:randHash) {{"a" => "a", "b" => "b"}}
7
+ let(:rand_path) {"rand_path"}
8
+ let(:rand_body) {"rand_body"}
9
+ let(:rest_code) {"post"}
10
+ let(:result) {Wit::REST::Result.new(randHash, rest_code, rand_path, rand_body)}
11
+
12
+
13
+ it "should have an instance of the original hash" do
14
+ expect(result.hash).to eql(randHash)
15
+ end
16
+
17
+ it "should raise an error for a method that is not in the attributes of the hash" do
18
+ expect{result.random_method}.to raise_error(NoMethodError)
19
+ end
20
+
21
+ it ".method_missing(name, *args, &block" do
22
+ expect(result).to respond_to(:method_missing)
23
+ end
24
+
25
+ it "should not raise any errors for the given keys in a hash" do
26
+ randHash.each_key do |key|
27
+ expect{result.send(key)}.not_to raise_error
28
+ end
29
+ end
30
+
31
+
32
+ it "should have an optional parameters to store the original request's body and pth" do
33
+ expect(result.restCode).to eql(rest_code)
34
+ expect(result.path).to eql(rand_path)
35
+ expect(result.body).to eql(rand_body)
36
+ end
37
+
38
+ end
@@ -0,0 +1,120 @@
1
+ ## session_spec.rb
2
+ ## Used to test lib/wit_ruby/rest/session_spec.rb
3
+
4
+ require 'spec_helper'
5
+
6
+ describe Wit::REST::Session do
7
+ let(:auth) {"randomAuth"}
8
+ let(:randClient) {"randomClient"}
9
+ let(:message) {"Hi"}
10
+ let(:randSession) {Wit::REST::Session.new(randClient)}
11
+ let(:session) {Wit::REST::Client.new.session}
12
+
13
+
14
+ ## Testing for method response
15
+ describe "Default attributes and method definitions" do
16
+ it "should have a client instance variable" do
17
+ randSession.instance_variable_get("@client").should be_eql randClient
18
+ end
19
+
20
+ it '.send_message(message)' do
21
+ randSession.should respond_to(:send_message)
22
+ end
23
+
24
+ it ".send_sound_message(soundwave)" do
25
+ randSession.should respond_to(:send_sound_message)
26
+ end
27
+
28
+ it ".get_message(message_id)" do
29
+ randSession.should respond_to(:get_message)
30
+ end
31
+
32
+ it "get_intent(intent_id = nil)" do
33
+ randSession.should respond_to(:get_intent)
34
+ end
35
+
36
+ it ".entities(entity_id = nil)" do
37
+ randSession.should respond_to(:entities)
38
+ end
39
+
40
+ it ".create_entity(new_entity)" do
41
+ randSession.should respond_to(:create_entity)
42
+ end
43
+
44
+ it ".update_entity(entity_id)" do
45
+ randSession.should respond_to(:update_entity)
46
+ end
47
+
48
+ it ".delete_entity(entity_id)" do
49
+ randSession.should respond_to(:delete_entity)
50
+ end
51
+
52
+ it ".add_value(entity_id, new_value)" do
53
+ randSession.should respond_to(:add_value)
54
+ end
55
+
56
+ it ".delete_value(entity_id, delete_value)" do
57
+ randSession.should respond_to(:delete_value)
58
+ end
59
+
60
+ it ".add_expression(entity_id, value, new_expression)" do
61
+ randSession.should respond_to(:add_expression)
62
+ end
63
+
64
+ it ".delete_expression(entity_id, value, expression)" do
65
+ randSession.should respond_to(:delete_expression)
66
+ end
67
+ end
68
+
69
+
70
+
71
+ ################# Functionalities with API mockup ###########################
72
+
73
+ describe "Sending message" do
74
+ let(:result) {session.send_message(message)}
75
+ let(:result_hash){result.hash}
76
+
77
+ before do
78
+ VCR.insert_cassette 'message', record: :new_episodes
79
+ end
80
+ after do
81
+ VCR.eject_cassette
82
+ end
83
+
84
+ it "should return an object of class Result" do
85
+ expect(result.class).to eql(Wit::REST::Result)
86
+ end
87
+
88
+ it "should have a message id method" do
89
+ expect(result.msg_id).to eql(result.hash["msg_id"])
90
+ end
91
+
92
+
93
+
94
+
95
+ describe "caching" do
96
+ ## Use webmock to disable the network connection after the api request
97
+ ## We use the simple sending message method for testing.
98
+ before do
99
+ @results = session.send_message(message)
100
+ stub_request(:any, /api.wit.ai/).to_timeout
101
+ end
102
+
103
+
104
+
105
+ it "must be able refresh and resend the call to the API given the result class" do
106
+ expect{session.refresh_results(@results)}.to raise_error(Timeout::Error)
107
+ end
108
+
109
+ it "should be able to refresh the last result" do
110
+ expect{session.refresh_last}.to raise_error(Timeout::Error)
111
+ end
112
+
113
+
114
+
115
+ end
116
+
117
+ end
118
+
119
+
120
+ end
data/wit_ruby.gemspec ADDED
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'wit_ruby/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "wit_ruby"
8
+ spec.version = Wit::VERSION
9
+ spec.authors = ["Gavin Ching"]
10
+ spec.email = ["gavinchingy@gmail.com"]
11
+ spec.description = %q{Provides a Ruby interface with the Wit.ai API.}
12
+ spec.summary = %q{Provides a Ruby interface with the Wit.ai API.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.required_ruby_version = ">= 1.8.7"
22
+ spec.add_development_dependency "bundler", "~> 1.3"
23
+ spec.add_dependency('multi_json', '>= 1.3.0')
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rspec"
26
+ spec.add_development_dependency "rspec-nc"
27
+ spec.add_development_dependency "guard"
28
+ spec.add_development_dependency "guard-rspec"
29
+ spec.add_development_dependency "pry"
30
+ spec.add_development_dependency "pry-remote"
31
+ spec.add_development_dependency "pry-nav"
32
+ spec.add_development_dependency "coveralls"
33
+ spec.add_development_dependency "webmock"
34
+ spec.add_development_dependency "vcr"
35
+ end