ordrin 0.1.1 → 0.1.2

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.
@@ -1,186 +1,186 @@
1
- require_relative 'errors'
2
-
3
- module Ordrin
4
- module Normalize
5
- class Normalizers
6
- private
7
- def regex(regex, error)
8
- lambda do |value|
9
- result = value.to_s[regex]
10
- if result.nil?
11
- raise error[value]
12
- else
13
- result
14
- end
15
- end
16
- end
17
-
18
- public
19
- def phone(phone_number)
20
- #strips out everything but digits from the phone number
21
- phone = phone_number.to_s.gsub(/\D/, '')
22
- if phone.length == 10
23
- phone[/^(\d{3})(\d{3})(\d{4})$/]
24
- "#{$1}-#{$2}-#{$3}"
25
- else
26
- raise Errors.phone[phone_number]
27
- end
28
- end
29
-
30
- def money(money)
31
- value = money.to_s.gsub(/,/, '')[/^\$?(\d+(\.\d+)?)$/, 1]
32
- if value.nil?
33
- raise Errors.money[money]
34
- else
35
- value
36
- end
37
- end
38
-
39
- def datetime(date_time)
40
- if date_time.to_s.upcase == 'ASAP'
41
- 'ASAP'
42
- else
43
- begin
44
- date_time.strftime('%m-%d+%H:%M')
45
- rescue NoMethodError
46
- raise Errors.date_time[date_time]
47
- end
48
- end
49
- end
50
-
51
- def date(date)
52
- if date.to_s.upcase == 'ASAP'
53
- 'ASAP'
54
- else
55
- begin
56
- date.strftime('%m-%d')
57
- rescue NoMethodError
58
- raise Errors.date[date_time]
59
- end
60
- end
61
- end
62
-
63
- def time(time)
64
- if time.to_s.upcase == 'ASAP'
65
- 'ASAP'
66
- else
67
- begin
68
- time.strftime('%m-%d+%H:%M')
69
- rescue NoMethodError
70
- raise Errors.time[date_time]
71
- end
72
- end
73
- end
74
-
75
- def url(url)
76
- url.to_s[/^(https?:\/\/)[-\w.~]+(:\d+)?(\/[-\w.~]+)*/]
77
- end
78
-
79
- def state(state)
80
- state = state.to_s[/^[A-Za-z]{2}$/]
81
- if state.nil?
82
- raise Errors.state[state]
83
- else
84
- state.upcase
85
- end
86
- end
87
-
88
- private
89
- def cc_type(cc_number)
90
- cc_map = {'American Express' => /^3[47]\d{13}$/,
91
- 'Visa' => /^4\d{12}(?:\d{3})?$/,
92
- 'Mastercard' => /^5[1-5]\d{14}$/,
93
- 'Discover' => /^6(?:011|5\d{2})\d{12}$/}
94
-
95
- type = nil
96
- cc_map.each {|key, value| type = key unless cc_number[value].nil?}
97
- type
98
- end
99
-
100
- def luhn_checksum(card_number)
101
- digits = card_number.to_s.scan(/./).map(&:to_i)
102
- checksum = 0
103
- digits.each_index do |index|
104
- digit = digits[index]
105
- if (digits.length-index)%2==1
106
- checksum += digit
107
- else
108
- checksum += 2 * digit
109
- end
110
- end
111
- checksum % 10
112
- end
113
-
114
- def luhn_valid?(card_number)
115
- luhn_checksum(card_number) == 0
116
- end
117
-
118
- public
119
- def credit_card(values)
120
- number, cvc = values
121
- num = number.to_s.gsub(/\D/, '')
122
- unless luhn_valid?(num)
123
- raise Errors.credit_card[number]
124
- end
125
- card_type = cc_type(num)
126
- if card_type.nil?
127
- raise Errors.credit_card[number]
128
- else
129
- if card_type=='American Express'
130
- cvc_length = 4
131
- else
132
- cvc_length = 3
133
- end
134
- if cvc.length == cvc_length and !cvc.to_s[/^\d+$/].nil?
135
- [num, cvc, card_type]
136
- else
137
- raise Errors.cvc[cvc]
138
- end
139
- end
140
- end
141
-
142
- def unchecked(value)
143
- value.to_s
144
- end
145
-
146
- def name(value)
147
- unchecked(value)
148
- end
149
-
150
- def zip(zip)
151
- regex(/^\d{5}$/, Errors.zip)[zip]
152
- end
153
-
154
- def number(num)
155
- regex(/^\d+/, Errors.number)[num]
156
- end
157
-
158
- def year(year)
159
- regex(/^\d{4}$/, Errors.year)[year]
160
- end
161
-
162
- def month(mon)
163
- regex(/^\d{2}$/, Errors.month)[mon]
164
- end
165
-
166
- def email(email)
167
- regex(/^[^@\s]+@[^@\s]+\.[a-zA-Z]{2,3}/, Errors.email)[email]
168
- end
169
-
170
- def nick(nick)
171
- regex(/^[-\w]+/, Errors.nick)[nick]
172
- end
173
-
174
- def alphanum(value)
175
- regex(/^[a-zA-Z\d]+$/, Errors.alphanum)[value]
176
- end
177
- end
178
-
179
- @@normalizer = Normalizers.new
180
-
181
- public
182
- def Normalize.normalize(value, normalizer)
183
- @@normalizer.send(normalizer, value)
184
- end
185
- end
186
- end
1
+ require_relative 'errors'
2
+
3
+ module Ordrin
4
+ module Normalize
5
+ class Normalizers
6
+ private
7
+ def regex(regex, error)
8
+ lambda do |value|
9
+ result = value.to_s[regex]
10
+ if result.nil?
11
+ raise error[value]
12
+ else
13
+ result
14
+ end
15
+ end
16
+ end
17
+
18
+ public
19
+ def phone(phone_number)
20
+ #strips out everything but digits from the phone number
21
+ phone = phone_number.to_s.gsub(/\D/, '')
22
+ if phone.length == 10
23
+ phone[/^(\d{3})(\d{3})(\d{4})$/]
24
+ "#{$1}-#{$2}-#{$3}"
25
+ else
26
+ raise Errors.phone[phone_number]
27
+ end
28
+ end
29
+
30
+ def money(money)
31
+ value = money.to_s.gsub(/,/, '')[/^\$?(\d+(\.\d+)?)$/, 1]
32
+ if value.nil?
33
+ raise Errors.money[money]
34
+ else
35
+ value
36
+ end
37
+ end
38
+
39
+ def datetime(date_time)
40
+ if date_time.to_s.upcase == 'ASAP'
41
+ 'ASAP'
42
+ else
43
+ begin
44
+ date_time.strftime('%m-%d+%H:%M')
45
+ rescue NoMethodError
46
+ raise Errors.date_time[date_time]
47
+ end
48
+ end
49
+ end
50
+
51
+ def date(date)
52
+ if date.to_s.upcase == 'ASAP'
53
+ 'ASAP'
54
+ else
55
+ begin
56
+ date.strftime('%m-%d')
57
+ rescue NoMethodError
58
+ raise Errors.date[date_time]
59
+ end
60
+ end
61
+ end
62
+
63
+ def time(time)
64
+ if time.to_s.upcase == 'ASAP'
65
+ 'ASAP'
66
+ else
67
+ begin
68
+ time.strftime('%m-%d+%H:%M')
69
+ rescue NoMethodError
70
+ raise Errors.time[date_time]
71
+ end
72
+ end
73
+ end
74
+
75
+ def url(url)
76
+ url.to_s[/^(https?:\/\/)[-\w.~]+(:\d+)?(\/[-\w.~]+)*/]
77
+ end
78
+
79
+ def state(state)
80
+ state = state.to_s[/^[A-Za-z]{2}$/]
81
+ if state.nil?
82
+ raise Errors.state[state]
83
+ else
84
+ state.upcase
85
+ end
86
+ end
87
+
88
+ private
89
+ def cc_type(cc_number)
90
+ cc_map = {'American Express' => /^3[47]\d{13}$/,
91
+ 'Visa' => /^4\d{12}(?:\d{3})?$/,
92
+ 'Mastercard' => /^5[1-5]\d{14}$/,
93
+ 'Discover' => /^6(?:011|5\d{2})\d{12}$/}
94
+
95
+ type = nil
96
+ cc_map.each {|key, value| type = key unless cc_number[value].nil?}
97
+ type
98
+ end
99
+
100
+ def luhn_checksum(card_number)
101
+ digits = card_number.to_s.scan(/./).map(&:to_i)
102
+ checksum = 0
103
+ digits.each_index do |index|
104
+ digit = digits[index]
105
+ if (digits.length-index)%2==1
106
+ checksum += digit
107
+ else
108
+ checksum += 2 * digit
109
+ end
110
+ end
111
+ checksum % 10
112
+ end
113
+
114
+ def luhn_valid?(card_number)
115
+ luhn_checksum(card_number) == 0
116
+ end
117
+
118
+ public
119
+ def credit_card(values)
120
+ number, cvc = values
121
+ num = number.to_s.gsub(/\D/, '')
122
+ unless luhn_valid?(num)
123
+ raise Errors.credit_card[number]
124
+ end
125
+ card_type = cc_type(num)
126
+ if card_type.nil?
127
+ raise Errors.credit_card[number]
128
+ else
129
+ if card_type=='American Express'
130
+ cvc_length = 4
131
+ else
132
+ cvc_length = 3
133
+ end
134
+ if cvc.length == cvc_length and !cvc.to_s[/^\d+$/].nil?
135
+ [num, cvc, card_type]
136
+ else
137
+ raise Errors.cvc[cvc]
138
+ end
139
+ end
140
+ end
141
+
142
+ def unchecked(value)
143
+ value.to_s
144
+ end
145
+
146
+ def name(value)
147
+ unchecked(value)
148
+ end
149
+
150
+ def zip(zip)
151
+ regex(/^\d{5}$/, Errors.zip)[zip]
152
+ end
153
+
154
+ def number(num)
155
+ regex(/^\d+/, Errors.number)[num]
156
+ end
157
+
158
+ def year(year)
159
+ regex(/^\d{4}$/, Errors.year)[year]
160
+ end
161
+
162
+ def month(mon)
163
+ regex(/^\d{2}$/, Errors.month)[mon]
164
+ end
165
+
166
+ def email(email)
167
+ regex(/^[^@\s]+@[^@\s]+\.[a-zA-Z]{2,3}/, Errors.email)[email]
168
+ end
169
+
170
+ def nick(nick)
171
+ regex(/^[-\w]+/, Errors.nick)[nick]
172
+ end
173
+
174
+ def alphanum(value)
175
+ regex(/^[a-zA-Z\d]+$/, Errors.alphanum)[value]
176
+ end
177
+ end
178
+
179
+ @@normalizer = Normalizers.new
180
+
181
+ public
182
+ def Normalize.normalize(value, normalizer)
183
+ @@normalizer.send(normalizer, value)
184
+ end
185
+ end
186
+ end
data/lib/ordrin/order.rb CHANGED
@@ -1,79 +1,79 @@
1
- require_relative 'ordrinapi'
2
- require_relative 'normalize'
3
- require_relative 'data'
4
-
5
- module Ordrin
6
- # This class will be used to access the order API. All return values
7
- # are documented at http://ordr.in/developers/order
8
- class OrderApi < OrdrinApi
9
-
10
- private
11
-
12
- #Put all of the data that needs to be passed to the POST request normalized into a dict.
13
- def build_dict(restaurant_id, tray, tip, delivery_date_time, first_name, last_name, address, credit_card, email, login=nil)
14
- data = {'restaurant_id' => Normalize.normalize(restaurant_id, :number),
15
- 'tray' => tray.to_s,
16
- 'tip' => Normalize.normalize(tip, :money),
17
- 'delivery_date' => Normalize.normalize(delivery_date_time, :date)}
18
- if data['delivery_date'] != 'ASAP'
19
- data['delivery_time'] = Normalize.normalize(delivery_date_time, :time)
20
- end
21
- data['first_name'] = Normalize.normalize(first_name, :name)
22
- data['last_name'] = Normalize.normalize(last_name, :name)
23
- begin
24
- data.merge!(address.make_dict)
25
- rescue NoMethodError=>e
26
- data['nick'] = Normalize.normalize(address, :nick)
27
- end
28
- if login.nil?
29
- data['em'] = Normalize.normalize(email, :email)
30
- end
31
- begin
32
- credit_card.make_dict.each_pair do |key, value|
33
- data["card_#{key}"] = value
34
- end
35
- rescue NoMethodError=>e
36
- data['card_nick'] = Normalize.normalize(credit_card, :nick)
37
- end
38
- data['type'] = 'res'
39
- return data
40
- end
41
-
42
- public
43
- # Place an order, either anonymously or as a logged in user. At least one
44
- # of email and login must be passed. If both are passed, email will be ignored.
45
- # Arguments:
46
- # restaurant_id -- Ordr.in's restaurant identifier
47
- # tray -- A tray of food to order. Should be an ordrin.data.Tray object
48
- # tip -- The tip amount
49
- # delivery_date_time -- Either 'ASAP' or a datetime object in the future
50
- # first_name -- The orderer's first name
51
- # last_name -- The orderer's last name
52
- # address -- An address object (Ordrin::Data::Address) or the nickname of a saved address
53
- # credit_card -- A credit card object (Ordrin::Data::CreditCard) or the nickname of a saved credit card
54
- # email -- The email address of an anonymous user
55
- # login -- The logged in user's login information. Should be an ordrin.data.UserLogin object
56
- def order(restaurant_id, tray, tip, delivery_date_time, first_name, last_name, address, credit_card, email=nil, login=nil)
57
- data = build_dict(restaurant_id, tray, tip, delivery_date_time, first_name, last_name, address, credit_card, email, login)
58
- return call_api(:post, ['o', restaurant_id], login, data)
59
- end
60
-
61
- # Place an order and create a user account
62
- # Arguments:
63
- # restaurant_id -- Ordr.in's restaurant identifier
64
- # tray -- A tray of food to order. Should be an ordrin.data.Tray object
65
- # tip -- The tip amount
66
- # delivery_date_time -- Either 'ASAP' or a datetime object in the future
67
- # first_name -- The orderer's first name
68
- # last_name -- The orderer's last name
69
- # address -- An address object (Ordrin::Data::Address) or the nickname of a saved address
70
- # credit_card -- A credit card object (Ordrin::Data::CreditCard) or the nickname of a saved credit card
71
- # email -- The email address of the user
72
- # password -- The user's password (in plain text)
73
- def order_create_user(restaurant_id, tray, tip, delivery_date_time, first_name, last_name, address, credit_card, email, password)
74
- data = build_dict(restaurant_id, tray, tip, delivery_date_time, first_name, last_name, address, credit_card, email)
75
- data['pw'] = Data::UserLogin.hash_password(password)
76
- return call_api(:post, ['o', restaurant_id], nil, data)
77
- end
78
- end
79
- end
1
+ require_relative 'ordrinapi'
2
+ require_relative 'normalize'
3
+ require_relative 'data'
4
+
5
+ module Ordrin
6
+ # This class will be used to access the order API. All return values
7
+ # are documented at http://ordr.in/developers/order
8
+ class OrderApi < OrdrinApi
9
+
10
+ private
11
+
12
+ #Put all of the data that needs to be passed to the POST request normalized into a dict.
13
+ def build_dict(restaurant_id, tray, tip, delivery_date_time, first_name, last_name, address, credit_card, email, login=nil)
14
+ data = {'restaurant_id' => Normalize.normalize(restaurant_id, :number),
15
+ 'tray' => tray.to_s,
16
+ 'tip' => Normalize.normalize(tip, :money),
17
+ 'delivery_date' => Normalize.normalize(delivery_date_time, :date)}
18
+ if data['delivery_date'] != 'ASAP'
19
+ data['delivery_time'] = Normalize.normalize(delivery_date_time, :time)
20
+ end
21
+ data['first_name'] = Normalize.normalize(first_name, :name)
22
+ data['last_name'] = Normalize.normalize(last_name, :name)
23
+ begin
24
+ data.merge!(address.make_dict)
25
+ rescue NoMethodError=>e
26
+ data['nick'] = Normalize.normalize(address, :nick)
27
+ end
28
+ if login.nil?
29
+ data['em'] = Normalize.normalize(email, :email)
30
+ end
31
+ begin
32
+ credit_card.make_dict.each_pair do |key, value|
33
+ data["card_#{key}"] = value
34
+ end
35
+ rescue NoMethodError=>e
36
+ data['card_nick'] = Normalize.normalize(credit_card, :nick)
37
+ end
38
+ data['type'] = 'res'
39
+ return data
40
+ end
41
+
42
+ public
43
+ # Place an order, either anonymously or as a logged in user. At least one
44
+ # of email and login must be passed. If both are passed, email will be ignored.
45
+ # Arguments:
46
+ # restaurant_id -- Ordr.in's restaurant identifier
47
+ # tray -- A tray of food to order. Should be an ordrin.data.Tray object
48
+ # tip -- The tip amount
49
+ # delivery_date_time -- Either 'ASAP' or a datetime object in the future
50
+ # first_name -- The orderer's first name
51
+ # last_name -- The orderer's last name
52
+ # address -- An address object (Ordrin::Data::Address) or the nickname of a saved address
53
+ # credit_card -- A credit card object (Ordrin::Data::CreditCard) or the nickname of a saved credit card
54
+ # email -- The email address of an anonymous user
55
+ # login -- The logged in user's login information. Should be an ordrin.data.UserLogin object
56
+ def order(restaurant_id, tray, tip, delivery_date_time, first_name, last_name, address, credit_card, email=nil, login=nil)
57
+ data = build_dict(restaurant_id, tray, tip, delivery_date_time, first_name, last_name, address, credit_card, email, login)
58
+ return call_api(:post, ['o', restaurant_id], login, data)
59
+ end
60
+
61
+ # Place an order and create a user account
62
+ # Arguments:
63
+ # restaurant_id -- Ordr.in's restaurant identifier
64
+ # tray -- A tray of food to order. Should be an ordrin.data.Tray object
65
+ # tip -- The tip amount
66
+ # delivery_date_time -- Either 'ASAP' or a datetime object in the future
67
+ # first_name -- The orderer's first name
68
+ # last_name -- The orderer's last name
69
+ # address -- An address object (Ordrin::Data::Address) or the nickname of a saved address
70
+ # credit_card -- A credit card object (Ordrin::Data::CreditCard) or the nickname of a saved credit card
71
+ # email -- The email address of the user
72
+ # password -- The user's password (in plain text)
73
+ def order_create_user(restaurant_id, tray, tip, delivery_date_time, first_name, last_name, address, credit_card, email, password)
74
+ data = build_dict(restaurant_id, tray, tip, delivery_date_time, first_name, last_name, address, credit_card, email)
75
+ data['pw'] = Data::UserLogin.hash_password(password)
76
+ return call_api(:post, ['o', restaurant_id], nil, data)
77
+ end
78
+ end
79
+ end
@@ -1,66 +1,66 @@
1
- require_relative 'normalize'
2
- require 'net/http'
3
- require 'json'
4
- require 'digest'
5
-
6
- module Ordrin
7
- # A base object for calling one part of the ordr.in API
8
- class OrdrinApi
9
-
10
- attr_reader :base_url
11
-
12
- # Save the url and key parameters in the object
13
- # Arguments:
14
- # key -- The developer's API key
15
- # base_url -- the url that all API call urls will expand from
16
- def initialize(key, base_url)
17
- @key = key
18
- @base_url = Normalize.normalize(base_url, :url)
19
- end
20
-
21
- protected
22
-
23
- # Calls the api at the saved url and returns the return value as Python data structures.
24
- # Rethrows any api error as a Ruby exception
25
- def call_api(method, arguments, login=nil, data=nil)
26
- methods = {:get => Net::HTTP::Get,
27
- :post => Net::HTTP::Post,
28
- :put => Net::HTTP::Put,
29
- :delete => Net::HTTP::Delete}
30
- method = methods[method]
31
- uri = ('/'+(arguments.collect {|a| URI.encode a.to_s})*'/')
32
- full_url = URI.parse(base_url+uri)
33
- req = method.new(full_url.request_uri)
34
- unless data.nil?
35
- req.body = URI.encode_www_form(data)
36
- end
37
- unless @key.empty?
38
- req['X-NAAMA-CLIENT-AUTHENTICATION'] = "id=\"#{@key}\", version=\"1\""
39
- end
40
- unless login.nil?
41
- hash_code = Digest::SHA256.new.hexdigest("#{login.password}#{login.email}#{uri}")
42
- req['X-NAAMA-AUTHENTICATION'] = "username=\"#{login.email}\", response=\"#{hash_code}\", version=\"1\""
43
- end
44
- http = Net::HTTP.new(full_url.host, full_url.port)
45
- if full_url.scheme == "https"
46
- http.use_ssl = true
47
- http.ca_file = File.join(File.dirname(__FILE__), "cacert.pem")
48
- end
49
- res = http.start {|http| http.request(req)}
50
- #error if not OK response
51
- res.value
52
- result = JSON.parse(res.body)
53
- if result.is_a? Hash
54
- if result.has_key?('_error') and result['_error']!=0
55
- if result.has_key?('text')
56
- raise Errors::ApiError.new(result['msg'], result['text'])
57
- else
58
- raise Errors::ApiError.new(result['msg'])
59
- end
60
- result
61
- end
62
- end
63
- result
64
- end
65
- end
66
- end
1
+ require_relative 'normalize'
2
+ require 'net/http'
3
+ require 'json'
4
+ require 'digest'
5
+
6
+ module Ordrin
7
+ # A base object for calling one part of the ordr.in API
8
+ class OrdrinApi
9
+
10
+ attr_reader :base_url
11
+
12
+ # Save the url and key parameters in the object
13
+ # Arguments:
14
+ # key -- The developer's API key
15
+ # base_url -- the url that all API call urls will expand from
16
+ def initialize(key, base_url)
17
+ @key = key
18
+ @base_url = Normalize.normalize(base_url, :url)
19
+ end
20
+
21
+ protected
22
+
23
+ # Calls the api at the saved url and returns the return value as Python data structures.
24
+ # Rethrows any api error as a Ruby exception
25
+ def call_api(method, arguments, login=nil, data=nil)
26
+ methods = {:get => Net::HTTP::Get,
27
+ :post => Net::HTTP::Post,
28
+ :put => Net::HTTP::Put,
29
+ :delete => Net::HTTP::Delete}
30
+ method = methods[method]
31
+ uri = ('/'+(arguments.collect {|a| URI.encode a.to_s})*'/')
32
+ full_url = URI.parse(base_url+uri)
33
+ req = method.new(full_url.request_uri)
34
+ unless data.nil?
35
+ req.body = URI.encode_www_form(data)
36
+ end
37
+ unless @key.empty?
38
+ req['X-NAAMA-CLIENT-AUTHENTICATION'] = "id=\"#{@key}\", version=\"1\""
39
+ end
40
+ unless login.nil?
41
+ hash_code = Digest::SHA256.new.hexdigest("#{login.password}#{login.email}#{uri}")
42
+ req['X-NAAMA-AUTHENTICATION'] = "username=\"#{login.email}\", response=\"#{hash_code}\", version=\"1\""
43
+ end
44
+ http = Net::HTTP.new(full_url.host, full_url.port)
45
+ if full_url.scheme == "https"
46
+ http.use_ssl = true
47
+ http.ca_file = File.join(File.dirname(__FILE__), "cacert.pem")
48
+ end
49
+ res = http.start {|http| http.request(req)}
50
+ #error if not OK response
51
+ res.value
52
+ result = JSON.parse(res.body)
53
+ if result.is_a? Hash
54
+ if result.has_key?('_error') and result['_error']!=0
55
+ if result.has_key?('text')
56
+ raise Errors::ApiError.new(result['msg'], result['text'])
57
+ else
58
+ raise Errors::ApiError.new(result['msg'])
59
+ end
60
+ result
61
+ end
62
+ end
63
+ result
64
+ end
65
+ end
66
+ end