diff --git a/package-lock.json b/package-lock.json index 24cce6b8..939a0970 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3397,6 +3397,20 @@ "ieee754": "^1.1.4" } }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -3407,6 +3421,11 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -4961,6 +4980,43 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, + "decompress": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", + "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", + "requires": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + }, + "dependencies": { + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, "decompress-response": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", @@ -4969,6 +5025,143 @@ "mimic-response": "^1.0.0" } }, + "decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "requires": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + }, + "dependencies": { + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + } + } + } + }, + "decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "requires": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "dependencies": { + "file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==" + } + } + }, + "decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "requires": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + } + }, + "decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "requires": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=" + }, + "get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "requires": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, "decompress-zip": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/decompress-zip/-/decompress-zip-0.3.2.tgz", @@ -6134,6 +6327,14 @@ "reusify": "^1.0.0" } }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "requires": { + "pend": "~1.2.0" + } + }, "fecha": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", @@ -6158,6 +6359,11 @@ "escape-string-regexp": "^1.0.5" } }, + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" + }, "filename-reserved-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", @@ -6975,6 +7181,11 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, "grapheme-splitter": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", @@ -7665,6 +7876,11 @@ "ip-regex": "^4.0.0" } }, + "is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=" + }, "is-npm": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", @@ -13874,6 +14090,26 @@ "integrity": "sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ==", "dev": true }, + "officeparser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/officeparser/-/officeparser-2.1.1.tgz", + "integrity": "sha512-8/gJ5zqwjt3Ruavmq37Tn4tML693NY1GcCWBj389MtMuEG48aXuS5Fpt/qKwh5yHNyoO34kUK1g41lND20uBmg==", + "requires": { + "decompress": "^4.2.0", + "rimraf": "^2.6.3", + "xml2js": "^0.4.19" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + } + } + } + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -14277,6 +14513,11 @@ "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -14297,14 +14538,12 @@ "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" }, "pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, "requires": { "pinkie": "^2.0.0" } @@ -16234,6 +16473,24 @@ "resolved": "https://registry.npmjs.org/scmp/-/scmp-2.0.0.tgz", "integrity": "sha1-JHEQ7yLM+JexOj8KvdtSeCOTzWo=" }, + "seek-bzip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", + "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "requires": { + "commander": "~2.8.1" + }, + "dependencies": { + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "requires": { + "graceful-readlink": ">= 1.0.0" + } + } + } + }, "semantic-release": { "version": "15.14.0", "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-15.14.0.tgz", @@ -17194,6 +17451,14 @@ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, + "strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "requires": { + "is-natural-number": "^4.0.1" + } + }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", @@ -17709,6 +17974,11 @@ "os-tmpdir": "~1.0.2" } }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -18115,6 +18385,15 @@ "typpy": "^2.3.4" } }, + "unbzip2-stream": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.2.tgz", + "integrity": "sha512-pZMVAofMrrHX6Ik39hCk470kulCbmZ2SWfQLPmTWqfJV/oUm0gn1CblvHdUu4+54Je6Jq34x8kY6XjTy6dMkOg==", + "requires": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, "unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", @@ -19194,6 +19473,15 @@ } } }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, "yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/package.json b/package.json index 77e4d408..2d1f0236 100644 --- a/package.json +++ b/package.json @@ -84,6 +84,7 @@ "nexmo": "2.5.2", "ngrok": "3.2.7", "npm": "6.13.4", + "officeparser": "^2.1.1", "opn": "6.0.0", "pragmatismo-io-framework": "1.0.20", "prism-media": "1.2.1", diff --git a/packages/admin.gbapp/dialogs/AdminDialog.ts b/packages/admin.gbapp/dialogs/AdminDialog.ts index 37b3939e..f4c3bf5c 100644 --- a/packages/admin.gbapp/dialogs/AdminDialog.ts +++ b/packages/admin.gbapp/dialogs/AdminDialog.ts @@ -45,6 +45,8 @@ import { GBDeployer } from '../../core.gbapp/services/GBDeployer'; import { GBImporter } from '../../core.gbapp/services/GBImporterService'; import { Messages } from '../strings'; import { GBAdminService } from '../services/GBAdminService'; +import { CollectionUtil } from 'pragmatismo-io-framework'; + /** * Dialogs for administration tasks. @@ -153,22 +155,44 @@ export class AdminDialog extends IGBDialog { new WaterfallDialog('/publish', [ async step => { const locale = step.context.activity.locale; - await step.context.sendActivity(Messages[locale].working('Publishing from WhatsApp')); + await step.context.sendActivity(Messages[locale].working('Publishing')); let unknownCommand = false; + step.activeDialog.state.options.args = (step.options as any).args; + let args = step.activeDialog.state.options.args.split(' '); + let filename = args[0]; + const packages = []; + if (filename === null) { + await step.context.sendActivity(`Starting publishing for all bot packages...`); + packages.push(`${min.instance.botId}.gbkb`); + packages.push(`${min.instance.botId}.gbdialog`); + packages.push(`${min.instance.botId}.gbot`); + packages.push(`${min.instance.botId}.gbtheme`); + packages.push(`${min.instance.botId}.gbapp`); + packages.push(`${min.instance.botId}.gblib`); + } else { + await step.context.sendActivity(`Starting publishing for ${filename}...`); + packages.push(filename); + } try { - const cmd1 = `deployPackage ${process.env.STORAGE_SITE} /${process.env.STORAGE_LIBRARY}/${min.instance.botId}.gbai/${min.instance.botId}.gbkb`; + await CollectionUtil.asyncForEach(packages, async packageName => { + + const cmd1 = `deployPackage ${process.env.STORAGE_SITE} /${process.env.STORAGE_LIBRARY}/${min.instance.botId}.gbai/${packageName}`; + + if (await (deployer as any).getStoragePackageByName(min.instance.instanceId, + packageName) !== null) { // TODO: Move to interface. + const cmd2 = `undeployPackage ${packageName}`; + await GBAdminService.undeployPackageCommand(cmd2, min); + } + await GBAdminService.deployPackageCommand(min, cmd1, deployer); + if (packageName.endsWith('.gbkb')) { + await step.context.sendActivity('Rebuilding my own index, wait a minute, please...'); + await GBAdminService.rebuildIndexPackageCommand(min, deployer); + } + await step.context.sendActivity(`Finished publishing ${packageName}.`); + }); - await step.context.sendActivity('Publishing your .gbkb and .gbdialog packages...'); - if (await (deployer as any).getStoragePackageByName(min.instance.instanceId, `${min.instance.botId}.gbkb`) !== null) { // TODO: Move to interface. - const cmd2 = `undeployPackage ${min.instance.botId}.gbkb`; - await GBAdminService.undeployPackageCommand(cmd2, min); - } - await GBAdminService.deployPackageCommand(min, cmd1, deployer); - await step.context.sendActivity('Package deployed. Just need to rebuild the index... Doing it right now.'); - await GBAdminService.rebuildIndexPackageCommand(min, deployer); - await step.context.sendActivity('Finished importing of all your packages. Thanks.'); return await step.replaceDialog('/ask', { firstRun: false }); } catch (error) { diff --git a/packages/core.gbapp/services/GBDeployer.ts b/packages/core.gbapp/services/GBDeployer.ts index 07ffe2ed..16752ccd 100644 --- a/packages/core.gbapp/services/GBDeployer.ts +++ b/packages/core.gbapp/services/GBDeployer.ts @@ -315,6 +315,21 @@ export class GBDeployer implements IGBDeployer { await vm.loadDialogPackage(localPath, min, this.core, this); break; + case '.gbtheme': + const packageName = Path.basename(localPath); + GBServer.globals.server.use(`/themes/${packageName}`, express.static(packageName)); + GBLog.info(`Theme (.gbtheme) assets accessible at: /themes/${packageName}.`); + + break; + + case '.gbapp': + await this.callGBAppCompiler(localPath, this.core); + break; + + case '.gblib': + await this.callGBAppCompiler(localPath, this.core); + break; + default: const err = GBError.create(`Unhandled package type: ${packageType}.`); Promise.reject(err); @@ -343,13 +358,19 @@ export class GBDeployer implements IGBDeployer { break; case '.gbtheme': - // Just remove the package. + break; case '.gbdialog': break; + case '.gblib': + + break; + case '.gbapp': + + break; default: const err = GBError.create(`Unhandled package type: ${packageType}.`); Promise.reject(err); @@ -457,8 +478,6 @@ export class GBDeployer implements IGBDeployer { if (Path.extname(filename) === '.gbapp' || Path.extname(filename) === '.gblib') { // Themes for bots. } else if (Path.extname(filename) === '.gbtheme') { - server.use(`/themes/${filenameOnly}`, express.static(filename)); - GBLog.info(`Theme (.gbtheme) assets accessible at: /themes/${filenameOnly}.`); } else if (Path.extname(filename) === '.gbkb') { this.mountGBKBAssets(filenameOnly, filename); } else if (Path.extname(filename) === '.gbui') { @@ -517,39 +536,43 @@ export class GBDeployer implements IGBDeployer { // Skips .gbapp inside deploy folder. if (this.isSystemPackage(filenameOnly) === false) { - GBLog.info(`Deploying app: ${e}...`); - - let folder = Path.join(e, 'node_modules'); - if (process.env.GBAPP_DISABLE_COMPILE !== "true") { - if (!Fs.existsSync(folder)) { - GBLog.info(`Installing modules for ${e}...`); - child_process.execSync('npm install', { cwd: e }); - } - } - folder = Path.join(e, 'dist'); - - - try { - if (process.env.GBAPP_DISABLE_COMPILE !== "true") { - GBLog.info(`Compiling .gbapp: ${e}.`); - child_process.execSync(Path.join(process.env.PWD, 'node_modules/.bin/tsc'), { cwd: e }); - } - const m = await import(e); - const p = new m.Package(); - await p.loadPackage(core, core.sequelize); - appPackages.push(p); - GBLog.info(`App (.gbapp) deployed: ${e}.`); - appPackagesProcessed++; - } catch (error) { - GBLog.error(`Error message: ${error.message}`); - GBLog.error(`Error message: ${error.stack}`); - GBLog.error(`Error compiling .gbapp package ${e}:\n${error.stderr.toString()}`); - GBLog.error(`Error compiling .gbapp package ${e}:\n${error.stdout.toString()}`); - appPackagesProcessed++; - } + appPackagesProcessed = await this.callGBAppCompiler(e, core, appPackages, appPackagesProcessed); } }); return appPackagesProcessed; } + + public async callGBAppCompiler(gbappPath: string, core: IGBCoreService, + appPackages: any[] = undefined, appPackagesProcessed: number = 0) { + GBLog.info(`Deploying General Bots Application (.gbapp) or Library (.gblib): ${Path.basepath(gbappPath)}...`); + let folder = Path.join(gbappPath, 'node_modules'); + if (process.env.GBAPP_DISABLE_COMPILE !== "true") { + if (!Fs.existsSync(folder)) { + GBLog.info(`Installing modules for ${gbappPath}...`); + child_process.execSync('npm install', { cwd: gbappPath }); + } + } + folder = Path.join(gbappPath, 'dist'); + try { + if (process.env.GBAPP_DISABLE_COMPILE !== "true") { + GBLog.info(`Compiling: ${gbappPath}.`); + child_process.execSync(Path.join(process.env.PWD, 'node_modules/.bin/tsc'), { cwd: gbappPath }); + } + const m = await import(gbappPath); + const p = new m.Package(); + await p.loadPackage(core, core.sequelize); + if (appPackages !== undefined) { + appPackages.push(p); + } + GBLog.info(`.gbapp or .gblib deployed: ${gbappPath}.`); + appPackagesProcessed++; + } + catch (error) { + GBLog.error(`Error message: ${error.stack}`); + GBLog.error(`Error compiling package ${gbappPath}:\n${error.stdout.toString()}`); + appPackagesProcessed++; + } + return appPackagesProcessed; + } } diff --git a/packages/core.gbapp/services/GBMinService.ts b/packages/core.gbapp/services/GBMinService.ts index 235f7cf6..7d90dee3 100644 --- a/packages/core.gbapp/services/GBMinService.ts +++ b/packages/core.gbapp/services/GBMinService.ts @@ -67,6 +67,7 @@ import { GBDeployer } from './GBDeployer'; import { SecService } from '../../security.gblib/services/SecService'; import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService'; import { WhatsappDirectLine } from '../../whatsapp.gblib/services/WhatsappDirectLine'; +import fs = require('fs'); /** * Minimal service layer for a bot. @@ -209,11 +210,24 @@ export class GBMinService { const { min, adapter, conversationState } = await this.buildBotAdapter(instance, GBServer.globals.sysPackages); GBServer.globals.minInstances.push(min); - // Install default BASIC module. - - - // this.deployer.deployPackage(min, 'packages/default.gbdialog'); + // Install per bot deployed packages. + let packagePath = `work/${min.botId}.gbdialog`; + if (fs.existsSync(packagePath)) { + await this.deployer.deployPackage(min, packagePath); + } + packagePath = `work/${min.botId}.gbapp`; + if (fs.existsSync(packagePath)) { + await this.deployer.deployPackage(min, packagePath); + } + packagePath = `work/${min.botId}.gbtheme`; + if (fs.existsSync(packagePath)) { + await this.deployer.deployPackage(min, packagePath); + } + packagePath = `work/${min.botId}.gblib`; + if (fs.existsSync(packagePath)) { + await this.deployer.deployPackage(min, packagePath); + } // Call the loadBot context.activity for all packages. await this.invokeLoadBot(GBServer.globals.appPackages, GBServer.globals.sysPackages, min); @@ -253,7 +267,7 @@ export class GBMinService { const error = `WhatsApp API lost connection.`; GBLog.error(error); res.status(500).send(error); - + return; } } diff --git a/packages/core.gbapp/services/GBVMService.ts b/packages/core.gbapp/services/GBVMService.ts index bded0c61..3b702bca 100644 --- a/packages/core.gbapp/services/GBVMService.ts +++ b/packages/core.gbapp/services/GBVMService.ts @@ -46,6 +46,7 @@ import { DialogClass } from './GBAPIService'; //tslint:disable-next-line:no-submodule-imports const vb2ts = require('vbscript-to-typescript/dist/converter'); const beautify = require('js-beautify').js; +const parseOffice = require('bluebird').promisify(require('officeparser').parseOffice); /** * @fileoverview Virtualization services for emulation of BASIC. @@ -68,21 +69,35 @@ export class GBVMService extends GBService { return Promise.all( files.map(async file => { - if ( - file.name.endsWith('.vbs') || - file.name.endsWith('.vb') || - file.name.endsWith('.basic') || - file.name.endsWith('.bas') - ) { - const mainName = file.name.replace(/\-|\./g, ''); - min.scriptMap[file.name] = mainName; - const filename = urlJoin(folder, file.name); - fs.watchFile(filename, async () => { - await this.run(filename, min, deployer, mainName); + let filename:string = file.name; + + if ( + filename.endsWith('.vbs') || + filename.endsWith('.vb') || + filename.endsWith('.basic') || + filename.endsWith('.bas') || + filename.endsWith('.docx') + ) { + + if (filename.endsWith('.docx')) { + const text = await parseOffice(filename); + + filename = filename.substr(0, file.indexOf('docx')) + '.vbs'; + + fs.writeFileSync(urlJoin(folder, filename), text); + + } + + const mainName = filename.replace(/\-|\./g, ''); + min.scriptMap[filename] = mainName; + + const fullFilename = urlJoin(folder, filename); + fs.watchFile(fullFilename, async () => { + await this.run(fullFilename, min, deployer, mainName); }); - await this.run(filename, min, deployer, mainName); + await this.run(fullFilename, min, deployer, mainName); } }) ); @@ -103,16 +118,20 @@ export class GBVMService extends GBService { today = this.getToday(step) id = sys().getRandomId() + ${code} `; // Keywords from General Bots BASIC. code = code.replace(/(hear email)/g, `email = askEmail()`); - + code = code.replace(/(hear)\s*(\w+)/g, ($0, $1, $2) => { return `${$2} = hear()`; }); + code = code.replace(/(\w)\s*\=\s*find\s*(.*)/g, ($0, $1, $2, $3) => { + return `${$1} = sys().find(${$2})\n`; + }); code = code.replace(/(wait)\s*(\d+)/g, ($0, $1, $2) => { return `sys().wait(${$2})`; @@ -243,7 +262,7 @@ export class GBVMService extends GBService { GBLog.info(`[GBVMService] Finished loading of ${filename}`); } catch (error) { GBLog.error(`[GBVMService] ERROR loading ${error}`); - + } } @@ -289,8 +308,8 @@ export class GBVMService extends GBService { delete min.cbMap[cbId]; const opts = await promise(step, step.result); - - return await step.replaceDialog ('/hear', opts); + + return await step.replaceDialog('/hear', opts); } ]) );