1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | var qs_module = require('querystring');
|
19 | var url_module = require('url');
|
20 | var crypto_module = require('crypto');
|
21 | var http_module = require('http');
|
22 | var https_module = require('https');
|
23 | var FileStreamer = require('./filestreamer');
|
24 |
|
25 | module.exports.request_defaults = {
|
26 | protocol : 'https:',
|
27 | hostname : 'api.vimeo.com',
|
28 | port : 443,
|
29 | method : 'GET',
|
30 | query : {},
|
31 | headers : {
|
32 | Accept: "application/vnd.vimeo.*+json;version=3.2",
|
33 | 'User-Agent': 'Vimeo.js/1.2.1'
|
34 | }
|
35 | };
|
36 |
|
37 | var auth_endpoints = module.exports.auth_endpoints = {
|
38 | authorization : '/oauth/authorize',
|
39 | accessToken : '/oauth/access_token',
|
40 | clientCredentials : '/oauth/authorize/client'
|
41 | };
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 | var Vimeo = module.exports.Vimeo = function Vimeo (client_id, client_secret, access_token) {
|
51 | this._client_id = client_id;
|
52 | this._client_secret = client_secret;
|
53 |
|
54 | if (access_token) {
|
55 | this.access_token = access_token;
|
56 | }
|
57 | };
|
58 |
|
59 | Vimeo.prototype._client_id = null;
|
60 | Vimeo.prototype._client_secret = null;
|
61 | Vimeo.prototype.access_token = null;
|
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 | Vimeo.prototype.request = function vimeo_request (options, callback) {
|
87 | var client = null;
|
88 |
|
89 |
|
90 | if (typeof options === "string") {
|
91 | options = url_module.parse(options, true);
|
92 | options.method = "GET";
|
93 | }
|
94 |
|
95 |
|
96 | if (typeof options.path !== "string") {
|
97 | return callback(new Error('You must provide an api path'));
|
98 | }
|
99 |
|
100 |
|
101 | if (options.path.charAt(0) !== '/') {
|
102 | options.path = '/' + options.path;
|
103 | }
|
104 |
|
105 |
|
106 | var request_options = this._buildRequestOptions(options);
|
107 |
|
108 |
|
109 | client = request_options.protocol === 'https:' ? https_module : http_module;
|
110 |
|
111 |
|
112 | if (['POST','PATCH','PUT','DELETE'].indexOf(request_options.method) !== -1) {
|
113 | if (request_options.headers['Content-Type'] === 'application/json') {
|
114 | request_options.body = JSON.stringify(options.query);
|
115 | } else {
|
116 | request_options.body = qs_module.stringify(options.query);
|
117 | }
|
118 |
|
119 | if (request_options.body) {
|
120 | request_options.headers['Content-Length'] = Buffer.byteLength(request_options.body, 'utf8');
|
121 | } else {
|
122 | request_options.headers['Content-Length'] = 0;
|
123 | }
|
124 | }
|
125 |
|
126 |
|
127 | var req = client.request(request_options, this._handleRequest(callback));
|
128 |
|
129 |
|
130 | if (request_options.body) {
|
131 | req.write(request_options.body);
|
132 | }
|
133 |
|
134 |
|
135 | req.on('error', function(e) {
|
136 | callback(e);
|
137 | });
|
138 |
|
139 |
|
140 | req.end();
|
141 | };
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 |
|
149 | Vimeo.prototype._handleRequest = function (callback) {
|
150 | return function (res) {
|
151 | res.setEncoding('utf8');
|
152 |
|
153 | var buffer = '';
|
154 |
|
155 | res.on('readable', function () {
|
156 | buffer += res.read() || '';
|
157 | });
|
158 |
|
159 | if (res.statusCode >= 400) {
|
160 |
|
161 | res.on('end', function () {
|
162 | var err = new Error(buffer);
|
163 | callback(err, buffer, res.statusCode, res.headers);
|
164 | });
|
165 | } else {
|
166 |
|
167 | res.on('end', function () {
|
168 | try {
|
169 | var body = buffer.length ? JSON.parse(buffer) : {};
|
170 | } catch (e) {
|
171 | return callback(buffer, buffer, res.statusCode, res.headers);
|
172 | }
|
173 | callback(null, body, res.statusCode, res.headers);
|
174 | });
|
175 | }
|
176 | };
|
177 | };
|
178 |
|
179 |
|
180 |
|
181 |
|
182 |
|
183 |
|
184 |
|
185 | Vimeo.prototype._buildRequestOptions = function (options) {
|
186 |
|
187 | var request_options = this._applyDefaultRequestOptions(options);
|
188 |
|
189 |
|
190 | if (this.access_token) {
|
191 | request_options.headers.Authorization = 'Bearer ' + this.access_token;
|
192 | } else if (this._client_id && this._client_secret) {
|
193 | request_options.headers.Authorization = 'Basic ' + new Buffer(this._client_id + ':' + this._client_secret).toString('base64');
|
194 | }
|
195 |
|
196 |
|
197 | if (['POST','PATCH','PUT','DELETE'].indexOf(request_options.method) !== -1 && !request_options.headers['Content-Type']) {
|
198 | request_options.headers['Content-Type'] = 'application/json';
|
199 |
|
200 |
|
201 | } else if (request_options.method === 'GET') {
|
202 | request_options.path = this._applyQuerystringParams(request_options, options);
|
203 | }
|
204 |
|
205 | return request_options;
|
206 | }
|
207 |
|
208 |
|
209 |
|
210 |
|
211 |
|
212 |
|
213 |
|
214 | Vimeo.prototype._applyDefaultRequestOptions = function (options) {
|
215 | var request_options = {
|
216 | protocol : options.protocol || module.exports.request_defaults.protocol,
|
217 | host : options.hostname || module.exports.request_defaults.hostname,
|
218 | port : options.port || module.exports.request_defaults.port,
|
219 | method : options.method || module.exports.request_defaults.method,
|
220 | headers : options.headers || {},
|
221 | body : '',
|
222 | path : options.path
|
223 | };
|
224 | var key = null;
|
225 |
|
226 |
|
227 | if (module.exports.request_defaults.headers) {
|
228 | for (key in module.exports.request_defaults.headers) {
|
229 | if (!request_options.headers[key]) {
|
230 | request_options.headers[key] = module.exports.request_defaults.headers[key];
|
231 | }
|
232 | }
|
233 | }
|
234 |
|
235 | return request_options;
|
236 | }
|
237 |
|
238 |
|
239 |
|
240 |
|
241 |
|
242 |
|
243 |
|
244 |
|
245 | Vimeo.prototype._applyQuerystringParams = function (request_options, options) {
|
246 | var querystring = '';
|
247 |
|
248 | if (!options.query) {
|
249 | return request_options.path;
|
250 | }
|
251 |
|
252 |
|
253 | if (Object.keys(options.query).length) {
|
254 | if (request_options.path.indexOf('?') < 0) {
|
255 |
|
256 | querystring = '?' + qs_module.stringify(options.query);
|
257 | } else {
|
258 |
|
259 | querystring = '&' + qs_module.stringify(options.query);
|
260 | }
|
261 | }
|
262 |
|
263 | return request_options.path + querystring;
|
264 | }
|
265 |
|
266 |
|
267 |
|
268 |
|
269 |
|
270 |
|
271 |
|
272 |
|
273 |
|
274 | Vimeo.prototype.accessToken = function (code, redirect_uri, fn) {
|
275 | var _self = this;
|
276 |
|
277 | this.request({
|
278 | method : 'POST',
|
279 | hostname : module.exports.request_defaults.hostname,
|
280 | path : auth_endpoints.accessToken,
|
281 | query : {
|
282 | grant_type : 'authorization_code',
|
283 | code : code,
|
284 | redirect_uri : redirect_uri
|
285 | },
|
286 | headers : {
|
287 | 'Content-Type' : 'application/x-www-form-urlencoded'
|
288 | }
|
289 | }, function (err, body, status, headers) {
|
290 | if (err) {
|
291 | return fn(err, null, status, headers);
|
292 | } else {
|
293 | fn(null, body, status, headers);
|
294 | }
|
295 | });
|
296 | };
|
297 |
|
298 |
|
299 |
|
300 |
|
301 |
|
302 |
|
303 |
|
304 |
|
305 |
|
306 |
|
307 |
|
308 |
|
309 |
|
310 |
|
311 |
|
312 |
|
313 | Vimeo.prototype.buildAuthorizationEndpoint = function (redirect_uri, scope, state) {
|
314 | var query = {
|
315 | response_type : 'code',
|
316 | client_id : this._client_id,
|
317 | redirect_uri : redirect_uri
|
318 | };
|
319 |
|
320 | if (scope) {
|
321 | if (Array.isArray(scope)) {
|
322 | query.scope = scope.join(' ');
|
323 | } else {
|
324 | query.scope = scope;
|
325 | }
|
326 | } else {
|
327 | query.scope = 'public';
|
328 | }
|
329 |
|
330 | if (state) {
|
331 | query.state = state;
|
332 | }
|
333 |
|
334 | return module.exports.request_defaults.protocol + '//' + module.exports.request_defaults.hostname + auth_endpoints.authorization + '?' + qs_module.stringify(query);
|
335 | };
|
336 |
|
337 |
|
338 |
|
339 |
|
340 |
|
341 |
|
342 |
|
343 | Vimeo.prototype.generateClientCredentials = function (scope, fn) {
|
344 | var query = {
|
345 | grant_type : 'client_credentials',
|
346 | }
|
347 |
|
348 | if (scope) {
|
349 | if (Array.isArray(scope)) {
|
350 | query.scope = scope.join(' ');
|
351 | } else {
|
352 | query.scope = scope;
|
353 | }
|
354 | } else {
|
355 | query.scope = 'public';
|
356 | }
|
357 |
|
358 | this.request({
|
359 | method : 'POST',
|
360 | hostname : module.exports.request_defaults.hostname,
|
361 | path : auth_endpoints.clientCredentials,
|
362 | query : query,
|
363 | headers : {
|
364 | 'Content-Type' : 'application/x-www-form-urlencoded'
|
365 | }
|
366 | }, function (err, body, status, headers) {
|
367 | if (err) {
|
368 | return fn(err, null, status, headers);
|
369 | } else {
|
370 | fn(null, body, status, headers);
|
371 | }
|
372 | });
|
373 | }
|
374 |
|
375 |
|
376 |
|
377 |
|
378 |
|
379 |
|
380 |
|
381 | Vimeo.prototype.streamingUpload = function (path, video_uri, callback, progress_callback) {
|
382 | var _self = this;
|
383 |
|
384 | if (typeof video_uri === 'function') {
|
385 | progress_callback = callback;
|
386 | callback = video_uri;
|
387 | video_uri = undefined;
|
388 | }
|
389 |
|
390 | var options = {
|
391 | method : video_uri ? 'PUT' : 'POST',
|
392 | path : video_uri ? video_uri + '/files' : '/me/videos',
|
393 | query : {
|
394 | type : 'streaming'
|
395 | }
|
396 | };
|
397 |
|
398 | this.request(options, function (err, ticket, status, headers) {
|
399 | if (err) {
|
400 | return callback(err);
|
401 | }
|
402 |
|
403 | var file = new FileStreamer(path, ticket.upload_link_secure, progress_callback);
|
404 |
|
405 | file.ready(function () {
|
406 | _self.request({
|
407 | method : 'DELETE',
|
408 | path : ticket.complete_uri
|
409 | }, callback);
|
410 | });
|
411 |
|
412 | file.error(callback);
|
413 | file.upload();
|
414 | });
|
415 | };
|