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.1.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 | var request_options = this._buildRequestOptions(options);
|
102 |
|
103 |
|
104 | client = request_options.protocol === 'https:' ? https_module : http_module;
|
105 |
|
106 |
|
107 | var req = client.request(request_options, this._handleRequest(callback));
|
108 |
|
109 |
|
110 | if (['POST','PATCH','PUT','DELETE'].indexOf(request_options.method) !== -1) {
|
111 | if (request_options.headers['Content-Type'] === 'application/json') {
|
112 | request_options.body = JSON.stringify(options.query);
|
113 | } else {
|
114 | request_options.body = qs_module.stringify(options.query);
|
115 | }
|
116 |
|
117 | if (request_options.body) {
|
118 | req.write(request_options.body);
|
119 | }
|
120 | }
|
121 |
|
122 |
|
123 | req.on('error', function(e) {
|
124 | callback(e);
|
125 | });
|
126 |
|
127 |
|
128 | req.end();
|
129 | };
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 |
|
136 |
|
137 | Vimeo.prototype._handleRequest = function (callback) {
|
138 | return function (res) {
|
139 | res.setEncoding('utf8');
|
140 |
|
141 | var buffer = '';
|
142 |
|
143 | res.on('readable', function () {
|
144 | buffer += res.read() || '';
|
145 | });
|
146 |
|
147 | if (res.statusCode >= 400) {
|
148 |
|
149 | res.on('end', function () {
|
150 | var err = new Error(buffer);
|
151 | callback(err, buffer, res.statusCode, res.headers);
|
152 | });
|
153 | } else {
|
154 |
|
155 | res.on('end', function () {
|
156 | try {
|
157 | var body = buffer.length ? JSON.parse(buffer) : {};
|
158 | } catch (e) {
|
159 | return callback(buffer, buffer, res.statusCode, res.headers);
|
160 | }
|
161 | callback(null, body, res.statusCode, res.headers);
|
162 | });
|
163 | }
|
164 | };
|
165 | };
|
166 |
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 | Vimeo.prototype._buildRequestOptions = function (options) {
|
174 |
|
175 | var request_options = this._applyDefaultRequestOptions(options);
|
176 |
|
177 |
|
178 | if (this.access_token) {
|
179 | request_options.headers.Authorization = 'Bearer ' + this.access_token;
|
180 | } else if (this._client_id && this._client_secret) {
|
181 | request_options.headers.Authorization = 'Basic ' + new Buffer(this._client_id + ':' + this._client_secret).toString('base64');
|
182 | }
|
183 |
|
184 |
|
185 | if (['POST','PATCH','PUT','DELETE'].indexOf(request_options.method) !== -1 && !request_options.headers['Content-Type']) {
|
186 | request_options.headers['Content-Type'] = 'application/json';
|
187 |
|
188 |
|
189 | } else if (request_options.method === 'GET') {
|
190 | request_options.path = this._applyQuerystringParams(request_options, options);
|
191 | }
|
192 |
|
193 | return request_options;
|
194 | }
|
195 |
|
196 |
|
197 |
|
198 |
|
199 |
|
200 |
|
201 |
|
202 | Vimeo.prototype._applyDefaultRequestOptions = function (options) {
|
203 | var request_options = {
|
204 | protocol : options.protocol || module.exports.request_defaults.protocol,
|
205 | host : options.hostname || module.exports.request_defaults.hostname,
|
206 | port : options.port || module.exports.request_defaults.port,
|
207 | method : options.method || module.exports.request_defaults.method,
|
208 | headers : options.headers || {},
|
209 | body : '',
|
210 | path : options.path
|
211 | };
|
212 | var key = null;
|
213 |
|
214 |
|
215 | if (module.exports.request_defaults.headers) {
|
216 | for (key in module.exports.request_defaults.headers) {
|
217 | if (!request_options.headers[key]) {
|
218 | request_options.headers[key] = module.exports.request_defaults.headers[key];
|
219 | }
|
220 | }
|
221 | }
|
222 |
|
223 | return request_options;
|
224 | }
|
225 |
|
226 |
|
227 |
|
228 |
|
229 |
|
230 |
|
231 |
|
232 |
|
233 | Vimeo.prototype._applyQuerystringParams = function (request_options, options) {
|
234 | var querystring = '';
|
235 |
|
236 | if (!options.query) {
|
237 | return request_options.path;
|
238 | }
|
239 |
|
240 |
|
241 | if (Object.keys(options.query).length) {
|
242 | if (request_options.path.indexOf('?') < 0) {
|
243 |
|
244 | querystring = '?' + qs_module.stringify(options.query);
|
245 | } else {
|
246 |
|
247 | querystring = '&' + qs_module.stringify(options.query);
|
248 | }
|
249 | }
|
250 |
|
251 | return request_options.path + querystring;
|
252 | }
|
253 |
|
254 |
|
255 |
|
256 |
|
257 |
|
258 |
|
259 |
|
260 |
|
261 |
|
262 | Vimeo.prototype.accessToken = function (code, redirect_uri, fn) {
|
263 | var _self = this;
|
264 |
|
265 | this.request({
|
266 | method : 'POST',
|
267 | hostname : module.exports.request_defaults.hostname,
|
268 | path : auth_endpoints.accessToken,
|
269 | query : {
|
270 | grant_type : 'authorization_code',
|
271 | code : code,
|
272 | redirect_uri : redirect_uri
|
273 | },
|
274 | headers : {
|
275 | 'Content-Type' : 'application/x-www-form-urlencoded'
|
276 | }
|
277 | }, function (err, body, status, headers) {
|
278 | if (err) {
|
279 | return fn(err, null, status, headers);
|
280 | } else {
|
281 | fn(null, body, status, headers);
|
282 | }
|
283 | });
|
284 | };
|
285 |
|
286 |
|
287 |
|
288 |
|
289 |
|
290 |
|
291 |
|
292 |
|
293 |
|
294 |
|
295 |
|
296 |
|
297 |
|
298 |
|
299 |
|
300 |
|
301 | Vimeo.prototype.buildAuthorizationEndpoint = function (redirect_uri, scope, state) {
|
302 | var query = {
|
303 | response_type : 'code',
|
304 | client_id : this._client_id,
|
305 | redirect_uri : redirect_uri
|
306 | };
|
307 |
|
308 | if (scope) {
|
309 | if (Array.isArray(scope)) {
|
310 | query.scope = scope.join(' ');
|
311 | } else {
|
312 | query.scope = scope;
|
313 | }
|
314 | } else {
|
315 | query.scope = 'public';
|
316 | }
|
317 |
|
318 | if (state) {
|
319 | query.state = state;
|
320 | }
|
321 |
|
322 | return module.exports.request_defaults.protocol + '//' + module.exports.request_defaults.hostname + auth_endpoints.authorization + '?' + qs_module.stringify(query);
|
323 | };
|
324 |
|
325 |
|
326 |
|
327 |
|
328 |
|
329 |
|
330 |
|
331 | Vimeo.prototype.generateClientCredentials = function (scope, fn) {
|
332 | var query = {
|
333 | grant_type : 'client_credentials',
|
334 | }
|
335 |
|
336 | if (scope) {
|
337 | if (Array.isArray(scope)) {
|
338 | query.scope = scope.join(' ');
|
339 | } else {
|
340 | query.scope = scope;
|
341 | }
|
342 | } else {
|
343 | query.scope = 'public';
|
344 | }
|
345 |
|
346 | this.request({
|
347 | method : 'POST',
|
348 | hostname : module.exports.request_defaults.hostname,
|
349 | path : auth_endpoints.clientCredentials,
|
350 | query : query,
|
351 | headers : {
|
352 | 'Content-Type' : 'application/x-www-form-urlencoded'
|
353 | }
|
354 | }, function (err, body, status, headers) {
|
355 | if (err) {
|
356 | return fn(err, null, status, headers);
|
357 | } else {
|
358 | fn(null, body, status, headers);
|
359 | }
|
360 | });
|
361 | }
|
362 |
|
363 |
|
364 |
|
365 |
|
366 |
|
367 |
|
368 |
|
369 | Vimeo.prototype.streamingUpload = function (path, video_uri, callback) {
|
370 | var _self = this;
|
371 |
|
372 | if (!callback) {
|
373 | callback = video_uri;
|
374 | video_uri = undefined;
|
375 | }
|
376 |
|
377 | var options = {
|
378 | method : video_uri ? 'PUT' : 'POST',
|
379 | path : video_uri ? video_uri + '/files' : '/me/videos',
|
380 | query : {
|
381 | type : 'streaming'
|
382 | }
|
383 | };
|
384 |
|
385 | this.request(options, function (err, ticket, status, headers) {
|
386 | if (err) {
|
387 | return callback(err);
|
388 | }
|
389 |
|
390 | var file = new FileStreamer(path, ticket.upload_link_secure);
|
391 |
|
392 | file.ready(function () {
|
393 | _self.request({
|
394 | method : 'DELETE',
|
395 | path : ticket.complete_uri
|
396 | }, callback);
|
397 | });
|
398 |
|
399 | file.error(callback);
|
400 | file.upload();
|
401 | });
|
402 | };
|