-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathVerificationServiceHttpClientHelper.py
262 lines (223 loc) · 9.32 KB
/
VerificationServiceHttpClientHelper.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
import http.client
import urllib.parse
import json
import time
from contextlib import closing
import ProfileCreationResponse
import EnrollmentResponse
import VerificationResponse
import VerificationProfile
import logging
class VerificationServiceHttpClientHelper:
"""Abstracts the interaction with the Verification service."""
_STATUS_OK = 200
_BASE_URI = 'api.projectoxford.ai'
_VERIFICATION_PROFILES_URI = '/spid/v1.0/verificationProfiles'
_VERIFICATION_URI = '/spid/v1.0/verify'
_SUBSCRIPTION_KEY_HEADER = 'Ocp-Apim-Subscription-Key'
_CONTENT_TYPE_HEADER = 'Content-Type'
_JSON_CONTENT_HEADER_VALUE = 'application/json'
_STREAM_CONTENT_HEADER_VALUE = 'application/octet-stream'
def __init__(self, subscription_key):
"""Constructor of the VerificationServiceHttpClientHelper class.
Arguments:
subscription_key -- the subscription key string
"""
self._subscription_key = subscription_key
def get_all_profiles(self):
"""Return a list of all profiles on the server."""
try:
# Send the request
res, message = self._send_request(
'GET',
self._BASE_URI,
self._VERIFICATION_PROFILES_URI,
self._JSON_CONTENT_HEADER_VALUE)
if res.status == self._STATUS_OK:
# Parse the response body
profiles_raw = json.loads(message)
return [VerificationProfile.VerificationProfile(profiles_raw[i])
for i in range(0, len(profiles_raw))]
else:
reason = reason if not message else message
raise Exception('Error getting all profiles: ' + reason)
except:
logging.error('Error getting all profiles.')
raise
def create_profile(self, locale):
"""Creates a profile on the server and returns a dictionary of the creation response.
Arguments:
locale -- the locale string for the profile
"""
try:
# Prepare the body of the message
body = json.dumps({'locale': '{0}'.format(locale)})
# Send the request
res, message = self._send_request(
'POST',
self._BASE_URI,
self._VERIFICATION_PROFILES_URI,
self._JSON_CONTENT_HEADER_VALUE,
body)
if res.status == self._STATUS_OK:
# Parse the response body
return ProfileCreationResponse.ProfileCreationResponse(json.loads(message))
else:
reason = res.reason if not message else message
raise Exception('Error creating profile: ' + reason)
except:
logging.error('Error creating profile.')
raise
def get_profile(self, profile_id):
"""Get a speaker's profile with given profile ID
Arguments:
subscription_key -- the subscription key string
profile_id -- the profile ID of the profile to resets
"""
try:
# Prepare the request
request_url = '{0}/{1}'.format(
self._VERIFICATION_PROFILES_URI,
urllib.parse.quote(profile_id))
# Send the request
res, message = self._send_request(
'GET',
self._BASE_URI,
request_url,
self._JSON_CONTENT_HEADER_VALUE)
if res.status == self._STATUS_OK:
# Parse the response body
profile_raw = json.loads(message)
return VerificationProfile.VerificationProfile(profile_raw)
else:
reason = reason if not message else message
raise Exception('Error getting profile: ' + reason)
except:
logging.error('Error getting profile')
raise
def delete_profile(self, profile_id):
"""Delete the given profile from the server
Arguments:
profile_id -- the profile ID of the profile to delete
"""
try:
# Prepare the request
request_url = '{0}/{1}'.format(
self._VERIFICATION_PROFILES_URI,
urllib.parse.quote(profile_id))
# Send the request
res, message = self._send_request(
'DELETE',
self._BASE_URI,
request_url,
self._JSON_CONTENT_HEADER_VALUE)
if res.status != self._STATUS_OK:
reason = res.reason if not message else message
raise Exception('Error deleting profile: ' + reason)
except:
logging.error('Error deleting profile')
raise
def reset_enrollments(self, profile_id):
"""Reset enrollments of a given profile from the server
Arguments:
profile_id -- the profile ID of the profile to reset
"""
try:
# prepare the request
request_url = '{0}/{1}/reset?'.format(
self._VERIFICATION_PROFILES_URI,
urllib.parse.quote(profile_id))
# Send the request
res, message = self._send_request(
'POST',
self._BASE_URI,
request_url,
self._JSON_CONTENT_HEADER_VALUE)
if res.status != self._STATUS_OK:
reason = res.reason if not message else message
raise Exception('Error resetting profile: ' + reason)
except:
logging.error('Error resetting profile')
raise
def enroll_profile(self, profile_id, file_path):
"""Enrolls a profile using an audio file and returns a
dictionary of the enrollment response.
Arguments:
profile_id -- the profile ID string of the user to enroll
file_path -- the file path string of the audio file to use
"""
try:
# Prepare the request
request_url = '{0}/{1}/enroll'.format(
self._VERIFICATION_PROFILES_URI,
urllib.parse.quote(profile_id))
# Prepare the body of the message
with open(file_path, 'rb') as body:
# Send the request
res, message = self._send_request(
'POST',
self._BASE_URI,
request_url,
self._STREAM_CONTENT_HEADER_VALUE,
body)
if res.status == self._STATUS_OK:
# Parse the response body
return EnrollmentResponse.EnrollmentResponse(json.loads(message))
else:
reason = res.reason if not message else message
raise Exception('Error enrolling profile: ' + reason)
except:
logging.error('Error enrolling profile.')
raise
def verify_file(self, file_path, profile_id):
"""Verifies a profile using an audio file and returns a
Arguments:
file_path -- the file path of the audio file to test
profile_id -- a profile to test against
"""
try:
# Prepare the request
request_url = '{0}?verificationProfileId={1}'.format(
self._VERIFICATION_URI,
urllib.parse.quote(profile_id))
# Prepare the body of the message
with open(file_path, 'rb') as body:
# Send the request
res, message = self._send_request(
'POST',
self._BASE_URI,
request_url,
self._STREAM_CONTENT_HEADER_VALUE,
body)
if res.status == self._STATUS_OK:
# Parse the response body
return VerificationResponse.VerificationResponse(json.loads(message))
else:
reason = res.reason if not message else message
raise Exception('Error verifying audio from file: ' + reason)
except:
logging.error('Error performing verification.')
raise
def _send_request(self, method, base_url, request_url, content_type_value, body=None):
"""Sends the request to the server then returns the response and the response body string.
Arguments:
method -- specifies whether the request is a GET or POST request
base_url -- the base url for the connection
request_url -- the request url for the connection
content_type_value -- the value of the content type field in the headers
body -- the body of the request (needed only in POST methods)
"""
try:
# Set the headers
headers = {self._CONTENT_TYPE_HEADER: content_type_value,
self._SUBSCRIPTION_KEY_HEADER: self._subscription_key}
# Start the connection
with closing(http.client.HTTPSConnection(base_url)) as conn:
# Send the request
conn.request(method, request_url, body, headers)
res = conn.getresponse()
message = res.read().decode('utf-8')
return res, message
except:
logging.error('Error sending the request.')
raise