diff --git a/lib-es5/uploader.js b/lib-es5/uploader.js index f45979a4..c5e6fa84 100644 --- a/lib-es5/uploader.js +++ b/lib-es5/uploader.js @@ -34,6 +34,7 @@ var Cache = require('./cache'); var utils = require("./utils"); var UploadStream = require('./upload_stream'); var config = require("./config"); +var ensureOption = require('./utils/ensureOption').defaults(config()); var build_upload_params = utils.build_upload_params, extend = utils.extend, @@ -219,6 +220,29 @@ exports.create_zip = function create_zip(callback) { return exports.create_archive(callback, options, "zip"); }; +exports.create_slideshow = function create_slideshow(options, callback) { + options.resource_type = ensureOption(options, "resource_type", "video"); + return call_api("create_slideshow", callback, options, function () { + // Generate a transformation from the manifest_transformation key, which should be a valid transformation + var manifest_transformation = utils.generate_transformation_string(extend({}, options.manifest_transformation)); + + // Try to use all the options to generate a transformation (Example: options.width and options.height) + var transformation = utils.generate_transformation_string(extend({}, ensureOption(options, 'transformation', {}))); + + return [{ + timestamp: utils.timestamp(), + manifest_transformation: manifest_transformation, + upload_preset: options.upload_preset, + overwrite: options.overwrite, + public_id: options.public_id, + notification_url: options.notification_url, + manifest_json: options.manifest_json, + tags: options.tags, + transformation: transformation + }]; + }); +}; + exports.destroy = function destroy(public_id, callback) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; diff --git a/lib-es5/v2/uploader.js b/lib-es5/v2/uploader.js index 844e1a09..de6cbaf2 100644 --- a/lib-es5/v2/uploader.js +++ b/lib-es5/v2/uploader.js @@ -34,4 +34,5 @@ exports.direct_upload = uploader.direct_upload; exports.upload_tag_params = uploader.upload_tag_params; exports.upload_url = uploader.upload_url; exports.image_upload_tag = uploader.image_upload_tag; -exports.unsigned_image_upload_tag = uploader.unsigned_image_upload_tag; \ No newline at end of file +exports.unsigned_image_upload_tag = uploader.unsigned_image_upload_tag; +exports.create_slideshow = uploader.create_slideshow; \ No newline at end of file diff --git a/lib/uploader.js b/lib/uploader.js index 698db098..b3eaf217 100644 --- a/lib/uploader.js +++ b/lib/uploader.js @@ -14,6 +14,7 @@ const Cache = require('./cache'); const utils = require("./utils"); const UploadStream = require('./upload_stream'); const config = require("./config"); +const ensureOption = require('./utils/ensureOption').defaults(config()); const { build_upload_params, @@ -167,6 +168,33 @@ exports.create_zip = function create_zip(callback, options = {}) { return exports.create_archive(callback, options, "zip"); }; + +exports.create_slideshow = function create_slideshow(options, callback) { + options.resource_type = ensureOption(options, "resource_type", "video"); + return call_api("create_slideshow", callback, options, function () { + // Generate a transformation from the manifest_transformation key, which should be a valid transformation + const manifest_transformation = utils.generate_transformation_string(extend({}, options.manifest_transformation)); + + // Try to use {options.transformation} to generate a transformation (Example: options.transformation.width, options.transformation.height) + const transformation = utils.generate_transformation_string(extend({}, ensureOption(options, 'transformation', {}))); + + return [ + { + timestamp: utils.timestamp(), + manifest_transformation: manifest_transformation, + upload_preset: options.upload_preset, + overwrite: options.overwrite, + public_id: options.public_id, + notification_url: options.notification_url, + manifest_json: options.manifest_json, + tags: options.tags, + transformation: transformation + } + ]; + }); +}; + + exports.destroy = function destroy(public_id, callback, options = {}) { return call_api("destroy", callback, options, function () { return [ diff --git a/lib/v2/uploader.js b/lib/v2/uploader.js index 7f931cb9..9c4e5d10 100644 --- a/lib/v2/uploader.js +++ b/lib/v2/uploader.js @@ -33,3 +33,4 @@ exports.upload_tag_params = uploader.upload_tag_params; exports.upload_url = uploader.upload_url; exports.image_upload_tag = uploader.image_upload_tag; exports.unsigned_image_upload_tag = uploader.unsigned_image_upload_tag; +exports.create_slideshow = uploader.create_slideshow; diff --git a/test/integration/api/provisioning/account_spec.js b/test/integration/api/provisioning/account_spec.js index d0400dcc..cd0f9bd4 100644 --- a/test/integration/api/provisioning/account_spec.js +++ b/test/integration/api/provisioning/account_spec.js @@ -8,10 +8,10 @@ runOnlyForInternalPRs('account API - Provisioning', function () { let CLOUD_API; let CLOUD_NAME; let CLOUD_ID; - let USER_NAME_1 = `SDK TEST ${Date.now()}`; - let USER_NAME_2 = `SDK TEST 2 ${Date.now()}`; - let USER_EMAIL_1 = `sdk-test+${Date.now()}@cloudinary.com`; - let USER_EMAIL_2 = `sdk-test2+${Date.now()}@cloudinary.com`; + let USER_NAME_1 = `NODE TEST ${Date.now()}`; + let USER_NAME_2 = `NODE TEST 2 ${Date.now()}`; + let USER_EMAIL_1 = `node-test+${Date.now()}@cloudinary.com`; + let USER_EMAIL_2 = `node-test2+${Date.now()}@cloudinary.com`; let USER_ROLE = 'billing'; let USER_ID_1; let USER_ID_2; diff --git a/test/integration/api/uploader/slideshow_spec.js b/test/integration/api/uploader/slideshow_spec.js new file mode 100644 index 00000000..1a82cf3b --- /dev/null +++ b/test/integration/api/uploader/slideshow_spec.js @@ -0,0 +1,104 @@ +const Q = require('q'); +const cloudinary = require("../../../../cloudinary"); +const describe = require('../../../testUtils/suite'); +const TEST_ID = Date.now(); + +const createTestConfig = require('../../../testUtils/createTestConfig'); + +const testConstants = require('../../../testUtils/testConstants'); +const UPLOADER_V2 = cloudinary.v2.uploader; + +const { + TIMEOUT, + TAGS +} = testConstants; + +const { + TEST_TAG +} = TAGS; + +require('jsdom-global')(); + +describe("create slideshow tests", function () { + this.timeout(TIMEOUT.LONG); + after(function () { + var config = cloudinary.config(true); + if (!(config.api_key && config.api_secret)) { + expect().fail("Missing key and secret. Please set CLOUDINARY_URL."); + } + return Q.allSettled([ + !cloudinary.config().keep_test_products ? cloudinary.v2.api.delete_resources_by_tag(TEST_TAG) : void 0, + !cloudinary.config().keep_test_products ? cloudinary.v2.api.delete_resources_by_tag(TEST_TAG, + { + resource_type: "video" + }) : void 0 + ]); + }); + beforeEach(function () { + cloudinary.config(true); + cloudinary.config(createTestConfig()); + }); + + + it("should successfully create slideshow", async function () { + // this.timeout(TIMEOUT.LONG); + const slideshowManifest + = 'w_352;h_240;du_5;fps_30;vars_(slides_((media_s64:aHR0cHM6Ly9y' + + 'ZXMuY2xvdWRpbmFyeS5jb20vZGVtby9pbWFnZS91cGxvYWQvY291cGxl);(media_s64:aH' + + 'R0cHM6Ly9yZXMuY2xvdWRpbmFyeS5jb20vZGVtby9pbWFnZS91cGxvYWQvc2FtcGxl)))'; + + const slideshowManifestJson = { + "w": 848, + "h": 480, + "du": 6, + "fps": 30, + "vars": { + "sdur": 500, + "tdur": 500, + "slides": [ + { + "media": "i:protests9" + }, { + "media": "i:protests8" + }, + { + "media": "i:protests7" + }, + { + "media": "i:protests6" + }, + { + "media": "i:protests2" + }, + { + "media": "i:protests1" + } + ] + } + } + + + const res = await UPLOADER_V2.create_slideshow({ + manifest_transformation: { + custom_function: { + function_type: 'render', + source: slideshowManifest + } + }, + transformation: { + width: 100, + height: 100, + crop: 'scale' + }, + // manifest_json: slideshowManifestJson, + tags: [TEST_TAG], + overwrite: true, + public_id: TEST_ID, + notification_url: 'https://example.com' + }); + + expect(res.status).to.be('processing'); + expect(res.public_id).to.be(TEST_ID.toString()); // TestID is int, Server returns a string and not an int. + expect(res.batch_id.length).to.be.above(5); // some long string + }) +}) diff --git a/types/cloudinary_ts_spec.ts b/types/cloudinary_ts_spec.ts index 8bbbc683..b9bc31a2 100644 --- a/types/cloudinary_ts_spec.ts +++ b/types/cloudinary_ts_spec.ts @@ -1048,3 +1048,14 @@ cloudinary.v2.api.create_folder('foo',{ cloudinary.v2.api.delete_folder('foo',{ agent: new Http.Agent() }); + +// $ExpectType Promise +cloudinary.v2.uploader.create_slideshow({ + manifest_json: { + foo: 'bar' // This is a typescript Record + }, // In practice only one of the two are allowed + manifest_transformation: { + width: 100 + }, + height:100 +}); diff --git a/types/index.d.ts b/types/index.d.ts index b9b4b4d3..3cc20680 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1044,6 +1044,8 @@ declare module 'cloudinary' { function upload_url(options?: ConfigOptions): Promise; + function create_slideshow(options?: ConfigOptions & { manifest_transformation?: TransformationOptions, manifest_json?: Record}, callback?: UploadResponseCallback): Promise; + /****************************** Structured Metadata API V2 Methods *************************************/ function update_metadata(metadata: string | object, public_ids: string[], options?:UploadApiOptions, callback?: ResponseCallback): Promise;