fix(all): TS Lint and minor fixes.
This commit is contained in:
parent
b33a8b5341
commit
e7d7a1a4b2
44 changed files with 768 additions and 899 deletions
188
package-lock.json
generated
188
package-lock.json
generated
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "botserver",
|
||||
"version": "2.0.45",
|
||||
"version": "2.0.79",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -87,15 +87,10 @@
|
|||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
|
||||
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
|
||||
},
|
||||
"universal-user-agent": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
|
||||
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "8.3.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz",
|
||||
"integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg=="
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -1325,28 +1320,6 @@
|
|||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@dabh/diagnostics": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz",
|
||||
"integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==",
|
||||
"requires": {
|
||||
"colorspace": "1.1.x",
|
||||
"enabled": "2.0.x",
|
||||
"kuler": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"enabled": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
|
||||
"integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ=="
|
||||
},
|
||||
"kuler": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
|
||||
"integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@derhuerst/http-basic": {
|
||||
"version": "8.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@derhuerst/http-basic/-/http-basic-8.2.1.tgz",
|
||||
|
@ -4569,9 +4542,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "10.17.46",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.46.tgz",
|
||||
"integrity": "sha512-Tice8a+sJtlP9C1EUo0DYyjq52T37b3LexVu3p871+kfIBIN+OQ7PKPei1oF3MgF39olEpUfxaLtD+QFc1k69Q=="
|
||||
"version": "10.17.50",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.50.tgz",
|
||||
"integrity": "sha512-vwX+/ija9xKc/z9VqMCdbf4WYcMTGsI0I/L/6shIF3qXURxZOhPQlPRHtjTpiNhAwn0paMJzlOQqw6mAGEQnTA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -4671,9 +4644,9 @@
|
|||
}
|
||||
},
|
||||
"botlib": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/botlib/-/botlib-1.7.0.tgz",
|
||||
"integrity": "sha512-U1kccXjruGNRWvAM/bvJ+r13hh/aWjrxk/Ws5jWZlOJeEmNMgO6yCNVjOp7ZaPYO7w4l/Tver2w8BGN9zZ4ibw==",
|
||||
"version": "1.7.1",
|
||||
"resolved": "https://registry.npmjs.org/botlib/-/botlib-1.7.1.tgz",
|
||||
"integrity": "sha512-Nu518PUt9o8ezuhOMhKSnbS0qkHt6XAR2RVzxEbyDpxyVyD7zKcBsHvnhTx8/jdRLR9O5MuHa4dD4jSxWWuSww==",
|
||||
"requires": {
|
||||
"async": "3.2.0",
|
||||
"botbuilder": "4.11.0",
|
||||
|
@ -4686,10 +4659,10 @@
|
|||
"ms": "2.1.2",
|
||||
"pragmatismo-io-framework": "1.0.20",
|
||||
"reflect-metadata": "0.1.13",
|
||||
"sequelize": "6.3.5",
|
||||
"sequelize": "5.21.5",
|
||||
"sequelize-typescript": "1.1.0",
|
||||
"underscore": "1.11.0",
|
||||
"winston": "3.3.3"
|
||||
"winston": "3.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": {
|
||||
|
@ -4697,14 +4670,6 @@
|
|||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz",
|
||||
"integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw=="
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
||||
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
||||
"requires": {
|
||||
"ms": "2.1.2"
|
||||
}
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz",
|
||||
|
@ -4713,84 +4678,10 @@
|
|||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
}
|
||||
},
|
||||
"is-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw=="
|
||||
},
|
||||
"one-time": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz",
|
||||
"integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==",
|
||||
"requires": {
|
||||
"fn.name": "1.x.x"
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
|
||||
"integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ=="
|
||||
},
|
||||
"sequelize": {
|
||||
"version": "6.3.5",
|
||||
"resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.3.5.tgz",
|
||||
"integrity": "sha512-MiwiPkYSA8NWttRKAXdU9h0TxP6HAc1fl7qZmMO/VQqQOND83G4nZLXd0kWILtAoT9cxtZgFqeb/MPYgEeXwsw==",
|
||||
"requires": {
|
||||
"debug": "^4.1.1",
|
||||
"dottie": "^2.0.0",
|
||||
"inflection": "1.12.0",
|
||||
"lodash": "^4.17.15",
|
||||
"moment": "^2.26.0",
|
||||
"moment-timezone": "^0.5.31",
|
||||
"retry-as-promised": "^3.2.0",
|
||||
"semver": "^7.3.2",
|
||||
"sequelize-pool": "^6.0.0",
|
||||
"toposort-class": "^1.0.1",
|
||||
"uuid": "^8.1.0",
|
||||
"validator": "^10.11.0",
|
||||
"wkx": "^0.5.0"
|
||||
}
|
||||
},
|
||||
"underscore": {
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.11.0.tgz",
|
||||
"integrity": "sha512-xY96SsN3NA461qIRKZ/+qox37YXPtSBswMGfiNptr+wrt6ds4HaMw23TP612fEyGekRE6LNRiLYr/aqbHXNedw=="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "8.3.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz",
|
||||
"integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg=="
|
||||
},
|
||||
"validator": {
|
||||
"version": "10.11.0",
|
||||
"resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
|
||||
"integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw=="
|
||||
},
|
||||
"winston": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz",
|
||||
"integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==",
|
||||
"requires": {
|
||||
"@dabh/diagnostics": "^2.0.2",
|
||||
"async": "^3.1.0",
|
||||
"is-stream": "^2.0.0",
|
||||
"logform": "^2.2.0",
|
||||
"one-time": "^1.0.0",
|
||||
"readable-stream": "^3.4.0",
|
||||
"stack-trace": "0.0.x",
|
||||
"triple-beam": "^1.3.0",
|
||||
"winston-transport": "^4.4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -5725,8 +5616,7 @@
|
|||
"colornames": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz",
|
||||
"integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=",
|
||||
"dev": true
|
||||
"integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y="
|
||||
},
|
||||
"colors": {
|
||||
"version": "1.4.0",
|
||||
|
@ -7376,7 +7266,6 @@
|
|||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz",
|
||||
"integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"colorspace": "1.1.x",
|
||||
"enabled": "1.0.x",
|
||||
|
@ -7667,7 +7556,6 @@
|
|||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz",
|
||||
"integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"env-variable": "0.0.x"
|
||||
}
|
||||
|
@ -7792,8 +7680,7 @@
|
|||
"env-variable": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.6.tgz",
|
||||
"integrity": "sha512-bHz59NlBbtS0NhftmR8+ExBEekE7br0e01jw+kk0NDro7TtZzBYZ5ScGPs3OmwnpyfHTHOtr1Y6uedCdrIldtg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-bHz59NlBbtS0NhftmR8+ExBEekE7br0e01jw+kk0NDro7TtZzBYZ5ScGPs3OmwnpyfHTHOtr1Y6uedCdrIldtg=="
|
||||
},
|
||||
"epub2": {
|
||||
"version": "1.3.4",
|
||||
|
@ -8820,11 +8707,6 @@
|
|||
"integrity": "sha512-iEjGZ94OBMcESxnLorXNjJmtd/JtQYXUVrQpfwvtAKkuyawRmv+2LM6nqyOsOJkISEYbyY6ziudRE0u4VyPSVA==",
|
||||
"dev": true
|
||||
},
|
||||
"fn.name": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
|
||||
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
|
||||
|
@ -11111,7 +10993,6 @@
|
|||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz",
|
||||
"integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"colornames": "^1.1.1"
|
||||
}
|
||||
|
@ -16901,8 +16782,7 @@
|
|||
"one-time": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz",
|
||||
"integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=",
|
||||
"dev": true
|
||||
"integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4="
|
||||
},
|
||||
"onetime": {
|
||||
"version": "5.1.0",
|
||||
|
@ -19601,11 +19481,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"sequelize-pool": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz",
|
||||
"integrity": "sha512-4YwEw3ZgK/tY/so+GfnSgXkdwIJJ1I32uZJztIEgZeAO6HMgj64OzySbWLgxj+tXhZCJnzRfkY9gINw8Ft8ZMg=="
|
||||
},
|
||||
"sequelize-typescript": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/sequelize-typescript/-/sequelize-typescript-1.1.0.tgz",
|
||||
|
@ -21766,6 +21641,26 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"tslint-microsoft-contrib": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tslint-microsoft-contrib/-/tslint-microsoft-contrib-6.2.0.tgz",
|
||||
"integrity": "sha512-6tfi/2tHqV/3CL77pULBcK+foty11Rr0idRDxKnteTaKm6gWF9qmaCNU17HVssOuwlYNyOmd9Jsmjd+1t3a3qw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tsutils": "^2.27.2 <2.29.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"tsutils": {
|
||||
"version": "2.28.0",
|
||||
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.28.0.tgz",
|
||||
"integrity": "sha512-bh5nAtW0tuhvOJnx1GLRn5ScraRLICGyJV5wJhtRWOLsxW70Kk5tZtpK3O/hW6LDnqKS9mlUMPZj9fEMJ0gxqA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tslib": "^1.8.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tsutils": {
|
||||
"version": "3.17.1",
|
||||
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz",
|
||||
|
@ -22087,8 +21982,7 @@
|
|||
"universal-user-agent": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
|
||||
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==",
|
||||
"dev": true
|
||||
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
|
||||
},
|
||||
"universalify": {
|
||||
"version": "0.1.2",
|
||||
|
@ -22559,7 +22453,6 @@
|
|||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/winston/-/winston-3.2.1.tgz",
|
||||
"integrity": "sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async": "^2.6.1",
|
||||
"diagnostics": "^1.1.1",
|
||||
|
@ -22576,7 +22469,6 @@
|
|||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
|
@ -22594,14 +22486,6 @@
|
|||
"triple-beam": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"wkx": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz",
|
||||
"integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==",
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"word-wrap": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
|
||||
|
|
|
@ -112,9 +112,6 @@
|
|||
"washyourmouthoutwithsoap": "1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ngrok": "3.3.0",
|
||||
"typedoc": "0.19.2",
|
||||
"simple-commit-message": "4.0.13",
|
||||
"@types/url-join": "4.0.0",
|
||||
"@types/winston": "2.4.4",
|
||||
"ban-sensitive-files": "1.9.14",
|
||||
|
@ -123,12 +120,16 @@
|
|||
"dependency-check": "4.1.0",
|
||||
"git-issues": "1.3.1",
|
||||
"license-checker": "25.0.1",
|
||||
"ngrok": "3.3.0",
|
||||
"nsp": "3.2.1",
|
||||
"prettier-standard": "16.4.1",
|
||||
"semantic-release": "17.2.4",
|
||||
"simple-commit-message": "4.0.13",
|
||||
"travis-deploy-once": "5.0.11",
|
||||
"ts-node": "9.0.0",
|
||||
"tslint": "6.1.2"
|
||||
"tslint": "6.1.2",
|
||||
"tslint-microsoft-contrib": "^6.2.0",
|
||||
"typedoc": "0.19.2"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"env": {
|
||||
|
|
|
@ -63,7 +63,6 @@ export class GBAdminPackage implements IGBPackage {
|
|||
GBLog.verbose(`onExchangeData called.`);
|
||||
}
|
||||
|
||||
|
||||
public async loadPackage(core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||
core.sequelize.addModels([GuaribasAdmin]);
|
||||
}
|
||||
|
|
|
@ -37,15 +37,15 @@
|
|||
'use strict';
|
||||
|
||||
import { AuthenticationContext, TokenResponse } from 'adal-node';
|
||||
import { IGBAdminService, IGBCoreService, IGBInstance, GBMinInstance, GBLog, IGBDeployer } from 'botlib';
|
||||
import { GBLog, GBMinInstance, IGBAdminService, IGBCoreService, IGBDeployer, IGBInstance } from 'botlib';
|
||||
import urlJoin = require('url-join');
|
||||
import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService';
|
||||
import { GuaribasInstance } from '../../core.gbapp/models/GBModel';
|
||||
import { GBConfigService } from '../../core.gbapp/services/GBConfigService';
|
||||
import { GuaribasAdmin } from '../models/AdminModel';
|
||||
import { GBSharePointService } from '../../sharepoint.gblib/services/SharePointService';
|
||||
import { GBImporter } from '../../core.gbapp/services/GBImporterService';
|
||||
import { GBDeployer } from '../../core.gbapp/services/GBDeployer';
|
||||
import { GBImporter } from '../../core.gbapp/services/GBImporterService';
|
||||
import { GBSharePointService } from '../../sharepoint.gblib/services/SharePointService';
|
||||
import { GuaribasAdmin } from '../models/AdminModel';
|
||||
const Path = require('path');
|
||||
const msRestAzure = require('ms-rest-azure');
|
||||
const PasswordGenerator = require('strict-password-generator').default;
|
||||
|
@ -145,6 +145,57 @@ export class GBAdminService implements IGBAdminService {
|
|||
return passwordGenerator.generatePassword(options);
|
||||
}
|
||||
|
||||
public static async undeployPackageCommand(text: any, min: GBMinInstance) {
|
||||
const packageName = text.split(' ')[1];
|
||||
const importer = new GBImporter(min.core);
|
||||
const deployer = new GBDeployer(min.core, importer);
|
||||
const localFolder = Path.join('work', `${min.instance.botId}.gbai`, Path.basename(packageName));
|
||||
await deployer.undeployPackageFromLocalPath(min.instance, localFolder);
|
||||
}
|
||||
|
||||
public static isSharePointPath(path: string) {
|
||||
return path.indexOf('sharepoint.com') > 0;
|
||||
}
|
||||
public static async deployPackageCommand(min: GBMinInstance, text: string, deployer: IGBDeployer) {
|
||||
const packageName = text.split(' ')[1];
|
||||
|
||||
if (!this.isSharePointPath(packageName)) {
|
||||
const additionalPath = GBConfigService.get('ADDITIONAL_DEPLOY_PATH');
|
||||
if (additionalPath === undefined) {
|
||||
throw new Error('ADDITIONAL_DEPLOY_PATH is not set and deployPackage was called.');
|
||||
}
|
||||
await deployer.deployPackage(min, urlJoin(additionalPath, packageName));
|
||||
} else {
|
||||
const siteName = text.split(' ')[1];
|
||||
const folderName = text.split(' ')[2];
|
||||
|
||||
const s = new GBSharePointService();
|
||||
|
||||
const localFolder = Path.join('work', `${min.instance.botId}.gbai`, Path.basename(folderName));
|
||||
GBLog.warn(`${GBConfigService.get('CLOUD_USERNAME')} must be authorized on SharePoint related site`);
|
||||
await s.downloadFolder(
|
||||
localFolder,
|
||||
siteName,
|
||||
folderName,
|
||||
GBConfigService.get('CLOUD_USERNAME'),
|
||||
GBConfigService.get('CLOUD_PASSWORD')
|
||||
);
|
||||
await deployer.deployPackage(min, localFolder);
|
||||
}
|
||||
}
|
||||
public static async rebuildIndexPackageCommand(min: GBMinInstance, deployer: IGBDeployer) {
|
||||
await deployer.rebuildIndex(
|
||||
min.instance,
|
||||
new AzureDeployerService(deployer).getKBSearchSchema(min.instance.searchIndex)
|
||||
);
|
||||
}
|
||||
|
||||
public static async syncBotServerCommand(min: GBMinInstance, deployer: GBDeployer) {
|
||||
const serverName = `${min.instance.botId}-server`;
|
||||
const service = await AzureDeployerService.createInstance(deployer);
|
||||
service.syncBotServerRepository(min.instance.botId, serverName);
|
||||
}
|
||||
|
||||
public async setValue(instanceId: number, key: string, value: string) {
|
||||
const options = { where: {} };
|
||||
options.where = { key: key };
|
||||
|
@ -183,7 +234,7 @@ export class GBAdminService implements IGBAdminService {
|
|||
public async acquireElevatedToken(instanceId: number): Promise<string> {
|
||||
// TODO: Use boot bot as base for authentication.
|
||||
|
||||
let botId = GBConfigService.get('BOT_ID');
|
||||
const botId = GBConfigService.get('BOT_ID');
|
||||
instanceId = (await this.core.loadInstanceByBotId(botId)).instanceId;
|
||||
|
||||
return new Promise<string>(async (resolve, reject) => {
|
||||
|
@ -228,56 +279,5 @@ export class GBAdminService implements IGBAdminService {
|
|||
});
|
||||
}
|
||||
|
||||
public static async undeployPackageCommand(text: any, min: GBMinInstance) {
|
||||
const packageName = text.split(' ')[1];
|
||||
const importer = new GBImporter(min.core);
|
||||
const deployer = new GBDeployer(min.core, importer);
|
||||
let localFolder = Path.join('work', `${min.instance.botId}.gbai`, Path.basename(packageName));
|
||||
await deployer.undeployPackageFromLocalPath(min.instance, localFolder);
|
||||
}
|
||||
|
||||
public static isSharePointPath(path: string) {
|
||||
return path.indexOf('sharepoint.com') > 0;
|
||||
}
|
||||
|
||||
public async publish(min: GBMinInstance, packageName: string, republish: boolean): Promise<void> { }
|
||||
public static async deployPackageCommand(min: GBMinInstance, text: string, deployer: IGBDeployer) {
|
||||
const packageName = text.split(' ')[1];
|
||||
|
||||
if (!this.isSharePointPath(packageName)) {
|
||||
const additionalPath = GBConfigService.get('ADDITIONAL_DEPLOY_PATH');
|
||||
if (additionalPath === undefined) {
|
||||
throw new Error('ADDITIONAL_DEPLOY_PATH is not set and deployPackage was called.');
|
||||
}
|
||||
await deployer.deployPackage(min, urlJoin(additionalPath, packageName));
|
||||
} else {
|
||||
let siteName = text.split(' ')[1];
|
||||
let folderName = text.split(' ')[2];
|
||||
|
||||
let s = new GBSharePointService();
|
||||
|
||||
let localFolder = Path.join('work', `${min.instance.botId}.gbai`, Path.basename(folderName));
|
||||
GBLog.warn(`${GBConfigService.get('CLOUD_USERNAME')} must be authorized on SharePoint related site`);
|
||||
await s.downloadFolder(
|
||||
localFolder,
|
||||
siteName,
|
||||
folderName,
|
||||
GBConfigService.get('CLOUD_USERNAME'),
|
||||
GBConfigService.get('CLOUD_PASSWORD')
|
||||
);
|
||||
await deployer.deployPackage(min, localFolder);
|
||||
}
|
||||
}
|
||||
public static async rebuildIndexPackageCommand(min: GBMinInstance, deployer: IGBDeployer) {
|
||||
await deployer.rebuildIndex(
|
||||
min.instance,
|
||||
new AzureDeployerService(deployer).getKBSearchSchema(min.instance.searchIndex)
|
||||
);
|
||||
}
|
||||
|
||||
public static async syncBotServerCommand(min: GBMinInstance, deployer: GBDeployer) {
|
||||
const serverName = `${min.instance.botId}-server`;
|
||||
const service = await AzureDeployerService.createInstance(deployer);
|
||||
service.syncBotServerRepository(min.instance.botId, serverName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ export const Messages = {
|
|||
publish_must_be_admin: 'Seu telefone precisa estar com privilégios administrativos para realizar publicação.',
|
||||
publish_success: 'Publicação realizada.',
|
||||
publish_type_yes: 'Por favor, digite *Sim* para continuar com a publicação.',
|
||||
publish_canceled: 'Publicação cancelada.',
|
||||
publish_canceled: 'Publicação cancelada.'
|
||||
},
|
||||
'pt-BR': {
|
||||
authenticate: 'Please, authenticate:',
|
||||
|
@ -47,6 +47,6 @@ export const Messages = {
|
|||
publish_must_be_admin: 'Seu telefone precisa estar com privilégios administrativos para realizar publicação.',
|
||||
publish_success: 'Publicação realizada.',
|
||||
publish_type_yes: 'Por favor, digite *Sim* para continuar com a publicação.',
|
||||
publish_canceled: 'Publicação cancelada.',
|
||||
publish_canceled: 'Publicação cancelada.'
|
||||
}
|
||||
};
|
||||
|
|
|
@ -58,7 +58,6 @@ import { GuaribasChannel, GuaribasInstance } from '../../core.gbapp/models/GBMod
|
|||
import { GuaribasSubject } from '../../kb.gbapp/models';
|
||||
import { GuaribasUser } from '../../security.gbapp/models';
|
||||
|
||||
|
||||
/**
|
||||
* A conversation that groups many messages.
|
||||
*/
|
||||
|
@ -74,7 +73,6 @@ export class GuaribasConversation extends Model<GuaribasConversation> {
|
|||
@Column
|
||||
public instanceId: number;
|
||||
|
||||
|
||||
@ForeignKey(() => GuaribasSubject)
|
||||
@Column
|
||||
public startSubjectId: number;
|
||||
|
@ -110,7 +108,6 @@ export class GuaribasConversation extends Model<GuaribasConversation> {
|
|||
public startedBy: GuaribasUser;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A single message in a conversation.
|
||||
*/
|
||||
|
|
|
@ -34,10 +34,10 @@
|
|||
* @fileoverview General Bots server core.
|
||||
*/
|
||||
|
||||
import { AzureText } from 'pragmatismo-io-framework';
|
||||
import { GBServer } from '../../../src/app';
|
||||
import { GuaribasUser } from '../../security.gbapp/models';
|
||||
import { GuaribasConversation, GuaribasConversationMessage } from '../models';
|
||||
import { GBServer } from '../../../src/app';
|
||||
import { AzureText } from 'pragmatismo-io-framework';
|
||||
|
||||
/**
|
||||
* Base services for Bot Analytics.
|
||||
|
@ -55,16 +55,19 @@ export class AnalyticsService {
|
|||
return await conversation.save();
|
||||
}
|
||||
|
||||
public async updateConversationSuggestion(instanceId: number, conversationId: string, feedback: string, locale: string): Promise<number> {
|
||||
|
||||
public async updateConversationSuggestion(instanceId: number,
|
||||
conversationId: string, feedback: string, locale: string): Promise<number> {
|
||||
|
||||
const minBoot = GBServer.globals.minBoot as any;
|
||||
const rate = await AzureText.getSentiment(
|
||||
minBoot.instance.textAnalyticsKey ? minBoot.instance.textAnalyticsKey : minBoot.instance.textAnalyticsKey,
|
||||
minBoot.instance.textAnalyticsEndpoint ? minBoot.instance.textAnalyticsEndpoint : minBoot.instance.textAnalyticsEndpoint,
|
||||
minBoot.instance.textAnalyticsKey ? minBoot.instance.textAnalyticsKey :
|
||||
minBoot.instance.textAnalyticsKey,
|
||||
minBoot.instance.textAnalyticsEndpoint ? minBoot.instance.textAnalyticsEndpoint :
|
||||
minBoot.instance.textAnalyticsEndpoint,
|
||||
locale,
|
||||
feedback
|
||||
);
|
||||
|
||||
|
||||
const options = { where: { } };
|
||||
options.where = { conversationId: conversationId, instanceId: instanceId };
|
||||
const item = await GuaribasConversation.findOne(options);
|
||||
|
@ -78,7 +81,6 @@ export class AnalyticsService {
|
|||
|
||||
}
|
||||
|
||||
|
||||
public async createMessage(
|
||||
instanceId: number,
|
||||
conversation: GuaribasConversation,
|
||||
|
|
|
@ -104,7 +104,7 @@ export class StartDialog {
|
|||
const instance = <IGBInstance>{};
|
||||
|
||||
instance.botId = botId;
|
||||
instance.state ='active';
|
||||
instance.state = 'active';
|
||||
instance.cloudUsername = username;
|
||||
instance.cloudPassword = password;
|
||||
instance.cloudSubscriptionId = subscriptionId;
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
'use strict';
|
||||
|
||||
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
||||
import { GuaribasSchedule } from 'packages/core.gbapp/models/GBModel';
|
||||
import { GuaribasSchedule } from '../core.gbapp/models/GBModel';
|
||||
import { Sequelize } from 'sequelize-typescript';
|
||||
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ import { GuaribasInstance } from '../../core.gbapp/models/GBModel';
|
|||
@Table
|
||||
//tslint:disable-next-line:max-classes-per-file
|
||||
export class GuaribasSchedule extends Model<GuaribasSchedule> {
|
||||
|
||||
|
||||
@Column
|
||||
public name: string;
|
||||
|
||||
|
|
|
@ -32,14 +32,14 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
import { TurnContext, BotAdapter } from 'botbuilder';
|
||||
import { WaterfallStepContext, WaterfallDialog } from 'botbuilder-dialogs';
|
||||
import { BotAdapter, TurnContext } from 'botbuilder';
|
||||
import { WaterfallDialog, WaterfallStepContext } from 'botbuilder-dialogs';
|
||||
import { GBLog, GBMinInstance } from 'botlib';
|
||||
import urlJoin = require('url-join');
|
||||
import { GBDeployer } from '../../core.gbapp/services/GBDeployer';
|
||||
import { Messages } from '../strings';
|
||||
import { GBServer } from '../../../src/app';
|
||||
import { GBDeployer } from '../../core.gbapp/services/GBDeployer';
|
||||
import { SecService } from '../../security.gbapp/services/SecService';
|
||||
import { Messages } from '../strings';
|
||||
import { SystemKeywords } from './SystemKeywords';
|
||||
|
||||
/**
|
||||
|
@ -48,8 +48,8 @@ import { SystemKeywords } from './SystemKeywords';
|
|||
*/
|
||||
export class DialogKeywords {
|
||||
|
||||
/**
|
||||
* Reference to minimal bot instance.
|
||||
/**
|
||||
* Reference to minimal bot instance.
|
||||
*/
|
||||
public min: GBMinInstance;
|
||||
|
||||
|
@ -77,17 +77,17 @@ export class DialogKeywords {
|
|||
|
||||
/**
|
||||
* Returns the today data filled in dd/mm/yyyy or mm/dd/yyyy.
|
||||
*
|
||||
*
|
||||
* @example x = TODAY
|
||||
*/
|
||||
public async getToday(step) {
|
||||
var d = new Date(),
|
||||
let d = new Date(),
|
||||
month = '' + (d.getMonth() + 1),
|
||||
day = '' + d.getDate(),
|
||||
year = d.getFullYear();
|
||||
|
||||
if (month.length < 2) month = '0' + month;
|
||||
if (day.length < 2) day = '0' + day;
|
||||
if (month.length < 2) { month = '0' + month; }
|
||||
if (day.length < 2) { day = '0' + day; }
|
||||
|
||||
const locale = step.context.activity.locale;
|
||||
switch (locale) {
|
||||
|
@ -104,7 +104,7 @@ export class DialogKeywords {
|
|||
|
||||
/**
|
||||
* Quits the dialog, currently required to get out of VM context.
|
||||
*
|
||||
*
|
||||
* @example EXIT
|
||||
*/
|
||||
public async exit(step) {
|
||||
|
@ -113,24 +113,24 @@ export class DialogKeywords {
|
|||
|
||||
/**
|
||||
* Returns current time in format hh:dd.
|
||||
*
|
||||
*
|
||||
* @example SAVE "file.xlsx", name, email, NOW
|
||||
*
|
||||
*
|
||||
*/
|
||||
public async getNow() {
|
||||
const nowUTC = new Date();
|
||||
const now = new Date((typeof nowUTC === "string" ?
|
||||
const now = new Date((typeof nowUTC === 'string' ?
|
||||
new Date(nowUTC) :
|
||||
nowUTC).toLocaleString("en-US", { timeZone: process.env.DEFAULT_TIMEZONE }));
|
||||
nowUTC).toLocaleString('en-US', { timeZone: process.env.DEFAULT_TIMEZONE }));
|
||||
|
||||
return now.getHours() + ':' + now.getMinutes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a file to a given mobile.
|
||||
*
|
||||
*
|
||||
* @example SEND FILE TO "+199988887777", "image.jpg"
|
||||
*
|
||||
*
|
||||
*/
|
||||
public async sendFileTo(mobile, filename, caption) {
|
||||
return await this.internalSendFile(null, mobile, filename, caption);
|
||||
|
@ -138,47 +138,24 @@ export class DialogKeywords {
|
|||
|
||||
/**
|
||||
* Sends a file to the current user.
|
||||
*
|
||||
*
|
||||
* @example SEND FILE "image.jpg"
|
||||
*
|
||||
*
|
||||
*/
|
||||
public async sendFile(step, filename, caption) {
|
||||
return await this.internalSendFile(step, null, filename, caption);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the sending of the file.
|
||||
*/
|
||||
private async internalSendFile(step, mobile, filename, caption) {
|
||||
if (filename.indexOf('.md') > -1) {
|
||||
GBLog.info(`BASIC: Sending the contents of ${filename} markdown to mobile.`);
|
||||
let md = await this.min.kbService.getAnswerTextByMediaName(this.min.instance.instanceId, filename);
|
||||
await this.min.conversationalService.sendMarkdownToMobile(this.min, step, mobile, md);
|
||||
} else {
|
||||
GBLog.info(`BASIC: Sending the file ${filename} to mobile.`);
|
||||
let url = urlJoin(
|
||||
GBServer.globals.publicAddress,
|
||||
'kb',
|
||||
`${this.min.botId}.gbai`,
|
||||
`${this.min.botId}.gbkb`,
|
||||
'assets',
|
||||
filename
|
||||
);
|
||||
|
||||
await this.min.conversationalService.sendFile(this.min, step, mobile, url, caption);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the current language of the bot conversation.
|
||||
*
|
||||
*
|
||||
* @example SET LANGUAGE "pt"
|
||||
*
|
||||
*
|
||||
*/
|
||||
public async setLanguage(step, language) {
|
||||
const user = await this.min.userProfile.get(step.context, {});
|
||||
|
||||
let sec = new SecService();
|
||||
const sec = new SecService();
|
||||
user.systemUser = await sec.updateUserLocale(user.systemUser.userId, language);
|
||||
|
||||
await this.min.userProfile.set(step.context, user);
|
||||
|
@ -190,12 +167,20 @@ export class DialogKeywords {
|
|||
public async userName(step) {
|
||||
return step.context.activity.from.name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* OBSOLETE.
|
||||
*/
|
||||
public async getFrom(step) {
|
||||
return await this.userMobile(step);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns current mobile number from user in conversation.
|
||||
*
|
||||
*
|
||||
* @example SAVE "file.xlsx", name, email, MOBILE
|
||||
*
|
||||
*
|
||||
*/
|
||||
public async userMobile(step) {
|
||||
if (isNaN(step.context.activity.from.id)) {
|
||||
|
@ -207,9 +192,9 @@ export class DialogKeywords {
|
|||
|
||||
/**
|
||||
* Shows the subject menu to the user
|
||||
*
|
||||
*
|
||||
* @example MENU
|
||||
*
|
||||
*
|
||||
*/
|
||||
public async showMenu(step) {
|
||||
return await step.beginDialog('/menu');
|
||||
|
@ -217,9 +202,9 @@ export class DialogKeywords {
|
|||
|
||||
/**
|
||||
* Performs the transfer of the conversation to a human agent.
|
||||
*
|
||||
*
|
||||
* @example TRANSFER
|
||||
*
|
||||
*
|
||||
*/
|
||||
public async transfer(step) {
|
||||
return await step.beginDialog('/t');
|
||||
|
@ -227,9 +212,9 @@ export class DialogKeywords {
|
|||
|
||||
/**
|
||||
* Hears something from user and put it in a variable
|
||||
*
|
||||
*
|
||||
* @example HEAR name
|
||||
*
|
||||
*
|
||||
*/
|
||||
public async hear(step, promise, previousResolve, kind, ...args) {
|
||||
function random(low, high) {
|
||||
|
@ -253,4 +238,27 @@ export class DialogKeywords {
|
|||
public async talk(step, text: string) {
|
||||
return await this.min.conversationalService.sendText(this.min, step, text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the sending of the file.
|
||||
*/
|
||||
private async internalSendFile(step, mobile, filename, caption) {
|
||||
if (filename.indexOf('.md') > -1) {
|
||||
GBLog.info(`BASIC: Sending the contents of ${filename} markdown to mobile.`);
|
||||
const md = await this.min.kbService.getAnswerTextByMediaName(this.min.instance.instanceId, filename);
|
||||
await this.min.conversationalService.sendMarkdownToMobile(this.min, step, mobile, md);
|
||||
} else {
|
||||
GBLog.info(`BASIC: Sending the file ${filename} to mobile.`);
|
||||
const url = urlJoin(
|
||||
GBServer.globals.publicAddress,
|
||||
'kb',
|
||||
`${this.min.botId}.gbai`,
|
||||
`${this.min.botId}.gbkb`,
|
||||
'assets',
|
||||
filename
|
||||
);
|
||||
|
||||
await this.min.conversationalService.sendFile(this.min, step, mobile, url, caption);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@ import * as fs from 'fs';
|
|||
import { GBDeployer } from '../../core.gbapp/services/GBDeployer';
|
||||
import { TSCompiler } from './TSCompiler';
|
||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||
const walkPromise = require('walk-promise');
|
||||
import urlJoin = require('url-join');
|
||||
import { DialogKeywords } from './DialogKeywords';
|
||||
import { Messages } from '../strings';
|
||||
|
@ -47,7 +46,8 @@ import { GBConversationalService } from '../../core.gbapp/services/GBConversatio
|
|||
const vm = require('vm');
|
||||
const vb2ts = require('./vbscript-to-typescript');
|
||||
const beautify = require('js-beautify').js;
|
||||
var textract = require('textract');
|
||||
const textract = require('textract');
|
||||
const walkPromise = require('walk-promise');
|
||||
const phoneUtil = require('google-libphonenumber').PhoneNumberUtil.getInstance();
|
||||
const phone = require('phone');
|
||||
|
||||
|
@ -678,7 +678,7 @@ export class GBVMService extends GBService {
|
|||
const promise = min.cbMap[id].promise;
|
||||
delete min.cbMap[id];
|
||||
try {
|
||||
|
||||
|
||||
await promise(step, result);
|
||||
if (step.activeDialog.state.options.previousResolve != undefined) {
|
||||
step.activeDialog.state.options.previousResolve();
|
||||
|
|
|
@ -9,12 +9,12 @@ export const Messages = {
|
|||
hi: (msg) => `Hello, ${msg}.`,
|
||||
very_sorry_about_error: `I'm sorry to inform that there was an error which was recorded to be solved.`,
|
||||
canceled: 'Canceled. If I can be useful, let me know how',
|
||||
whats_email: "What's your E-mail address?",
|
||||
which_language: "Please, type the language name you would like to talk through.",
|
||||
validation_enter_valid_email: "Please enter a valid e-mail." ,
|
||||
language_chosen: "Very good, so let's go..." ,
|
||||
affirmative_sentences: /^(sim|s|positivo|afirmativo|claro|evidente|sem dúvida|confirmo|confirmar|confirmado|uhum|si|y|yes|sure)/i,
|
||||
|
||||
whats_email: 'What\'s your E-mail address?',
|
||||
which_language: 'Please, type the language name you would like to talk through.',
|
||||
validation_enter_valid_email: 'Please enter a valid e-mail.' ,
|
||||
language_chosen: 'Very good, so let\'s go...' ,
|
||||
affirmative_sentences: /^(sim|s|positivo|afirmativo|claro|evidente|sem dúvida|confirmo|confirmar|confirmado|uhum|si|y|yes|sure)/i
|
||||
|
||||
},
|
||||
'pt-BR': {
|
||||
show_video: 'Vou te mostrar um vídeo. Por favor, aguarde...',
|
||||
|
@ -24,11 +24,11 @@ export const Messages = {
|
|||
hi: (msg) => `Oi, ${msg}.`,
|
||||
very_sorry_about_error: `Lamento, ocorreu um erro que já foi registrado para ser tratado.`,
|
||||
canceled: 'Cancelado, avise como posso ser útil novamente.',
|
||||
whats_email: "Qual seu e-mail?",
|
||||
which_language: "Por favor, digite o idioma que você gostaria de usar para conversarmos.",
|
||||
validation_enter_valid_email: "Por favor digite um email válido.",
|
||||
language_chosen: "Muito bem, então vamos lá..." ,
|
||||
affirmative_sentences: /^(sim|s|positivo|afirmativo|claro|evidente|sem dúvida|confirmo|confirmar|confirmado|uhum|si|y|yes|sure)/i,
|
||||
whats_email: 'Qual seu e-mail?',
|
||||
which_language: 'Por favor, digite o idioma que você gostaria de usar para conversarmos.',
|
||||
validation_enter_valid_email: 'Por favor digite um email válido.',
|
||||
language_chosen: 'Muito bem, então vamos lá...' ,
|
||||
affirmative_sentences: /^(sim|s|positivo|afirmativo|claro|evidente|sem dúvida|confirmo|confirmar|confirmado|uhum|si|y|yes|sure)/i
|
||||
|
||||
}
|
||||
};
|
||||
|
|
|
@ -64,8 +64,6 @@ export class GBConsolePackage implements IGBPackage {
|
|||
public async onExchangeData(min: GBMinInstance, kind: string, data: any) {
|
||||
GBLog.verbose(`onExchangeData called.`);
|
||||
}
|
||||
|
||||
|
||||
public async loadBot(min: GBMinInstance): Promise<void> {
|
||||
this.channel = new ConsoleDirectLine(min.instance.webchatKey);
|
||||
}
|
||||
|
|
|
@ -39,10 +39,10 @@
|
|||
import { BotAdapter } from 'botbuilder';
|
||||
import { WaterfallDialog } from 'botbuilder-dialogs';
|
||||
import { GBMinInstance, IGBDialog } from 'botlib';
|
||||
import { Messages } from '../strings';
|
||||
import { SecService } from '../../security.gbapp/services/SecService';
|
||||
import { GBServer } from '../../../src/app';
|
||||
import { SecService } from '../../security.gbapp/services/SecService';
|
||||
import { GBConversationalService } from '../services/GBConversationalService';
|
||||
import { Messages } from '../strings';
|
||||
/**
|
||||
* Dialog for the bot explains about itself.
|
||||
*/
|
||||
|
@ -59,16 +59,16 @@ export class SwitchBotDialog extends IGBDialog {
|
|||
async step => {
|
||||
const locale = step.context.activity.locale;
|
||||
|
||||
return await min.conversationalService.prompt (min, step, "Qual seria o código de ativação?");
|
||||
return await min.conversationalService.prompt (min, step, 'Qual seria o código de ativação?');
|
||||
},
|
||||
async step => {
|
||||
let sec = new SecService();
|
||||
let from = step.context.activity.from.id;
|
||||
const sec = new SecService();
|
||||
const from = step.context.activity.from.id;
|
||||
const botId = step.result;
|
||||
const instance = await min.core.loadInstanceByBotId(botId);
|
||||
await sec.updateUserInstance(from, instance.instanceId);
|
||||
await min.conversationalService.sendText(min, step, `Opa, vamos lá!`);
|
||||
|
||||
|
||||
return await step.next();
|
||||
}
|
||||
]));
|
||||
|
|
|
@ -39,9 +39,9 @@
|
|||
import { BotAdapter } from 'botbuilder';
|
||||
import {WaterfallDialog } from 'botbuilder-dialogs';
|
||||
import { GBMinInstance, IGBDialog } from 'botlib';
|
||||
import { Messages } from '../strings';
|
||||
import { GBServer } from '../../../src/app';
|
||||
import { GBConversationalService } from '../services/GBConversationalService';
|
||||
import { Messages } from '../strings';
|
||||
|
||||
/**
|
||||
* Dialog for Welcoming people.
|
||||
|
@ -59,16 +59,15 @@ export class WelcomeDialog extends IGBDialog {
|
|||
async step => {
|
||||
|
||||
if (GBServer.globals.entryPointDialog !== null &&
|
||||
min.instance.botId === process.env.BOT_ID &&
|
||||
step.context.activity.channelId === "webchat")
|
||||
{
|
||||
min.instance.botId === process.env.BOT_ID &&
|
||||
step.context.activity.channelId === 'webchat') {
|
||||
return step.replaceDialog(GBServer.globals.entryPointDialog);
|
||||
}
|
||||
|
||||
const user = await min.userProfile.get(step.context, {});
|
||||
const locale = step.context.activity.locale;
|
||||
|
||||
if (!user.once && step.context.activity.channelId === "webchat") {
|
||||
if (!user.once && step.context.activity.channelId === 'webchat') {
|
||||
user.once = true;
|
||||
await min.userProfile.set(step.context, user);
|
||||
const a = new Date();
|
||||
|
@ -81,7 +80,7 @@ export class WelcomeDialog extends IGBDialog {
|
|||
: Messages[locale].good_night;
|
||||
|
||||
await min.conversationalService.sendText(min, step, Messages[locale].hi(msg));
|
||||
|
||||
|
||||
await step.replaceDialog('/ask', { firstTime: true });
|
||||
|
||||
if (
|
||||
|
|
|
@ -39,8 +39,8 @@
|
|||
import { BotAdapter } from 'botbuilder';
|
||||
import { WaterfallDialog } from 'botbuilder-dialogs';
|
||||
import { GBMinInstance, IGBDialog } from 'botlib';
|
||||
import { Messages } from '../strings';
|
||||
import { GBConversationalService } from '../services/GBConversationalService';
|
||||
import { Messages } from '../strings';
|
||||
/**
|
||||
* Dialog for the bot explains about itself.
|
||||
*/
|
||||
|
|
|
@ -50,7 +50,8 @@ import { GuaribasChannel, GuaribasException, GuaribasInstance, GuaribasPackage }
|
|||
*/
|
||||
export class GBCorePackage implements IGBPackage {
|
||||
public sysPackages: IGBPackage[];
|
||||
public CurrentEngineName = "guaribas-1.0.0";
|
||||
public CurrentEngineName = 'guaribas-1.0.0';
|
||||
|
||||
public async loadPackage(core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||
core.sequelize.addModels([GuaribasInstance, GuaribasPackage, GuaribasChannel, GuaribasException]);
|
||||
}
|
||||
|
@ -71,7 +72,6 @@ export class GBCorePackage implements IGBPackage {
|
|||
GBLog.verbose(`onExchangeData called.`);
|
||||
}
|
||||
|
||||
|
||||
public async loadBot(min: GBMinInstance): Promise<void> {
|
||||
WelcomeDialog.setup(min.bot, min);
|
||||
WhoAmIDialog.setup(min.bot, min);
|
||||
|
|
|
@ -102,7 +102,6 @@ export class GuaribasInstance extends Model<GuaribasInstance>
|
|||
@Column
|
||||
public textAnalyticsEndpoint: string;
|
||||
|
||||
|
||||
@Column({ type: DataType.STRING(64) })
|
||||
public translatorKey: string;
|
||||
|
||||
|
@ -333,7 +332,7 @@ export class GuaribasException extends Model<GuaribasException> {
|
|||
@Table
|
||||
//tslint:disable-next-line:max-classes-per-file
|
||||
export class GuaribasApplications extends Model<GuaribasApplications> {
|
||||
|
||||
|
||||
@Column
|
||||
public name: string;
|
||||
|
||||
|
@ -353,11 +352,10 @@ export class GuaribasApplications extends Model<GuaribasApplications> {
|
|||
public updatedAt: Date;
|
||||
}
|
||||
|
||||
|
||||
@Table
|
||||
//tslint:disable-next-line:max-classes-per-file
|
||||
export class GuaribasSchedule extends Model<GuaribasSchedule> {
|
||||
|
||||
|
||||
@Column
|
||||
public name: string;
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ import { GBLog } from 'botlib';
|
|||
* Base configuration for the server like storage.
|
||||
*/
|
||||
export class GBConfigService {
|
||||
static getBoolean(value: string): boolean {
|
||||
public static getBoolean(value: string): boolean {
|
||||
return this.get(value) as unknown as boolean;
|
||||
}
|
||||
public static getServerPort(): string {
|
||||
|
|
|
@ -44,21 +44,21 @@ const child_process = require('child_process');
|
|||
const graph = require('@microsoft/microsoft-graph-client');
|
||||
const rimraf = require('rimraf');
|
||||
|
||||
import { GBError, GBLog, GBMinInstance, IGBCoreService, IGBInstance, IGBPackage, IGBDeployer } from 'botlib';
|
||||
import { GBError, GBLog, GBMinInstance, IGBCoreService, IGBDeployer, IGBInstance, IGBPackage } from 'botlib';
|
||||
import { AzureSearch } from 'pragmatismo-io-framework';
|
||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||
import { GBServer } from '../../../src/app';
|
||||
import { GBVMService } from '../../basic.gblib/services/GBVMService';
|
||||
import { GuaribasPackage } from '../models/GBModel';
|
||||
import { GBAdminService } from './../../admin.gbapp/services/GBAdminService';
|
||||
import { AzureDeployerService } from './../../azuredeployer.gbapp/services/AzureDeployerService';
|
||||
import { KBService } from './../../kb.gbapp/services/KBService';
|
||||
import { GBConfigService } from './GBConfigService';
|
||||
import { GBImporter } from './GBImporterService';
|
||||
import { GBVMService } from '../../basic.gblib/services/GBVMService';
|
||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||
const MicrosoftGraph = require('@microsoft/microsoft-graph-client');
|
||||
|
||||
/**
|
||||
* Deployer service for bots, themes, ai and more.
|
||||
* Deployer service for bots, themes, ai and more.
|
||||
*/
|
||||
export class GBDeployer implements IGBDeployer {
|
||||
|
||||
|
@ -77,7 +77,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
*/
|
||||
public core: IGBCoreService;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Reference to the importer service.
|
||||
*/
|
||||
public importer: GBImporter;
|
||||
|
@ -112,7 +112,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
}
|
||||
const botPackages: string[] = [];
|
||||
const gbappPackages: string[] = [];
|
||||
let generalPackages: string[] = [];
|
||||
const generalPackages: string[] = [];
|
||||
|
||||
async function scanPackageDirectory(path) {
|
||||
|
||||
|
@ -126,7 +126,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
const dirs = getDirectories(path);
|
||||
await CollectionUtil.asyncForEach(dirs, async element => {
|
||||
|
||||
|
||||
// For each folder, checks its extensions looking for valid packages.
|
||||
|
||||
element = element.toLowerCase();
|
||||
|
@ -166,7 +165,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
|
||||
// Deploys all .gblib files first.
|
||||
|
||||
let list = [];
|
||||
const list = [];
|
||||
for (let index = 0; index < gbappPackages.length; index++) {
|
||||
const element = gbappPackages[index];
|
||||
if (element.endsWith('.gblib')) {
|
||||
|
@ -187,7 +186,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
const instances = await core.loadInstances();
|
||||
await CollectionUtil.asyncForEach(instances, async instance => {
|
||||
this.mountGBKBAssets(`${instance.botId}.gbkb`,
|
||||
instance.botId, `${instance.botId}.gbkb`);
|
||||
instance.botId, `${instance.botId}.gbkb`);
|
||||
});
|
||||
|
||||
GBLog.info(`Package deployment done.`);
|
||||
|
@ -200,7 +199,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
|
||||
// Creates a new row on the GuaribasInstance table.
|
||||
|
||||
let instance = await this.importer.createBotInstance(botId);
|
||||
const instance = await this.importer.createBotInstance(botId);
|
||||
const bootInstance = GBServer.globals.bootInstance;
|
||||
|
||||
// Gets the access token to perform service operations.
|
||||
|
@ -210,7 +209,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
// Creates the MSFT application that will be associated to the bot.
|
||||
|
||||
const service = new AzureDeployerService(this);
|
||||
let application = await service.createApplication(accessToken, botId);
|
||||
const application = await service.createApplication(accessToken, botId);
|
||||
|
||||
// Fills new instance base information and get App secret.
|
||||
|
||||
|
@ -240,6 +239,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
*/
|
||||
public async botExists(botId: string): Promise<boolean> {
|
||||
const service = new AzureDeployerService(this);
|
||||
|
||||
return await service.botExists(botId);
|
||||
}
|
||||
|
||||
|
@ -267,13 +267,9 @@ export class GBDeployer implements IGBDeployer {
|
|||
instance.description,
|
||||
`${publicAddress}/api/messages/${instance.botId}`
|
||||
);
|
||||
}
|
||||
|
||||
// Otherwise, perform the bot creation.
|
||||
|
||||
else {
|
||||
let botId = GBConfigService.get('BOT_ID');
|
||||
let bootInstance = await this.core.loadInstanceByBotId(botId);
|
||||
} else {
|
||||
const botId = GBConfigService.get('BOT_ID');
|
||||
const bootInstance = await this.core.loadInstanceByBotId(botId);
|
||||
|
||||
instance.searchHost = bootInstance.searchHost;
|
||||
instance.searchIndex = bootInstance.searchIndex;
|
||||
|
@ -324,8 +320,8 @@ export class GBDeployer implements IGBDeployer {
|
|||
public async publishNLP(instance: IGBInstance): Promise<void> {
|
||||
const service = new AzureDeployerService(this);
|
||||
const res = await service.publishNLP(instance.cloudLocation, instance.nlpAppId,
|
||||
instance.nlpAuthoringKey);
|
||||
if (res.status !== 200 && res.status !== 201) throw res.bodyAsText;
|
||||
instance.nlpAuthoringKey);
|
||||
if (res.status !== 200 && res.status !== 201) { throw res.bodyAsText; }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -334,8 +330,8 @@ export class GBDeployer implements IGBDeployer {
|
|||
public async trainNLP(instance: IGBInstance): Promise<void> {
|
||||
const service = new AzureDeployerService(this);
|
||||
const res = await service.trainNLP(instance.cloudLocation, instance.nlpAppId, instance.nlpAuthoringKey);
|
||||
if (res.status !== 200 && res.status !== 202) throw res.bodyAsText;
|
||||
let sleep = ms => {
|
||||
if (res.status !== 200 && res.status !== 202) { throw res.bodyAsText; }
|
||||
const sleep = ms => {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, ms);
|
||||
});
|
||||
|
@ -355,7 +351,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
instance.nlpAuthoringKey,
|
||||
listData
|
||||
);
|
||||
if (res.status !== 200) throw res.bodyAsText;
|
||||
if (res.status !== 200) { throw res.bodyAsText; }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -363,7 +359,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
*/
|
||||
public async deployBotFromLocalPath(localPath: string, publicAddress: string): Promise<void> {
|
||||
const packageName = Path.basename(localPath);
|
||||
let instance = await this.importer.importIfNotExistsBotPackage(undefined, packageName, localPath);
|
||||
const instance = await this.importer.importIfNotExistsBotPackage(undefined, packageName, localPath);
|
||||
await this.deployBotFull(instance, publicAddress);
|
||||
}
|
||||
|
||||
|
@ -374,10 +370,10 @@ export class GBDeployer implements IGBDeployer {
|
|||
|
||||
// Connects to MSFT storage.
|
||||
|
||||
let token = await min.adminService.acquireElevatedToken(min.instance.instanceId);
|
||||
let siteId = process.env.STORAGE_SITE_ID;
|
||||
let libraryId = process.env.STORAGE_LIBRARY;
|
||||
let client = MicrosoftGraph.Client.init({
|
||||
const token = await min.adminService.acquireElevatedToken(min.instance.instanceId);
|
||||
const siteId = process.env.STORAGE_SITE_ID;
|
||||
const libraryId = process.env.STORAGE_LIBRARY;
|
||||
const client = MicrosoftGraph.Client.init({
|
||||
authProvider: done => {
|
||||
done(null, token);
|
||||
}
|
||||
|
@ -387,24 +383,25 @@ export class GBDeployer implements IGBDeployer {
|
|||
|
||||
const botId = min.instance.botId;
|
||||
const path = `/${botId}.gbai/${botId}.gbot`;
|
||||
let res = await client
|
||||
const res = await client
|
||||
.api(`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/root:${path}:/children`)
|
||||
.get();
|
||||
|
||||
// Finds Config.xlsx.
|
||||
|
||||
let document = res.value.filter(m => {
|
||||
const document = res.value.filter(m => {
|
||||
return m.name === 'Config.xlsx';
|
||||
});
|
||||
if (document === undefined || document.length === 0) {
|
||||
GBLog.info(`Config.xlsx not found on .bot folder, check the package.`);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Reads all rows in Config.xlsx that contains a pair of name/value
|
||||
// and fills an object that is returned to be saved in params instance field.
|
||||
|
||||
let results = await client
|
||||
const results = await client
|
||||
.api(
|
||||
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/items/${document[0].id}/workbook/worksheets('General')/range(address='A7:B100')`
|
||||
)
|
||||
|
@ -416,6 +413,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
}
|
||||
obj[results.text[index][0]] = results.text[index][1];
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -494,7 +492,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
return pck;
|
||||
}
|
||||
|
||||
// Deploy platform packages here accordingly to their extension.
|
||||
// Deploy platform packages here accordingly to their extension.
|
||||
|
||||
switch (packageType) {
|
||||
case '.gbot':
|
||||
|
@ -585,6 +583,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
case '.gbkb':
|
||||
const service = new KBService(this.core.sequelize);
|
||||
rimraf.sync(localPath);
|
||||
|
||||
return await service.undeployKbFromStorage(instance, this, p.packageId);
|
||||
|
||||
case '.gbui':
|
||||
|
@ -712,7 +711,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
* Servers bot storage assets to be used by web, WhatsApp and other channels.
|
||||
*/
|
||||
public mountGBKBAssets(packageName: any, botId: string, filename: string) {
|
||||
|
||||
|
||||
// Servers menu assets.
|
||||
|
||||
GBServer.globals.server.use(
|
||||
|
@ -723,55 +722,18 @@ export class GBDeployer implements IGBDeployer {
|
|||
// Servers all other assets in .gbkb folders.
|
||||
|
||||
const gbaiName = `${botId}.gbai`;
|
||||
GBServer.globals.server.use(`/kb/${gbaiName}/${packageName}/assets`, express.static(urlJoin('work', gbaiName, filename, 'assets')));
|
||||
GBServer.globals.server.use(`/kb/${gbaiName}/${packageName}/images`, express.static(urlJoin('work', gbaiName, filename, 'images')));
|
||||
GBServer.globals.server.use(`/kb/${gbaiName}/${packageName}/audios`, express.static(urlJoin('work', gbaiName, filename, 'audios')));
|
||||
GBServer.globals.server.use(`/kb/${gbaiName}/${packageName}/videos`, express.static(urlJoin('work', gbaiName, filename, 'videos')));
|
||||
GBServer.globals.server.use(`/kb/${gbaiName}/${packageName}/assets`,
|
||||
express.static(urlJoin('work', gbaiName, filename, 'assets')));
|
||||
GBServer.globals.server.use(`/kb/${gbaiName}/${packageName}/images`,
|
||||
express.static(urlJoin('work', gbaiName, filename, 'images')));
|
||||
GBServer.globals.server.use(`/kb/${gbaiName}/${packageName}/audios`,
|
||||
express.static(urlJoin('work', gbaiName, filename, 'audios')));
|
||||
GBServer.globals.server.use(`/kb/${gbaiName}/${packageName}/videos`,
|
||||
express.static(urlJoin('work', gbaiName, filename, 'videos')));
|
||||
|
||||
GBLog.info(`KB (.gbkb) assets accessible at: /kb/${botId}.gbai/${packageName}.`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a given package is of system kind.
|
||||
*/
|
||||
private isSystemPackage(name: string): Boolean {
|
||||
const names = [
|
||||
'analytics.gblib',
|
||||
'console.gblib',
|
||||
'security.gbapp',
|
||||
'whatsapp.gblib',
|
||||
'sharepoint.gblib',
|
||||
'core.gbapp',
|
||||
'admin.gbapp',
|
||||
'azuredeployer.gbapp',
|
||||
'customer-satisfaction.gbapp',
|
||||
'kb.gbapp'
|
||||
];
|
||||
|
||||
return names.indexOf(name) > -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the process of compiling all .gbapp folders.
|
||||
*/
|
||||
private async deployAppPackages(gbappPackages: string[], core: any, appPackages: any[]) {
|
||||
|
||||
// Loops through all ready to load .gbapp packages.
|
||||
|
||||
let appPackagesProcessed = 0;
|
||||
await CollectionUtil.asyncForEach(gbappPackages, async e => {
|
||||
const filenameOnly = Path.basename(e);
|
||||
|
||||
// Skips .gbapp inside deploy folder.
|
||||
|
||||
if (this.isSystemPackage(filenameOnly) === false) {
|
||||
appPackagesProcessed = await this.callGBAppCompiler(e, core, appPackages, appPackagesProcessed);
|
||||
}
|
||||
});
|
||||
|
||||
return appPackagesProcessed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes Type Script compiler for a given .gbapp package (Node.js based).
|
||||
*/
|
||||
|
@ -792,7 +754,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
child_process.execSync('npm install', { cwd: gbappPath });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
folder = Path.join(gbappPath, 'dist');
|
||||
try {
|
||||
|
||||
|
@ -823,6 +785,48 @@ export class GBDeployer implements IGBDeployer {
|
|||
}
|
||||
appPackagesProcessed++;
|
||||
}
|
||||
|
||||
return appPackagesProcessed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a given package is of system kind.
|
||||
*/
|
||||
private isSystemPackage(name: string): Boolean {
|
||||
const names = [
|
||||
'analytics.gblib',
|
||||
'console.gblib',
|
||||
'security.gbapp',
|
||||
'whatsapp.gblib',
|
||||
'sharepoint.gblib',
|
||||
'core.gbapp',
|
||||
'admin.gbapp',
|
||||
'azuredeployer.gbapp',
|
||||
'customer-satisfaction.gbapp',
|
||||
'kb.gbapp'
|
||||
];
|
||||
|
||||
return names.indexOf(name) > -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the process of compiling all .gbapp folders.
|
||||
*/
|
||||
private async deployAppPackages(gbappPackages: string[], core: any, appPackages: any[]) {
|
||||
|
||||
// Loops through all ready to load .gbapp packages.
|
||||
|
||||
let appPackagesProcessed = 0;
|
||||
await CollectionUtil.asyncForEach(gbappPackages, async e => {
|
||||
const filenameOnly = Path.basename(e);
|
||||
|
||||
// Skips .gbapp inside deploy folder.
|
||||
|
||||
if (this.isSystemPackage(filenameOnly) === false) {
|
||||
appPackagesProcessed = await this.callGBAppCompiler(e, core, appPackages, appPackagesProcessed);
|
||||
}
|
||||
});
|
||||
|
||||
return appPackagesProcessed;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,12 +36,12 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
import { IGBCoreService, IGBInstance, GBMinInstance } from 'botlib';
|
||||
import { GBMinInstance, IGBCoreService, IGBInstance } from 'botlib';
|
||||
import fs = require('fs');
|
||||
import urlJoin = require('url-join');
|
||||
import { GBServer } from '../../../src/app';
|
||||
import { GuaribasInstance } from '../models/GBModel';
|
||||
import { GBConfigService } from './GBConfigService';
|
||||
import { GBServer } from '../../../src/app';
|
||||
|
||||
/**
|
||||
* Handles the importing of packages.
|
||||
|
@ -53,8 +53,8 @@ export class GBImporter {
|
|||
this.core = core;
|
||||
}
|
||||
|
||||
public async importIfNotExistsBotPackage(botId: string,
|
||||
packageName: string, localPath: string, additionalInstance: IGBInstance = null) {
|
||||
public async importIfNotExistsBotPackage(botId: string,
|
||||
packageName: string, localPath: string, additionalInstance: IGBInstance = null) {
|
||||
const settingsJson = JSON.parse(fs.readFileSync(urlJoin(localPath, 'settings.json'), 'utf8'));
|
||||
if (botId === undefined) {
|
||||
botId = settingsJson.botId;
|
||||
|
@ -84,10 +84,9 @@ export class GBImporter {
|
|||
instance = await this.core.loadInstanceByBotId(botId);
|
||||
}
|
||||
|
||||
if (instance != null && instance.botId === null) {
|
||||
if (instance != undefined && instance.botId === null) {
|
||||
console.log(`Null BotId after load instance with botId: ${botId}.`);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
instance = additionalInstance;
|
||||
}
|
||||
|
||||
|
@ -95,8 +94,9 @@ export class GBImporter {
|
|||
}
|
||||
|
||||
public async createBotInstance(botId: string) {
|
||||
let fullSettingsJson = { ...GBServer.globals.bootInstance };
|
||||
const fullSettingsJson = { ...GBServer.globals.bootInstance };
|
||||
fullSettingsJson.botId = botId;
|
||||
|
||||
return await GuaribasInstance.create(fullSettingsJson);
|
||||
}
|
||||
|
||||
|
@ -106,10 +106,10 @@ export class GBImporter {
|
|||
localPath: string,
|
||||
settingsJson: any
|
||||
) {
|
||||
let packageJson = JSON.parse(fs.readFileSync(urlJoin(localPath, 'package.json'), 'utf8'));
|
||||
const packageJson = JSON.parse(fs.readFileSync(urlJoin(localPath, 'package.json'), 'utf8'));
|
||||
const servicesJson = JSON.parse(fs.readFileSync(urlJoin(localPath, 'services.json'), 'utf8'));
|
||||
|
||||
let fullSettingsJson = { ...GBServer.globals.bootInstance, ...packageJson, ...settingsJson, ...servicesJson };
|
||||
const fullSettingsJson = { ...GBServer.globals.bootInstance, ...packageJson, ...settingsJson, ...servicesJson };
|
||||
|
||||
if (botId !== undefined) {
|
||||
fullSettingsJson.botId = botId;
|
||||
|
|
|
@ -51,7 +51,6 @@ import {
|
|||
TurnContext,
|
||||
UserState
|
||||
} from 'botbuilder';
|
||||
import { CollectionUtil, AzureText } from 'pragmatismo-io-framework';
|
||||
import { ConfirmPrompt, OAuthPrompt, WaterfallDialog } from 'botbuilder-dialogs';
|
||||
import {
|
||||
GBDialogStep,
|
||||
|
@ -63,28 +62,34 @@ import {
|
|||
IGBInstance,
|
||||
IGBPackage
|
||||
} from 'botlib';
|
||||
import { AzureText, CollectionUtil } from 'pragmatismo-io-framework';
|
||||
|
||||
import { MicrosoftAppCredentials } from 'botframework-connector';
|
||||
import fs = require('fs');
|
||||
import { GBServer } from '../../../src/app';
|
||||
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService';
|
||||
import { GuaribasConversationMessage } from '../../analytics.gblib/models';
|
||||
import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService';
|
||||
import { GBVMService } from '../../basic.gblib/services/GBVMService';
|
||||
import { AskDialogArgs } from '../../kb.gbapp/dialogs/AskDialog';
|
||||
import { KBService } from '../../kb.gbapp/services/KBService';
|
||||
import { SecService } from '../../security.gbapp/services/SecService';
|
||||
import { WhatsappDirectLine } from '../../whatsapp.gblib/services/WhatsappDirectLine';
|
||||
import { Messages } from '../strings';
|
||||
import { GBConfigService } from './GBConfigService';
|
||||
import { GBDeployer } from './GBDeployer';
|
||||
import { SecService } from '../../security.gbapp/services/SecService';
|
||||
import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService';
|
||||
import { WhatsappDirectLine } from '../../whatsapp.gblib/services/WhatsappDirectLine';
|
||||
import fs = require('fs');
|
||||
import { GuaribasConversationMessage } from '../../analytics.gblib/models';
|
||||
import { GBVMService } from '../../basic.gblib/services/GBVMService';
|
||||
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService';
|
||||
import { GBConversationalService } from './GBConversationalService';
|
||||
import { GBDeployer } from './GBDeployer';
|
||||
|
||||
/**
|
||||
* Minimal service layer for a bot and encapsulation of BOT Framework calls.
|
||||
*/
|
||||
export class GBMinService {
|
||||
|
||||
/**
|
||||
* Default General Bots User Interface package.
|
||||
*/
|
||||
private static uiPackage = 'default.gbui';
|
||||
|
||||
/**
|
||||
* Main core service attached to this bot service.
|
||||
*/
|
||||
|
@ -105,11 +110,6 @@ export class GBMinService {
|
|||
*/
|
||||
public deployer: GBDeployer;
|
||||
|
||||
/**
|
||||
* Default General Bots User Interface package.
|
||||
*/
|
||||
private static uiPackage = 'default.gbui';
|
||||
|
||||
/**
|
||||
* Static initialization of minimal instance.
|
||||
*
|
||||
|
@ -127,118 +127,6 @@ export class GBMinService {
|
|||
this.deployer = deployer;
|
||||
}
|
||||
|
||||
|
||||
private async WhatsAppCallback(req, res) {
|
||||
try {
|
||||
|
||||
// Detects if the message is echo fro itself.
|
||||
|
||||
const id = req.body.messages[0].chatId.split('@')[0];
|
||||
const senderName = req.body.messages[0].senderName;
|
||||
const text = req.body.messages[0].body;
|
||||
if (req.body.messages[0].fromMe) {
|
||||
res.end();
|
||||
return; // Exit here.
|
||||
}
|
||||
|
||||
// Detects if the welcome message is enabled.
|
||||
|
||||
let activeMin;
|
||||
if (process.env.WHATSAPP_WELCOME_DISABLED !== 'true') {
|
||||
|
||||
// Tries to find if user wants to switch bots.
|
||||
|
||||
let toSwitchMin = GBServer.globals.minInstances.filter(
|
||||
p => p.instance.botId.toLowerCase() === text.toLowerCase()
|
||||
)[0];
|
||||
if (!toSwitchMin) {
|
||||
toSwitchMin = GBServer.globals.minInstances.filter(p =>
|
||||
p.instance.activationCode ? p.instance.activationCode.toLowerCase() === text.toLowerCase() : false
|
||||
)[0];
|
||||
}
|
||||
|
||||
// Find active bot instance.
|
||||
|
||||
activeMin = toSwitchMin ? toSwitchMin : GBServer.globals.minBoot;
|
||||
|
||||
// If it is the first time for the user, tries to auto-execute
|
||||
// start dialog if any is specified in Config.xlsx.
|
||||
|
||||
let sec = new SecService();
|
||||
let user = await sec.getUserFromSystemId(id);
|
||||
if (user === null || user.hearOnDialog) {
|
||||
user = await sec.ensureUser(activeMin.instance.instanceId, id, senderName, '', 'whatsapp', senderName);
|
||||
|
||||
let startDialog = user.hearOnDialog ?
|
||||
user.hearOnDialog :
|
||||
activeMin.core.getParam(activeMin.instance, 'Start Dialog', null);
|
||||
|
||||
GBLog.info(`Auto start dialog is now being called: ${startDialog}...`);
|
||||
if (startDialog) {
|
||||
req.body.messages[0].body = `${startDialog}`;
|
||||
|
||||
// Resets HEAR ON DIALOG value to none and passes
|
||||
// current dialog to the direct line.
|
||||
|
||||
await sec.updateUserHearOnDialog(user.userId, null);
|
||||
await (activeMin as any).whatsAppDirectLine.received(req, res);
|
||||
}
|
||||
else {
|
||||
await (activeMin as any).whatsAppDirectLine.sendToDevice(
|
||||
id,
|
||||
`Olá! Seja bem-vinda(o)!\nMe chamo ${activeMin.instance.title}. Como posso ajudar? Pode me falar que eu te ouço, me manda um aúdio.`
|
||||
);
|
||||
res.end();
|
||||
}
|
||||
} else {
|
||||
|
||||
// User wants to switch bots.
|
||||
|
||||
if (toSwitchMin !== undefined) {
|
||||
|
||||
// So gets the new bot instance information and prepares to
|
||||
// auto start dialog if any is specified.
|
||||
|
||||
const instance = await this.core.loadInstanceByBotId(activeMin.botId);
|
||||
await sec.updateUserInstance(id, instance.instanceId);
|
||||
await (activeMin as any).whatsAppDirectLine.resetConversationId(id);
|
||||
let startDialog = activeMin.core.getParam(activeMin.instance, 'Start Dialog', null);
|
||||
GBLog.info(`Auto start dialog is now being called: ${startDialog}...`);
|
||||
|
||||
if (startDialog) {
|
||||
req.body.messages[0].body = `${startDialog}`;
|
||||
await (activeMin as any).whatsAppDirectLine.received(req, res);
|
||||
}
|
||||
else {
|
||||
await (activeMin as any).whatsAppDirectLine.sendToDevice(
|
||||
id,
|
||||
`Agora falando com ${activeMin.instance.title}...`
|
||||
);
|
||||
res.end();
|
||||
}
|
||||
} else {
|
||||
activeMin = GBServer.globals.minInstances.filter(p => p.instance.instanceId === user.instanceId)[0];
|
||||
if (activeMin === undefined) {
|
||||
activeMin = GBServer.globals.minBoot;
|
||||
await (activeMin as any).whatsAppDirectLine.sendToDevice(
|
||||
id,
|
||||
`O outro Bot que você estava falando(${user.instanceId}), não está mais disponível. Agora você está falando comigo, ${activeMin.instance.title}...`
|
||||
);
|
||||
}
|
||||
await (activeMin as any).whatsAppDirectLine.received(req, res);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// Just pass the message to the receiver.
|
||||
|
||||
await (GBServer.globals.minBoot as any).whatsAppDirectLine.received(req, res);
|
||||
}
|
||||
} catch (error) {
|
||||
GBLog.error(`Error on Whatsapp callback: ${error.data ? error.data : error}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new minimal instance for each bot.
|
||||
*/
|
||||
|
@ -246,7 +134,7 @@ export class GBMinService {
|
|||
|
||||
// Servers default UI on root address '/' if web enabled.
|
||||
if (process.env.DISABLE_WEB !== 'true') {
|
||||
let url = GBServer.globals.wwwroot
|
||||
const url = GBServer.globals.wwwroot
|
||||
? GBServer.globals.wwwroot
|
||||
: urlJoin(GBDeployer.deployFolder, GBMinService.uiPackage, 'build');
|
||||
|
||||
|
@ -257,12 +145,12 @@ export class GBMinService {
|
|||
// instance information stored on server.
|
||||
|
||||
if (process.env.DISABLE_WEB !== 'true') {
|
||||
GBServer.globals.server.get('/instances/:botId', this.handleGetInstanceForClient);
|
||||
GBServer.globals.server.get('/instances/:botId', this.handleGetInstanceForClient.bind(this));
|
||||
}
|
||||
|
||||
// Servers the WhatsApp callback.
|
||||
|
||||
GBServer.globals.server.post('/webhooks/whatsapp', this.WhatsAppCallback);
|
||||
GBServer.globals.server.post('/webhooks/whatsapp', this.WhatsAppCallback.bind(this));
|
||||
|
||||
// Call mountBot event to all bots.
|
||||
|
||||
|
@ -372,6 +260,116 @@ export class GBMinService {
|
|||
this.createCheckHealthAddress(GBServer.globals.server, min, min.instance);
|
||||
}
|
||||
|
||||
private async WhatsAppCallback(req, res) {
|
||||
try {
|
||||
|
||||
// Detects if the message is echo fro itself.
|
||||
|
||||
const id = req.body.messages[0].chatId.split('@')[0];
|
||||
const senderName = req.body.messages[0].senderName;
|
||||
const text = req.body.messages[0].body;
|
||||
if (req.body.messages[0].fromMe) {
|
||||
res.end();
|
||||
|
||||
return; // Exit here.
|
||||
}
|
||||
|
||||
// Detects if the welcome message is enabled.
|
||||
|
||||
let activeMin;
|
||||
if (process.env.WHATSAPP_WELCOME_DISABLED !== 'true') {
|
||||
|
||||
// Tries to find if user wants to switch bots.
|
||||
|
||||
let toSwitchMin = GBServer.globals.minInstances.filter(
|
||||
p => p.instance.botId.toLowerCase() === text.toLowerCase()
|
||||
)[0];
|
||||
if (!toSwitchMin) {
|
||||
toSwitchMin = GBServer.globals.minInstances.filter(p =>
|
||||
p.instance.activationCode ? p.instance.activationCode.toLowerCase() === text.toLowerCase() : false
|
||||
)[0];
|
||||
}
|
||||
|
||||
// Find active bot instance.
|
||||
|
||||
activeMin = toSwitchMin ? toSwitchMin : GBServer.globals.minBoot;
|
||||
|
||||
// If it is the first time for the user, tries to auto-execute
|
||||
// start dialog if any is specified in Config.xlsx.
|
||||
|
||||
const sec = new SecService();
|
||||
let user = await sec.getUserFromSystemId(id);
|
||||
if (user === null || user.hearOnDialog) {
|
||||
user = await sec.ensureUser(activeMin.instance.instanceId, id, senderName, '', 'whatsapp', senderName);
|
||||
|
||||
const startDialog = user.hearOnDialog ?
|
||||
user.hearOnDialog :
|
||||
activeMin.core.getParam(activeMin.instance, 'Start Dialog', null);
|
||||
|
||||
GBLog.info(`Auto start dialog is now being called: ${startDialog}...`);
|
||||
if (startDialog) {
|
||||
req.body.messages[0].body = `${startDialog}`;
|
||||
|
||||
// Resets HEAR ON DIALOG value to none and passes
|
||||
// current dialog to the direct line.
|
||||
|
||||
await sec.updateUserHearOnDialog(user.userId, null);
|
||||
await (activeMin as any).whatsAppDirectLine.received(req, res);
|
||||
} else {
|
||||
await (activeMin as any).whatsAppDirectLine.sendToDevice(
|
||||
id,
|
||||
`Olá! Seja bem-vinda(o)!\nMe chamo ${activeMin.instance.title}. Como posso ajudar? Pode me falar que eu te ouço, me manda um aúdio.`
|
||||
);
|
||||
res.end();
|
||||
}
|
||||
} else {
|
||||
|
||||
// User wants to switch bots.
|
||||
|
||||
if (toSwitchMin !== undefined) {
|
||||
|
||||
// So gets the new bot instance information and prepares to
|
||||
// auto start dialog if any is specified.
|
||||
|
||||
const instance = await this.core.loadInstanceByBotId(activeMin.botId);
|
||||
await sec.updateUserInstance(id, instance.instanceId);
|
||||
await (activeMin as any).whatsAppDirectLine.resetConversationId(id);
|
||||
const startDialog = activeMin.core.getParam(activeMin.instance, 'Start Dialog', null);
|
||||
GBLog.info(`Auto start dialog is now being called: ${startDialog}...`);
|
||||
|
||||
if (startDialog) {
|
||||
req.body.messages[0].body = `${startDialog}`;
|
||||
await (activeMin as any).whatsAppDirectLine.received(req, res);
|
||||
} else {
|
||||
await (activeMin as any).whatsAppDirectLine.sendToDevice(
|
||||
id,
|
||||
`Agora falando com ${activeMin.instance.title}...`
|
||||
);
|
||||
res.end();
|
||||
}
|
||||
} else {
|
||||
activeMin = GBServer.globals.minInstances.filter(p => p.instance.instanceId === user.instanceId)[0];
|
||||
if (activeMin === undefined) {
|
||||
activeMin = GBServer.globals.minBoot;
|
||||
await (activeMin as any).whatsAppDirectLine.sendToDevice(
|
||||
id,
|
||||
`O outro Bot que você estava falando(${user.instanceId}), não está mais disponível. Agora você está falando comigo, ${activeMin.instance.title}...`
|
||||
);
|
||||
}
|
||||
await (activeMin as any).whatsAppDirectLine.received(req, res);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// Just pass the message to the receiver.
|
||||
|
||||
await (GBServer.globals.minBoot as any).whatsAppDirectLine.received(req, res);
|
||||
}
|
||||
} catch (error) {
|
||||
GBLog.error(`Error on Whatsapp callback: ${error.data ? error.data : error}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a listener that can be used by external monitors to check
|
||||
* bot instance health.
|
||||
|
@ -499,7 +497,7 @@ export class GBMinService {
|
|||
// Gets the webchat token, speech token and theme.
|
||||
|
||||
const webchatTokenContainer = await this.getWebchatToken(instance);
|
||||
const speechToken = instance.speechKey != null ? await this.getSTSToken(instance) : null;
|
||||
const speechToken = instance.speechKey != undefined ? await this.getSTSToken(instance) : null;
|
||||
let theme = instance.theme;
|
||||
|
||||
// Sends all information to the .gbui web client.
|
||||
|
@ -540,9 +538,11 @@ export class GBMinService {
|
|||
|
||||
try {
|
||||
const json = await request(options);
|
||||
|
||||
return JSON.parse(json);
|
||||
} catch (error) {
|
||||
const msg = `[botId:${instance.botId}] Error calling Direct Line to generate a token for Web control: ${error}.`;
|
||||
|
||||
return Promise.reject(new Error(msg));
|
||||
}
|
||||
}
|
||||
|
@ -575,13 +575,14 @@ export class GBMinService {
|
|||
|
||||
// MSFT stuff.
|
||||
|
||||
const adapter = new BotFrameworkAdapter({ appId: instance.marketplaceId, appPassword: instance.marketplacePassword });
|
||||
const adapter = new BotFrameworkAdapter(
|
||||
{ appId: instance.marketplaceId, appPassword: instance.marketplacePassword });
|
||||
const storage = new MemoryStorage();
|
||||
const conversationState = new ConversationState(storage);
|
||||
const userState = new UserState(storage);
|
||||
adapter.use(new AutoSaveStateMiddleware(conversationState, userState));
|
||||
MicrosoftAppCredentials.trustServiceUrl('https://directline.botframework.com',
|
||||
new Date(new Date().setFullYear(new Date().getFullYear() + 10))
|
||||
new Date(new Date().setFullYear(new Date().getFullYear() + 10))
|
||||
);
|
||||
|
||||
// The minimal bot is built here.
|
||||
|
@ -611,7 +612,7 @@ export class GBMinService {
|
|||
await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => {
|
||||
let services: ConcatArray<never>;
|
||||
if ((services = await e.onExchangeData(min, 'getServices', null))) {
|
||||
min.gbappServices = Object.assign(min.gbappServices, services);
|
||||
min.gbappServices = {...min.gbappServices, ...services};
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -736,7 +737,7 @@ export class GBMinService {
|
|||
user.welcomed = false;
|
||||
firstTime = true;
|
||||
|
||||
// Sends loadInstance event to .gbui clients.
|
||||
// Sends loadInstance event to .gbui clients.
|
||||
|
||||
await min.conversationalService.sendEvent(min, step, 'loadInstance', {
|
||||
instanceId: instance.instanceId,
|
||||
|
@ -746,7 +747,7 @@ export class GBMinService {
|
|||
});
|
||||
|
||||
// This same event is dispatched either to all participants
|
||||
// including the bot, that is filtered bellow.
|
||||
// including the bot, that is filtered bellow.
|
||||
|
||||
if (context.activity.from.id !== min.botId) {
|
||||
|
||||
|
@ -762,7 +763,7 @@ export class GBMinService {
|
|||
member.name
|
||||
);
|
||||
|
||||
// Required for MSTEAMS handling of persisted conversations.
|
||||
// Required for MSTEAMS handling of persisted conversations.
|
||||
|
||||
if (step.context.activity.channelId === 'msteams') {
|
||||
persistedUser.conversationReference = JSON.stringify(
|
||||
|
@ -809,8 +810,7 @@ export class GBMinService {
|
|||
user.welcomed = true;
|
||||
GBLog.info(`Auto start dialog is now being called: ${startDialog}...`);
|
||||
await GBVMService.callVM(startDialog.toLowerCase(), min, step, this.deployer);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
|
||||
// Otherwise, calls / (root) to default welcome users.
|
||||
|
||||
|
@ -822,7 +822,6 @@ export class GBMinService {
|
|||
GBLog.info(`Member added to conversation: ${member.name}`);
|
||||
}
|
||||
|
||||
|
||||
} else if (context.activity.type === 'message') {
|
||||
|
||||
// Process messages activities.
|
||||
|
@ -896,7 +895,7 @@ export class GBMinService {
|
|||
// Removes <at>Bot Id</at> from MS Teams.
|
||||
|
||||
context.activity.text = context.activity.text.trim();
|
||||
context.activity.text = context.activity.text.replace(/\<at\>.*\<\/at\>\s/gi, '')
|
||||
context.activity.text = context.activity.text.replace(/\<at\>.*\<\/at\>\s/gi, '');
|
||||
|
||||
const user = await min.userProfile.get(context, {});
|
||||
let message: GuaribasConversationMessage;
|
||||
|
@ -931,64 +930,38 @@ export class GBMinService {
|
|||
const isVMCall = Object.keys(min.scriptMap).find(key => min.scriptMap[key] === context.activity.text) !== undefined;
|
||||
if (isVMCall) {
|
||||
await GBVMService.callVM(context.activity.text, min, step, this.deployer);
|
||||
}
|
||||
} else if (context.activity.text.charAt(0) === '/') {
|
||||
|
||||
// When user starts text by typing a slash, it can call either a dialog directly
|
||||
// or /call <script> will invoke VM for a given .gbdialog script.
|
||||
|
||||
else if (context.activity.text.charAt(0) === '/') {
|
||||
|
||||
let text = context.activity.text;
|
||||
let parts = text.split(' ');
|
||||
let cmdOrDialogName = parts[0];
|
||||
const text = context.activity.text;
|
||||
const parts = text.split(' ');
|
||||
const cmdOrDialogName = parts[0];
|
||||
parts.splice(0, 1);
|
||||
let args = parts.join(' ');
|
||||
const args = parts.join(' ');
|
||||
|
||||
if (cmdOrDialogName === '/call') {
|
||||
await GBVMService.callVM(args, min, step, this.deployer);
|
||||
} else {
|
||||
await step.beginDialog(cmdOrDialogName, { args: args });
|
||||
}
|
||||
}
|
||||
|
||||
// Processes global escape keywords like 'quit'.
|
||||
|
||||
else if (globalQuit(step.context.activity.locale, context.activity.text)) {
|
||||
} else if (globalQuit(step.context.activity.locale, context.activity.text)) {
|
||||
await step.cancelAllDialogs();
|
||||
await min.conversationalService.sendText(min, step, Messages[step.context.activity.locale].canceled);
|
||||
|
||||
}
|
||||
|
||||
// Handles the admin conversational keyword.
|
||||
|
||||
else if (context.activity.text === 'admin') {
|
||||
} else if (context.activity.text === 'admin') {
|
||||
await step.beginDialog('/admin');
|
||||
|
||||
}
|
||||
|
||||
// Checks for /menu JSON signature.
|
||||
|
||||
else if (context.activity.text.startsWith('{"title"')) {
|
||||
} else if (context.activity.text.startsWith('{"title"')) {
|
||||
await step.beginDialog('/menu', JSON.parse(context.activity.text));
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Checks if it is the first time the bot are talking and auto-publish default packages.
|
||||
|
||||
else if (
|
||||
} else if (
|
||||
!(await this.deployer.getStoragePackageByName(min.instance.instanceId, `${min.instance.botId}.gbkb`)) &&
|
||||
process.env.GBKB_ENABLE_AUTO_PUBLISH === "true"
|
||||
process.env.GBKB_ENABLE_AUTO_PUBLISH === 'true'
|
||||
) {
|
||||
await min.conversationalService.sendText(min, step,
|
||||
`Oi, ainda não possuo pacotes de conhecimento publicados. Por favor, aguarde alguns segundos enquanto eu auto-publico alguns pacotes.`
|
||||
`Oi, ainda não possuo pacotes de conhecimento publicados. Por favor, aguarde alguns segundos enquanto eu auto-publico alguns pacotes.`
|
||||
);
|
||||
await step.beginDialog('/publish', { confirm: true, firstTime: true });
|
||||
}
|
||||
|
||||
// Otherwise, continue to the default dialog processing of the input message.
|
||||
|
||||
else {
|
||||
} else {
|
||||
|
||||
// Removes unwanted chars in input text.
|
||||
|
||||
|
@ -997,14 +970,14 @@ export class GBMinService {
|
|||
text = text.replace(/<([^>]+?)([^>]*?)>(.*?)<\/\1>/gi, '');
|
||||
|
||||
// Saves special words (keep text) in tokens to prevent it from
|
||||
// spell checking and translation.
|
||||
// spell checking and translation.
|
||||
|
||||
const keepText: string = min.core.getParam(min.instance, 'Keep Text', '');
|
||||
let keepTextList = [];
|
||||
if (keepTextList) {
|
||||
keepTextList = keepTextList.concat(keepText.split(';'));
|
||||
}
|
||||
let replacements = [];
|
||||
const replacements = [];
|
||||
await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => {
|
||||
const result = await e.onExchangeData(min, 'getKeepText', {});
|
||||
if (result) {
|
||||
|
@ -1016,10 +989,10 @@ export class GBMinService {
|
|||
keepTextList = keepTextList.filter(p => p.trim() !== '');
|
||||
let i = 0;
|
||||
await CollectionUtil.asyncForEach(keepTextList, item => {
|
||||
let it = GBConversationalService.removeDiacritics(item);
|
||||
const it = GBConversationalService.removeDiacritics(item);
|
||||
|
||||
if (textProcessed.toLowerCase().indexOf(it.toLowerCase()) != -1) {
|
||||
const replacementToken = 'X' + GBAdminService['getNumberIdentifier']().substr(0, 4);
|
||||
const replacementToken = 'X' + GBAdminService.getNumberIdentifier().substr(0, 4);
|
||||
replacements[i] = { text: item, replacementToken: replacementToken };
|
||||
i++;
|
||||
textProcessed = textProcessed.replace(new RegExp(`\\b${it.trim()}\\b`, 'gi'), `${replacementToken}`);
|
||||
|
@ -1035,17 +1008,17 @@ export class GBMinService {
|
|||
// Detects user typed language and updates their locale profile if applies.
|
||||
|
||||
let locale = min.core.getParam<string>(min.instance, 'Default User Language',
|
||||
GBConfigService.get('DEFAULT_USER_LANGUAGE')
|
||||
GBConfigService.get('DEFAULT_USER_LANGUAGE')
|
||||
);
|
||||
let detectLanguage = min.core.getParam<boolean>(min.instance, 'Language Detector',
|
||||
GBConfigService.getBoolean('LANGUAGE_DETECTOR')
|
||||
const detectLanguage = min.core.getParam<boolean>(min.instance, 'Language Detector',
|
||||
GBConfigService.getBoolean('LANGUAGE_DETECTOR')
|
||||
) === 'true';
|
||||
const systemUser = user.systemUser;
|
||||
locale = systemUser.locale;
|
||||
if (detectLanguage || !locale) {
|
||||
locale = await min.conversationalService.getLanguage(min, text);
|
||||
if (systemUser.locale != locale) {
|
||||
let sec = new SecService();
|
||||
const sec = new SecService();
|
||||
user.systemUser = await sec.updateUserLocale(systemUser.userId, locale);
|
||||
await min.userProfile.set(step.context, user);
|
||||
}
|
||||
|
@ -1061,7 +1034,7 @@ export class GBMinService {
|
|||
// Translates text into content language, keeping
|
||||
// reserved tokens specified in Config.
|
||||
|
||||
let contentLocale = min.core.getParam<string>(
|
||||
const contentLocale = min.core.getParam<string>(
|
||||
min.instance,
|
||||
'Default Content Language',
|
||||
GBConfigService.get('DEFAULT_CONTENT_LANGUAGE')
|
||||
|
@ -1082,17 +1055,12 @@ export class GBMinService {
|
|||
context.activity.originalText = originalText;
|
||||
GBLog.info(`Final text ready for NLP/Search/.gbapp: ${text}.`);
|
||||
|
||||
|
||||
// If there is a dialog in course, continue to the next step.
|
||||
|
||||
if (step.activeDialog !== undefined) {
|
||||
await step.continueDialog();
|
||||
|
||||
}
|
||||
|
||||
// Checks if any .gbapp will handle this answer, if not goes to standard kb.gbapp.
|
||||
|
||||
else {
|
||||
} else {
|
||||
|
||||
let nextDialog = null;
|
||||
await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => {
|
||||
|
@ -1101,12 +1069,12 @@ export class GBMinService {
|
|||
step: step,
|
||||
notTranslatedQuery: originalText,
|
||||
message: message ? message['dataValues'] : null,
|
||||
user: user ? user['dataValues'] : null
|
||||
user: user ? user.dataValues : null
|
||||
});
|
||||
});
|
||||
await step.beginDialog(nextDialog ? nextDialog : '/answer', {
|
||||
query: text,
|
||||
user: user ? user['dataValues'] : null,
|
||||
user: user ? user.dataValues : null,
|
||||
message: message
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
export const Messages = {
|
||||
global_quit: /^(sair|sai|chega|exit|quit|finish|end|ausfahrt|verlassen)/i,
|
||||
'en-US': {
|
||||
|
||||
|
||||
},
|
||||
'pt-BR': {
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
|
|
@ -39,10 +39,10 @@
|
|||
import { BotAdapter } from 'botbuilder';
|
||||
import { WaterfallDialog } from 'botbuilder-dialogs';
|
||||
import { GBMinInstance, IGBDialog } from 'botlib';
|
||||
import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService';
|
||||
import { SecService } from '../../security.gbapp/services/SecService';
|
||||
import { CSService } from '../services/CSService';
|
||||
import { Messages } from '../strings';
|
||||
import { SecService } from '../../security.gbapp/services/SecService';
|
||||
import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService';
|
||||
|
||||
/**
|
||||
* Dialog for feedback collecting.
|
||||
|
@ -74,14 +74,14 @@ export class FeedbackDialog extends IGBDialog {
|
|||
|
||||
const locale = step.context.activity.locale;
|
||||
|
||||
let sec = new SecService();
|
||||
let from = step.context.activity.from.id;
|
||||
const sec = new SecService();
|
||||
const from = step.context.activity.from.id;
|
||||
|
||||
await min.conversationalService.sendText(min, step, Messages[locale].please_wait_transfering);
|
||||
let agentSystemId = await sec.assignHumanAgent(from, min.instance.instanceId);
|
||||
const agentSystemId = await sec.assignHumanAgent(from, min.instance.instanceId);
|
||||
|
||||
await min.whatsAppDirectLine.sendToDevice(agentSystemId,
|
||||
Messages[locale].notify_agent(step.context.activity.from.name));
|
||||
Messages[locale].notify_agent(step.context.activity.from.name));
|
||||
|
||||
return await step.next();
|
||||
}
|
||||
|
@ -94,8 +94,8 @@ export class FeedbackDialog extends IGBDialog {
|
|||
|
||||
const locale = step.context.activity.locale;
|
||||
|
||||
let sec = new SecService();
|
||||
let from = step.context.activity.from.id;
|
||||
const sec = new SecService();
|
||||
const from = step.context.activity.from.id;
|
||||
|
||||
await sec.updateCurrentAgent(from, min.instance.instanceId, null);
|
||||
await min.conversationalService.sendText(min, step, Messages[locale].notify_end_transfer(min.instance.botId));
|
||||
|
@ -105,7 +105,6 @@ export class FeedbackDialog extends IGBDialog {
|
|||
])
|
||||
);
|
||||
|
||||
|
||||
min.dialogs.add(
|
||||
new WaterfallDialog('/feedbackNumber', [
|
||||
async step => {
|
||||
|
@ -144,13 +143,13 @@ export class FeedbackDialog extends IGBDialog {
|
|||
const analytics = new AnalyticsService();
|
||||
const rate = await analytics.updateConversationSuggestion(
|
||||
min.instance.instanceId, user.conversation.conversationId, step.result, user.systemUser.locale);
|
||||
|
||||
|
||||
if (rate > 0.5) {
|
||||
await min.conversationalService.sendText(min, step, Messages[fixedLocale].glad_you_liked);
|
||||
} else {
|
||||
|
||||
const message = min.core.getParam<string>(min.instance, "Feedback Improve Message",
|
||||
Messages[fixedLocale].we_will_improve); // TODO: Improve to be multi-language.
|
||||
const message = min.core.getParam<string>(min.instance, 'Feedback Improve Message',
|
||||
Messages[fixedLocale].we_will_improve); // TODO: Improve to be multi-language.
|
||||
|
||||
await min.conversationalService.sendText(min, step, message);
|
||||
}
|
||||
|
|
|
@ -40,10 +40,10 @@ import { GBMinInstance, IGBDialog } from 'botlib';
|
|||
|
||||
import { BotAdapter } from 'botbuilder';
|
||||
import { WaterfallDialog } from 'botbuilder-dialogs';
|
||||
import { CSService } from '../services/CSService';
|
||||
import { Messages } from '../strings';
|
||||
import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService';
|
||||
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService';
|
||||
import { CSService } from '../services/CSService';
|
||||
import { Messages } from '../strings';
|
||||
|
||||
/**
|
||||
* Dialog for collecting quality of answer.
|
||||
|
@ -82,10 +82,10 @@ export class QualityDialog extends IGBDialog {
|
|||
);
|
||||
|
||||
// Updates values to perform Bot Analytics.
|
||||
|
||||
|
||||
const analytics = new AnalyticsService();
|
||||
analytics.updateConversationSuggestion(
|
||||
min.instance.instanceId, user.conversation,step.result, user.systemUser.locale);
|
||||
min.instance.instanceId, user.conversation, step.result, user.systemUser.locale);
|
||||
|
||||
// Goes to the ask loop.
|
||||
|
||||
|
|
|
@ -65,7 +65,6 @@ export class GBCustomerSatisfactionPackage implements IGBPackage {
|
|||
GBLog.verbose(`onExchangeData called.`);
|
||||
}
|
||||
|
||||
|
||||
public async loadPackage(core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||
core.sequelize.addModels([GuaribasQuestionAlternate]);
|
||||
}
|
||||
|
|
|
@ -30,9 +30,9 @@
|
|||
| |
|
||||
\*****************************************************************************/
|
||||
|
||||
import { GuaribasQuestion } from '../../../packages/kb.gbapp/models';
|
||||
import { GuaribasConversation } from '../../analytics.gblib/models';
|
||||
import { GuaribasQuestionAlternate } from '../models';
|
||||
import { GuaribasQuestion } from '../../../packages/kb.gbapp/models';
|
||||
|
||||
/**
|
||||
* Customer Satisfaction Service Layer.
|
||||
|
@ -43,7 +43,7 @@ export class CSService {
|
|||
instanceId: number,
|
||||
text: string): Promise<GuaribasQuestion> {
|
||||
|
||||
let questionAlternate = await GuaribasQuestionAlternate.findOne({
|
||||
const questionAlternate = await GuaribasQuestionAlternate.findOne({
|
||||
where: {
|
||||
instanceId: instanceId,
|
||||
questionTyped: text
|
||||
|
@ -61,6 +61,7 @@ export class CSService {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
return question;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ export const Messages = {
|
|||
please_no_bad_words: 'Please, no bad words.',
|
||||
please_wait_transfering: 'Please, wait while I find an agent to answer you.',
|
||||
notify_agent: (name) => `New call available for *${name}*, you can answer right here when you are finished, type /qt.`,
|
||||
notify_end_transfer: (botName) => `Now talking to ${botName} again.`,
|
||||
notify_end_transfer: (botName) => `Now talking to ${botName} again.`
|
||||
},
|
||||
'pt-BR': {
|
||||
about_suggestions: 'Sugestões melhoram muito minha qualidade...',
|
||||
|
|
|
@ -39,9 +39,9 @@
|
|||
import { BotAdapter } from 'botbuilder';
|
||||
import { WaterfallDialog } from 'botbuilder-dialogs';
|
||||
import { GBMinInstance, IGBDialog } from 'botlib';
|
||||
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService';
|
||||
import { Messages } from '../strings';
|
||||
import { KBService } from './../services/KBService';
|
||||
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService';
|
||||
|
||||
/**
|
||||
* Handle display of FAQ allowing direct access to KB.
|
||||
|
|
|
@ -41,10 +41,10 @@ import urlJoin = require('url-join');
|
|||
import { BotAdapter, CardFactory, MessageFactory } from 'botbuilder';
|
||||
import { WaterfallDialog } from 'botbuilder-dialogs';
|
||||
import { GBMinInstance, IGBDialog } from 'botlib';
|
||||
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService';
|
||||
import { GuaribasSubject } from '../models';
|
||||
import { KBService } from '../services/KBService';
|
||||
import { Messages } from '../strings';
|
||||
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService';
|
||||
|
||||
/**
|
||||
* Dialog arguments.
|
||||
|
@ -134,8 +134,8 @@ export class MenuDialog extends IGBDialog {
|
|||
if (attachments.length === 0) {
|
||||
|
||||
if (user.subjects && user.subjects.length > 0) {
|
||||
await min.conversationalService.sendText(min, step,
|
||||
Messages[locale].lets_search(KBService.getFormattedSubjectItems(user.subjects))
|
||||
await min.conversationalService.sendText(min, step,
|
||||
Messages[locale].lets_search(KBService.getFormattedSubjectItems(user.subjects))
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -64,7 +64,6 @@ export class GBKBPackage implements IGBPackage {
|
|||
GBLog.verbose(`onExchangeData called.`);
|
||||
}
|
||||
|
||||
|
||||
public async loadPackage(core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||
core.sequelize.addModels([GuaribasAnswer, GuaribasQuestion, GuaribasSubject]);
|
||||
}
|
||||
|
|
|
@ -43,28 +43,28 @@ const asyncPromise = require('async-promises');
|
|||
const walkPromise = require('walk-promise');
|
||||
// tslint:disable-next-line:newline-per-chained-call
|
||||
const { SearchService } = require('azure-search-client');
|
||||
var Excel = require('exceljs');
|
||||
import { GBServer } from '../../../src/app';
|
||||
const Excel = require('exceljs');
|
||||
import {
|
||||
IGBKBService,
|
||||
GBDialogStep,
|
||||
GBLog,
|
||||
GBMinInstance,
|
||||
IGBConversationalService,
|
||||
IGBCoreService,
|
||||
IGBInstance,
|
||||
GBMinInstance
|
||||
IGBKBService
|
||||
} from 'botlib';
|
||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||
import { Op } from 'sequelize';
|
||||
import { Sequelize } from 'sequelize-typescript';
|
||||
import { GBServer } from '../../../src/app';
|
||||
import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService';
|
||||
import { GuaribasPackage } from '../../core.gbapp/models/GBModel';
|
||||
import { GBDeployer } from '../../core.gbapp/services/GBDeployer';
|
||||
import { CSService } from '../../customer-satisfaction.gbapp/services/CSService';
|
||||
import { SecService } from '../../security.gbapp/services/SecService';
|
||||
import { GuaribasAnswer, GuaribasQuestion, GuaribasSubject } from '../models';
|
||||
import { Messages } from '../strings';
|
||||
import { GBConfigService } from './../../core.gbapp/services/GBConfigService';
|
||||
import { CSService } from '../../customer-satisfaction.gbapp/services/CSService';
|
||||
import { SecService } from '../../security.gbapp/services/SecService';
|
||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||
|
||||
/**
|
||||
* Result for quey on KB data.
|
||||
|
@ -116,7 +116,7 @@ export class KBService implements IGBKBService {
|
|||
}
|
||||
});
|
||||
|
||||
return answer != null ? answer.content : null;
|
||||
return answer != undefined ? answer.content : null;
|
||||
}
|
||||
|
||||
public async getQuestionById(instanceId: number, questionId: number): Promise<GuaribasQuestion> {
|
||||
|
@ -177,8 +177,6 @@ export class KBService implements IGBKBService {
|
|||
): Promise<KBServiceSearchResults> {
|
||||
// Builds search query.
|
||||
|
||||
|
||||
|
||||
query = query.toLowerCase();
|
||||
query = query.replace('?', ' ');
|
||||
query = query.replace('!', ' ');
|
||||
|
@ -222,6 +220,7 @@ export class KBService implements IGBKBService {
|
|||
`SEARCH WILL BE USED with score: ${returnedScore} > required (searchScore): ${searchScore}`
|
||||
);
|
||||
notSearched = false;
|
||||
|
||||
return { answer: value, questionId: values[0].questionId };
|
||||
} else {
|
||||
GBLog.info(
|
||||
|
@ -243,6 +242,7 @@ export class KBService implements IGBKBService {
|
|||
GBLog.info(
|
||||
`SEARCH called but NO answer could be found (zero results).`
|
||||
);
|
||||
|
||||
return { answer: undefined, questionId: 0 };
|
||||
}
|
||||
}
|
||||
|
@ -320,8 +320,8 @@ export class KBService implements IGBKBService {
|
|||
packageId: number
|
||||
): Promise<GuaribasQuestion[]> {
|
||||
GBLog.info(`Now reading file ${filePath}...`);
|
||||
var workbook = new Excel.Workbook();
|
||||
let data = await workbook.xlsx.readFile(filePath);
|
||||
const workbook = new Excel.Workbook();
|
||||
const data = await workbook.xlsx.readFile(filePath);
|
||||
|
||||
let lastQuestionId: number;
|
||||
let lastAnswer: GuaribasAnswer;
|
||||
|
@ -337,9 +337,9 @@ export class KBService implements IGBKBService {
|
|||
}
|
||||
}
|
||||
|
||||
let rows = worksheet._rows;
|
||||
let answers = [];
|
||||
let questions = [];
|
||||
const rows = worksheet._rows;
|
||||
const answers = [];
|
||||
const questions = [];
|
||||
|
||||
GBLog.info(`Processing ${rows.length} rows from tabular file ${filePath}...`);
|
||||
await asyncPromise.eachSeries(rows, async line => {
|
||||
|
@ -454,6 +454,7 @@ export class KBService implements IGBKBService {
|
|||
await CollectionUtil.asyncForEach(questions, async question => {
|
||||
question.answerId = answersCreated[i++].answerId;
|
||||
});
|
||||
|
||||
return await GuaribasQuestion.bulkCreate(questions);
|
||||
}
|
||||
|
||||
|
@ -470,6 +471,123 @@ export class KBService implements IGBKBService {
|
|||
}
|
||||
}
|
||||
|
||||
public async importKbPackage(
|
||||
localPath: string,
|
||||
packageStorage: GuaribasPackage,
|
||||
instance: IGBInstance
|
||||
): Promise<any> {
|
||||
// Imports subjects tree into database and return it.
|
||||
|
||||
const subjectFile = urlJoin(localPath, 'subjects.json');
|
||||
|
||||
if (Fs.existsSync(subjectFile)) {
|
||||
await this.importSubjectFile(packageStorage.packageId, subjectFile, instance);
|
||||
}
|
||||
|
||||
// Import tabular files in the tabular directory.
|
||||
|
||||
await this.importKbTabularDirectory(localPath, instance, packageStorage.packageId);
|
||||
|
||||
// Import remaining .md files in articles directory.
|
||||
|
||||
return await this.importRemainingArticles(localPath, instance, packageStorage.packageId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import all .md files in artcles folder that has not been referenced by tabular files.
|
||||
*/
|
||||
public async importRemainingArticles(localPath: string, instance: IGBInstance, packageId: number): Promise<any> {
|
||||
const files = await walkPromise(urlJoin(localPath, 'articles'));
|
||||
|
||||
await CollectionUtil.asyncForEach(files, async file => {
|
||||
if (file !== null && file.name.endsWith('.md')) {
|
||||
let content = await this.getAnswerTextByMediaName(instance.instanceId, file.name);
|
||||
|
||||
if (content === null) {
|
||||
const fullFilename = urlJoin(file.root, file.name);
|
||||
content = Fs.readFileSync(fullFilename, 'utf-8');
|
||||
|
||||
await GuaribasAnswer.create({
|
||||
instanceId: instance.instanceId,
|
||||
content: content,
|
||||
format: '.md',
|
||||
media: file.name,
|
||||
packageId: packageId,
|
||||
prevId: 0 // TODO: Calculate total rows and increment.
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
public async importKbTabularDirectory(localPath: string, instance: IGBInstance, packageId: number): Promise<any> {
|
||||
const files = await walkPromise(localPath);
|
||||
|
||||
await CollectionUtil.asyncForEach(files, async file => {
|
||||
if (file !== null && file.name.endsWith('.xlsx')) {
|
||||
return await this.importKbTabularFile(urlJoin(file.root, file.name), instance.instanceId, packageId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async importSubjectFile(packageId: number, filename: string, instance: IGBInstance): Promise<any> {
|
||||
const subjectsLoaded = JSON.parse(Fs.readFileSync(filename, 'utf8'));
|
||||
|
||||
const doIt = async (subjects: GuaribasSubject[], parentSubjectId: number) => {
|
||||
return asyncPromise.eachSeries(subjects, async item => {
|
||||
const value = await GuaribasSubject.create({
|
||||
internalId: item.id,
|
||||
parentSubjectId: parentSubjectId,
|
||||
instanceId: instance.instanceId,
|
||||
from: item.from,
|
||||
to: item.to,
|
||||
title: item.title,
|
||||
description: item.description,
|
||||
packageId: packageId
|
||||
});
|
||||
|
||||
if (item.children) {
|
||||
return doIt(item.children, value.subjectId);
|
||||
} else {
|
||||
return item;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return doIt(subjectsLoaded.children, undefined);
|
||||
}
|
||||
|
||||
public async undeployKbFromStorage(instance: IGBInstance, deployer: GBDeployer, packageId: number) {
|
||||
await GuaribasQuestion.destroy({
|
||||
where: { instanceId: instance.instanceId, packageId: packageId }
|
||||
});
|
||||
await GuaribasAnswer.destroy({
|
||||
where: { instanceId: instance.instanceId, packageId: packageId }
|
||||
});
|
||||
await GuaribasSubject.destroy({
|
||||
where: { instanceId: instance.instanceId, packageId: packageId }
|
||||
});
|
||||
await this.undeployPackageFromStorage(instance, packageId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deploys a knowledge base to the storage using the .gbkb format.
|
||||
*
|
||||
* @param localPath Path to the .gbkb folder.
|
||||
*/
|
||||
public async deployKb(core: IGBCoreService, deployer: GBDeployer, localPath: string, min: GBMinInstance) {
|
||||
const packageName = Path.basename(localPath);
|
||||
GBLog.info(`[GBDeployer] Opening package: ${localPath}`);
|
||||
|
||||
const instance = await core.loadInstanceByBotId(min.botId);
|
||||
GBLog.info(`[GBDeployer] Importing: ${localPath}`);
|
||||
const p = await deployer.deployPackageToStorage(instance.instanceId, packageName);
|
||||
await this.importKbPackage(localPath, p, instance);
|
||||
deployer.mountGBKBAssets(packageName, min.botId, localPath);
|
||||
|
||||
await deployer.rebuildIndex(instance, new AzureDeployerService(deployer).getKBSearchSchema(instance.searchIndex));
|
||||
GBLog.info(`[GBDeployer] Finished import of ${localPath}`);
|
||||
}
|
||||
|
||||
private async playAudio(
|
||||
min: GBMinInstance,
|
||||
answer: GuaribasAnswer,
|
||||
|
@ -571,126 +689,9 @@ export class KBService implements IGBKBService {
|
|||
}
|
||||
}
|
||||
|
||||
public async importKbPackage(
|
||||
localPath: string,
|
||||
packageStorage: GuaribasPackage,
|
||||
instance: IGBInstance
|
||||
): Promise<any> {
|
||||
// Imports subjects tree into database and return it.
|
||||
|
||||
const subjectFile = urlJoin(localPath, 'subjects.json');
|
||||
|
||||
if (Fs.existsSync(subjectFile)) {
|
||||
await this.importSubjectFile(packageStorage.packageId, subjectFile, instance);
|
||||
}
|
||||
|
||||
// Import tabular files in the tabular directory.
|
||||
|
||||
await this.importKbTabularDirectory(localPath, instance, packageStorage.packageId);
|
||||
|
||||
// Import remaining .md files in articles directory.
|
||||
|
||||
return await this.importRemainingArticles(localPath, instance, packageStorage.packageId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import all .md files in artcles folder that has not been referenced by tabular files.
|
||||
*/
|
||||
public async importRemainingArticles(localPath: string, instance: IGBInstance, packageId: number): Promise<any> {
|
||||
const files = await walkPromise(urlJoin(localPath, 'articles'));
|
||||
|
||||
await CollectionUtil.asyncForEach(files, async file => {
|
||||
if (file !== null && file.name.endsWith('.md')) {
|
||||
let content = await this.getAnswerTextByMediaName(instance.instanceId, file.name);
|
||||
|
||||
if (content === null) {
|
||||
const fullFilename = urlJoin(file.root, file.name);
|
||||
content = Fs.readFileSync(fullFilename, 'utf-8');
|
||||
|
||||
await GuaribasAnswer.create({
|
||||
instanceId: instance.instanceId,
|
||||
content: content,
|
||||
format: '.md',
|
||||
media: file.name,
|
||||
packageId: packageId,
|
||||
prevId: 0 // TODO: Calculate total rows and increment.
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
public async importKbTabularDirectory(localPath: string, instance: IGBInstance, packageId: number): Promise<any> {
|
||||
let files = await walkPromise(localPath);
|
||||
|
||||
await CollectionUtil.asyncForEach(files, async file => {
|
||||
if (file !== null && file.name.endsWith('.xlsx')) {
|
||||
return await this.importKbTabularFile(urlJoin(file.root, file.name), instance.instanceId, packageId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async importSubjectFile(packageId: number, filename: string, instance: IGBInstance): Promise<any> {
|
||||
const subjectsLoaded = JSON.parse(Fs.readFileSync(filename, 'utf8'));
|
||||
|
||||
const doIt = async (subjects: GuaribasSubject[], parentSubjectId: number) => {
|
||||
return asyncPromise.eachSeries(subjects, async item => {
|
||||
const value = await GuaribasSubject.create({
|
||||
internalId: item.id,
|
||||
parentSubjectId: parentSubjectId,
|
||||
instanceId: instance.instanceId,
|
||||
from: item.from,
|
||||
to: item.to,
|
||||
title: item.title,
|
||||
description: item.description,
|
||||
packageId: packageId
|
||||
});
|
||||
|
||||
if (item.children) {
|
||||
return doIt(item.children, value.subjectId);
|
||||
} else {
|
||||
return item;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return doIt(subjectsLoaded.children, undefined);
|
||||
}
|
||||
|
||||
public async undeployKbFromStorage(instance: IGBInstance, deployer: GBDeployer, packageId: number) {
|
||||
await GuaribasQuestion.destroy({
|
||||
where: { instanceId: instance.instanceId, packageId: packageId }
|
||||
});
|
||||
await GuaribasAnswer.destroy({
|
||||
where: { instanceId: instance.instanceId, packageId: packageId }
|
||||
});
|
||||
await GuaribasSubject.destroy({
|
||||
where: { instanceId: instance.instanceId, packageId: packageId }
|
||||
});
|
||||
await this.undeployPackageFromStorage(instance, packageId);
|
||||
}
|
||||
|
||||
private async undeployPackageFromStorage(instance: any, packageId: number) {
|
||||
await GuaribasPackage.destroy({
|
||||
where: { instanceId: instance.instanceId, packageId: packageId }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Deploys a knowledge base to the storage using the .gbkb format.
|
||||
*
|
||||
* @param localPath Path to the .gbkb folder.
|
||||
*/
|
||||
public async deployKb(core: IGBCoreService, deployer: GBDeployer, localPath: string, min: GBMinInstance) {
|
||||
const packageName = Path.basename(localPath);
|
||||
GBLog.info(`[GBDeployer] Opening package: ${localPath}`);
|
||||
|
||||
const instance = await core.loadInstanceByBotId(min.botId);
|
||||
GBLog.info(`[GBDeployer] Importing: ${localPath}`);
|
||||
const p = await deployer.deployPackageToStorage(instance.instanceId, packageName);
|
||||
await this.importKbPackage(localPath, p, instance);
|
||||
deployer.mountGBKBAssets(packageName, min.botId, localPath);
|
||||
|
||||
await deployer.rebuildIndex(instance, new AzureDeployerService(deployer).getKBSearchSchema(instance.searchIndex));
|
||||
GBLog.info(`[GBDeployer] Finished import of ${localPath}`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
'use strict';
|
||||
|
||||
import { TokenResponse } from 'botbuilder';
|
||||
import { IGBDialog, GBLog, GBMinInstance } from 'botlib';
|
||||
import { GBLog, GBMinInstance, IGBDialog } from 'botlib';
|
||||
import { Messages } from '../strings';
|
||||
|
||||
/**
|
||||
|
@ -50,6 +50,7 @@ export class OAuthDialog extends IGBDialog {
|
|||
waterfall: [
|
||||
async step => {
|
||||
step.activeDialog.state.options = step.options;
|
||||
|
||||
return await step.beginDialog('oAuthPrompt');
|
||||
},
|
||||
async step => {
|
||||
|
@ -60,6 +61,7 @@ export class OAuthDialog extends IGBDialog {
|
|||
return await step.endDialog(tokenResponse);
|
||||
} else {
|
||||
await step.context.sendActivity('Please sign in so I can show you your profile.');
|
||||
|
||||
return await step.replaceDialog('/auth');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,10 +40,10 @@ import urlJoin = require('url-join');
|
|||
|
||||
import { BotAdapter, CardFactory, MessageFactory } from 'botbuilder';
|
||||
import { WaterfallDialog } from 'botbuilder-dialogs';
|
||||
import { GBMinInstance, IGBDialog, GBLog } from 'botlib';
|
||||
import { Messages } from '../strings';
|
||||
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService';
|
||||
import { GBLog, GBMinInstance, IGBDialog } from 'botlib';
|
||||
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService';
|
||||
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService';
|
||||
import { Messages } from '../strings';
|
||||
const phoneUtil = require('google-libphonenumber').PhoneNumberUtil.getInstance();
|
||||
const phone = require('phone');
|
||||
|
||||
|
@ -52,47 +52,45 @@ const phone = require('phone');
|
|||
*/
|
||||
export class ProfileDialog extends IGBDialog {
|
||||
|
||||
static getNameDialog(min: GBMinInstance) {
|
||||
public static getNameDialog(min: GBMinInstance) {
|
||||
|
||||
return {
|
||||
id: '/profile_name', waterfall: [
|
||||
async step => {
|
||||
step.activeDialog.state.options = step.options;
|
||||
const locale = step.context.activity.locale;
|
||||
await step.prompt("textPrompt", Messages[locale].whats_name);
|
||||
await step.prompt('textPrompt', Messages[locale].whats_name);
|
||||
},
|
||||
async step => {
|
||||
const locale = step.context.activity.locale;
|
||||
|
||||
const fullName = (text) => {
|
||||
return text.match(/^[a-zA-Z]+(([',. -][a-zA-Z ])?[a-zA-Z]*)*$/gi);
|
||||
}
|
||||
};
|
||||
|
||||
const value = fullName(step.result);
|
||||
|
||||
if (value === null) {
|
||||
await step.context.sendActivity(Messages[locale].validation_enter_name);
|
||||
await step.replaceDialog('/profile_name', step.activeDialog.state.options);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
step.activeDialog.state.options.name = value[0];
|
||||
|
||||
return await step.replaceDialog('/profile_mobile', step.activeDialog.state.options);
|
||||
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
static getMobileDialog(min: GBMinInstance) {
|
||||
public static getMobileDialog(min: GBMinInstance) {
|
||||
|
||||
return {
|
||||
id: '/profile_mobile', waterfall: [
|
||||
async step => {
|
||||
step.activeDialog.state.options = step.options;
|
||||
const locale = step.context.activity.locale;
|
||||
await step.prompt("textPrompt", Messages[locale].whats_mobile);
|
||||
await step.prompt('textPrompt', Messages[locale].whats_mobile);
|
||||
},
|
||||
async step => {
|
||||
const locale = step.context.activity.locale;
|
||||
|
@ -109,25 +107,24 @@ export class ProfileDialog extends IGBDialog {
|
|||
await step.context.sendActivity(Messages[locale].validation_enter_valid_mobile);
|
||||
|
||||
return await step.replaceDialog('/profile_mobile', step.activeDialog.state.options);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
step.activeDialog.state.options.mobile = `${phoneNumber.values_['1']}${phoneNumber.values_['2']}`;
|
||||
step.activeDialog.state.options.mobileCode = GBAdminService.getMobileCode();
|
||||
|
||||
return await step.replaceDialog('/profile_mobile_confirm', step.activeDialog.state.options);
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static getMobileConfirmDialog(min: GBMinInstance) {
|
||||
public static getMobileConfirmDialog(min: GBMinInstance) {
|
||||
|
||||
return {
|
||||
id: '/profile_mobile_confirm', waterfall: [
|
||||
async step => {
|
||||
step.activeDialog.state.options = step.options;
|
||||
const locale = step.context.activity.locale;
|
||||
let from = step.activeDialog.state.options.mobile;
|
||||
const from = step.activeDialog.state.options.mobile;
|
||||
if (min.whatsAppDirectLine) {
|
||||
|
||||
await min.whatsAppDirectLine.sendToDevice(from, `${step.activeDialog.state.options.mobileCode} is your General Bots creation code.`);
|
||||
|
@ -135,7 +132,7 @@ export class ProfileDialog extends IGBDialog {
|
|||
GBLog.info(`WhatsApp not configured. Here is the code: ${step.activeDialog.state.options.mobileCode}.`);
|
||||
}
|
||||
|
||||
await step.prompt("textPrompt", Messages[locale].confirm_mobile);
|
||||
await step.prompt('textPrompt', Messages[locale].confirm_mobile);
|
||||
},
|
||||
async step => {
|
||||
const locale = step.context.activity.locale;
|
||||
|
@ -144,40 +141,37 @@ export class ProfileDialog extends IGBDialog {
|
|||
await step.context.sendActivity(Messages[locale].confirm_mobile_again);
|
||||
|
||||
return await step.replaceDialog('/profile_mobile_confirm', step.activeDialog.state.options);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
await step.replaceDialog('/profile_email', step.activeDialog.state.options);
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
static getEmailDialog(min: GBMinInstance) {
|
||||
public static getEmailDialog(min: GBMinInstance) {
|
||||
return {
|
||||
id: '/profile_email', waterfall: [
|
||||
async step => {
|
||||
const locale = step.context.activity.locale;
|
||||
await step.prompt("textPrompt", Messages[locale].whats_email);
|
||||
await step.prompt('textPrompt', Messages[locale].whats_email);
|
||||
},
|
||||
async step => {
|
||||
const locale = step.context.activity.locale;
|
||||
|
||||
const extractEntity = (text) => {
|
||||
return text.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/gi);
|
||||
}
|
||||
};
|
||||
|
||||
const value = extractEntity(step.result);
|
||||
|
||||
if (value === null) {
|
||||
await step.context.sendActivity(Messages[locale].validation_enter_valid_email);
|
||||
await step.replaceDialog('/profile_email', step.activeDialog.state.options);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
step.activeDialog.state.options.email = value[0];
|
||||
await step.replaceDialog(`/${step.activeDialog.state.options.nextDialog}`, step.activeDialog.state.options);
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,10 +39,10 @@
|
|||
import urlJoin = require('url-join');
|
||||
|
||||
import { GBDialogStep, GBLog, GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
|
||||
import {ProfileDialog} from './dialogs/ProfileDialog'
|
||||
import { Sequelize } from 'sequelize-typescript';
|
||||
import { GuaribasGroup, GuaribasUser, GuaribasUserGroup } from './models';
|
||||
import { OAuthDialog } from './dialogs/OAuthDialog';
|
||||
import {ProfileDialog} from './dialogs/ProfileDialog';
|
||||
import { GuaribasGroup, GuaribasUser, GuaribasUserGroup } from './models';
|
||||
|
||||
/**
|
||||
* Package for the security module.
|
||||
|
@ -55,9 +55,9 @@ export class GBSecurityPackage implements IGBPackage {
|
|||
ProfileDialog.getEmailDialog(min),
|
||||
ProfileDialog.getMobileDialog(min),
|
||||
ProfileDialog.getMobileConfirmDialog(min),
|
||||
OAuthDialog.getOAuthDialog(min),
|
||||
OAuthDialog.getOAuthDialog(min)
|
||||
];
|
||||
|
||||
|
||||
}
|
||||
public async unloadPackage(core: IGBCoreService): Promise<void> {
|
||||
GBLog.verbose(`unloadPackage called.`);
|
||||
|
@ -74,7 +74,7 @@ export class GBSecurityPackage implements IGBPackage {
|
|||
public async onExchangeData(min: GBMinInstance, kind: string, data: any) {
|
||||
GBLog.verbose(`onExchangeData called.`);
|
||||
}
|
||||
|
||||
|
||||
public async loadPackage(core: IGBCoreService, sequelize: Sequelize): Promise<void> {
|
||||
core.sequelize.addModels([GuaribasGroup, GuaribasUser, GuaribasUserGroup]);
|
||||
}
|
||||
|
|
|
@ -79,21 +79,21 @@ export class GuaribasUser extends Model<GuaribasUser> {
|
|||
public instance: GuaribasInstance;
|
||||
|
||||
@Column(DataType.STRING(16))
|
||||
agentSystemId: string
|
||||
|
||||
public agentSystemId: string;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
@Column
|
||||
agentContacted: Date;
|
||||
public agentContacted: Date;
|
||||
|
||||
@Column(DataType.STRING(16))
|
||||
agentMode: string;
|
||||
public agentMode: string;
|
||||
|
||||
@Column(DataType.TEXT)
|
||||
@Column
|
||||
conversationReference: string
|
||||
public conversationReference: string;
|
||||
|
||||
@Column(DataType.STRING(64))
|
||||
hearOnDialog: string;
|
||||
public hearOnDialog: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
const Fs = require('fs');
|
||||
import urlJoin = require('url-join');
|
||||
|
||||
import { GBService, IGBInstance } from 'botlib';
|
||||
import { GuaribasGroup, GuaribasUser, GuaribasUserGroup } from '../models';
|
||||
import { ConversationReference } from 'botbuilder';
|
||||
import { GBService, IGBInstance } from 'botlib';
|
||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||
import { GuaribasGroup, GuaribasUser, GuaribasUserGroup } from '../models';
|
||||
|
||||
/**
|
||||
* Security service layer.
|
||||
|
@ -57,6 +57,7 @@ export class SecService extends GBService {
|
|||
user.displayName = displayName;
|
||||
user.email = userName;
|
||||
user.defaultChannel = channelName;
|
||||
|
||||
return await user.save();
|
||||
}
|
||||
|
||||
|
@ -82,27 +83,29 @@ export class SecService extends GBService {
|
|||
}
|
||||
|
||||
public async updateUserLocale(userId: number, locale: any): Promise<GuaribasUser> {
|
||||
let user = await GuaribasUser.findOne({
|
||||
const user = await GuaribasUser.findOne({
|
||||
where: {
|
||||
userId: userId
|
||||
}
|
||||
});
|
||||
user.locale = locale;
|
||||
|
||||
return await user.save();
|
||||
}
|
||||
|
||||
public async updateUserHearOnDialog(userId: number, dialogName: string): Promise<GuaribasUser> {
|
||||
let user = await GuaribasUser.findOne({
|
||||
const user = await GuaribasUser.findOne({
|
||||
where: {
|
||||
userId: userId
|
||||
}
|
||||
});
|
||||
user.hearOnDialog = dialogName;
|
||||
|
||||
return await user.save();
|
||||
}
|
||||
|
||||
public async updateUserInstance(userSystemId: string, instanceId: number): Promise<GuaribasUser> {
|
||||
let user = await GuaribasUser.findOne({
|
||||
const user = await GuaribasUser.findOne({
|
||||
where: {
|
||||
userSystemId: userSystemId
|
||||
}
|
||||
|
@ -154,18 +157,19 @@ export class SecService extends GBService {
|
|||
}
|
||||
|
||||
await user.save();
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
public async isAgentSystemId(systemId: string): Promise<Boolean> {
|
||||
let user = await GuaribasUser.findOne({
|
||||
const user = await GuaribasUser.findOne({
|
||||
where: {
|
||||
userSystemId: systemId
|
||||
}
|
||||
});
|
||||
|
||||
if (user === null) {
|
||||
throw `TRANSFER_TO phones must talk first to the bot before becoming an agent.`;
|
||||
throw new Error(`TRANSFER_TO phones must talk first to the bot before becoming an agent.`);
|
||||
}
|
||||
|
||||
return user.agentMode === 'self';
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
export const Messages = {
|
||||
'en-US': {
|
||||
whats_name: "What's your name?",
|
||||
whats_mobile: "What's your mobile number including country code (e.g. +1 222 9998888)?",
|
||||
confirm_mobile: "Please type the code just sent to your mobile.",
|
||||
whats_email: "What's your E-mail address?",
|
||||
validation_enter_name: "Please enter your full name.",
|
||||
validation_enter_valid_mobile: "Please enter a valid mobile number.",
|
||||
validation_enter_valid_email: "Please enter a valid e-mail.",
|
||||
whats_name: 'What\'s your name?',
|
||||
whats_mobile: 'What\'s your mobile number including country code (e.g. +1 222 9998888)?',
|
||||
confirm_mobile: 'Please type the code just sent to your mobile.',
|
||||
whats_email: 'What\'s your E-mail address?',
|
||||
validation_enter_name: 'Please enter your full name.',
|
||||
validation_enter_valid_mobile: 'Please enter a valid mobile number.',
|
||||
validation_enter_valid_email: 'Please enter a valid e-mail.'
|
||||
},
|
||||
'pt-BR': {
|
||||
whats_name: "Qual o seu nome?",
|
||||
whats_email: "Qual o seu e-mail?",
|
||||
whats_mobile: "Qual o seu celular?",
|
||||
confirm_mobile: "Por favor, digite o código enviado para seu celular.",
|
||||
confirm_mobile_again: "Esse não me parece ser um código numérico válido. Por favor, digite novamente o código enviado para seu celular.",
|
||||
validation_enter_valid_email: "Por favor, digite um e-mail válido no formato nome@domínio.com.br.",
|
||||
validation_enter_name: "Por favor, digite seu nome completo",
|
||||
validation_enter_valid_mobile: "Por favor, insira um número de celular válido (ex.: +55 21 98888-7766).",
|
||||
whats_name: 'Qual o seu nome?',
|
||||
whats_email: 'Qual o seu e-mail?',
|
||||
whats_mobile: 'Qual o seu celular?',
|
||||
confirm_mobile: 'Por favor, digite o código enviado para seu celular.',
|
||||
confirm_mobile_again: 'Esse não me parece ser um código numérico válido. Por favor, digite novamente o código enviado para seu celular.',
|
||||
validation_enter_valid_email: 'Por favor, digite um e-mail válido no formato nome@domínio.com.br.',
|
||||
validation_enter_name: 'Por favor, digite seu nome completo',
|
||||
validation_enter_valid_mobile: 'Por favor, insira um número de celular válido (ex.: +55 21 98888-7766).'
|
||||
}
|
||||
};
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const { sppull } = require("sppull");
|
||||
const { sppull } = require('sppull');
|
||||
|
||||
/**
|
||||
* Service facade for SharePoint Online.
|
||||
|
@ -61,5 +61,4 @@ export class GBSharePointService {
|
|||
return await sppull(context, options);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -35,18 +35,20 @@ import urlJoin = require('url-join');
|
|||
const Swagger = require('swagger-client');
|
||||
const rp = require('request-promise');
|
||||
const fs = require('fs');
|
||||
import { GBLog, GBService, GBMinInstance, IGBPackage } from 'botlib';
|
||||
import { GBLog, GBMinInstance, GBService, IGBPackage } from 'botlib';
|
||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||
import * as request from 'request-promise-native';
|
||||
import { GBServer } from '../../../src/app';
|
||||
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService';
|
||||
import { SecService } from '../../security.gbapp/services/SecService';
|
||||
import { Messages } from '../strings';
|
||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||
|
||||
/**
|
||||
* Support for Whatsapp.
|
||||
*/
|
||||
export class WhatsappDirectLine extends GBService {
|
||||
|
||||
public static conversationIds = {};
|
||||
public pollInterval = 5000;
|
||||
public directLineClientName = 'DirectLineClient';
|
||||
|
||||
|
@ -55,12 +57,10 @@ export class WhatsappDirectLine extends GBService {
|
|||
public whatsappServiceNumber: string;
|
||||
public whatsappServiceUrl: string;
|
||||
public botId: string;
|
||||
public min: GBMinInstance;
|
||||
private directLineSecret: string;
|
||||
private locale: string = 'pt-BR';
|
||||
|
||||
static conversationIds = {};
|
||||
min: GBMinInstance;
|
||||
|
||||
constructor(
|
||||
min: GBMinInstance,
|
||||
botId,
|
||||
|
@ -80,13 +80,19 @@ export class WhatsappDirectLine extends GBService {
|
|||
|
||||
}
|
||||
|
||||
public static async asyncForEach(array, callback) {
|
||||
for (let index = 0; index < array.length; index++) {
|
||||
await callback(array[index], index, array);
|
||||
}
|
||||
}
|
||||
|
||||
public async setup(setUrl) {
|
||||
this.directLineClient =
|
||||
new Swagger({
|
||||
spec: JSON.parse(fs.readFileSync('directline-3.0.json', 'utf8')),
|
||||
usePromise: true
|
||||
});
|
||||
let client = await this.directLineClient;
|
||||
const client = await this.directLineClient;
|
||||
|
||||
client.clientAuthorizations.add(
|
||||
'AuthorizationBotConnector',
|
||||
|
@ -111,9 +117,9 @@ export class WhatsappDirectLine extends GBService {
|
|||
const express = require('express');
|
||||
GBServer.globals.server.use(`/audios`, express.static('work'));
|
||||
|
||||
if (process.env.ENDPOINT_UPDATE === "true") {
|
||||
if (process.env.ENDPOINT_UPDATE === 'true') {
|
||||
try {
|
||||
let res = await request.post(options);
|
||||
const res = await request.post(options);
|
||||
GBLog.info(res);
|
||||
} catch (error) {
|
||||
GBLog.error(`Error initializing 3rd party Whatsapp provider(1) ${error.message}`);
|
||||
|
@ -123,12 +129,6 @@ export class WhatsappDirectLine extends GBService {
|
|||
|
||||
}
|
||||
|
||||
public static async asyncForEach(array, callback) {
|
||||
for (let index = 0; index < array.length; index++) {
|
||||
await callback(array[index], index, array);
|
||||
}
|
||||
}
|
||||
|
||||
public async resetConversationId(number) {
|
||||
WhatsappDirectLine.conversationIds[number] = undefined;
|
||||
}
|
||||
|
@ -139,19 +139,21 @@ export class WhatsappDirectLine extends GBService {
|
|||
|
||||
const options = {
|
||||
url: urlJoin(this.whatsappServiceUrl, 'status') + `?token=${this.min.instance.whatsappServiceKey}`,
|
||||
method: 'GET',
|
||||
method: 'GET'
|
||||
|
||||
};
|
||||
|
||||
const res = await request(options);
|
||||
const json = JSON.parse(res);
|
||||
return json.accountStatus === "authenticated";
|
||||
|
||||
return json.accountStatus === 'authenticated';
|
||||
|
||||
}
|
||||
|
||||
public async received(req, res) {
|
||||
if (req.body.messages === undefined) {
|
||||
res.end();
|
||||
|
||||
return; // Exit here.
|
||||
}
|
||||
|
||||
|
@ -162,25 +164,26 @@ export class WhatsappDirectLine extends GBService {
|
|||
|
||||
if (req.body.messages[0].fromMe) {
|
||||
res.end();
|
||||
|
||||
return; // Exit here.
|
||||
}
|
||||
GBLog.info(`GBWhatsapp: RCV ${from}(${fromName}): ${text})`);
|
||||
|
||||
await CollectionUtil.asyncForEach(this.min.appPackages, async (e: IGBPackage) => {
|
||||
await e.onExchangeData(this.min, "whatsappMessage", message);
|
||||
await e.onExchangeData(this.min, 'whatsappMessage', message);
|
||||
});
|
||||
|
||||
const id = req.body.messages[0].chatId.split('@')[0];
|
||||
const senderName = req.body.messages[0].senderName;
|
||||
let sec = new SecService();
|
||||
const sec = new SecService();
|
||||
|
||||
const user = await sec.ensureUser(this.min.instance.instanceId, id,
|
||||
senderName, "", "whatsapp", senderName);
|
||||
senderName, '', 'whatsapp', senderName);
|
||||
|
||||
const locale = user.locale ? user.locale : 'pt';
|
||||
if (message.type === "ptt") {
|
||||
if (message.type === 'ptt') {
|
||||
|
||||
if (process.env.AUDIO_DISABLED !== "true") {
|
||||
if (process.env.AUDIO_DISABLED !== 'true') {
|
||||
const options = {
|
||||
url: message.body,
|
||||
method: 'GET',
|
||||
|
@ -188,71 +191,67 @@ export class WhatsappDirectLine extends GBService {
|
|||
};
|
||||
|
||||
const res = await request(options);
|
||||
let buf = Buffer.from(res, 'binary');
|
||||
const buf = Buffer.from(res, 'binary');
|
||||
text = await GBConversationalService.getTextFromAudioBuffer(
|
||||
this.min.instance.speechKey,
|
||||
this.min.instance.cloudLocation,
|
||||
buf, locale
|
||||
);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
await this.sendToDevice(user.userSystemId, `No momento estou apenas conseguindo ler mensagens de texto.`);
|
||||
}
|
||||
}
|
||||
|
||||
const conversationId = WhatsappDirectLine.conversationIds[from];
|
||||
|
||||
let client = await this.directLineClient;
|
||||
if (user.agentMode === "self") {
|
||||
let manualUser = await sec.getUserFromAgentSystemId(id);
|
||||
const client = await this.directLineClient;
|
||||
if (user.agentMode === 'self') {
|
||||
const manualUser = await sec.getUserFromAgentSystemId(id);
|
||||
|
||||
if (manualUser === null) {
|
||||
await sec.updateCurrentAgent(id, this.min.instance.instanceId, null);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
const cmd = '/reply ';
|
||||
if (text.startsWith(cmd)) {
|
||||
let filename = text.substr(cmd.length);
|
||||
let message = await this.min.kbService.getAnswerTextByMediaName(this.min.instance.instanceId, filename);
|
||||
const filename = text.substr(cmd.length);
|
||||
const message = await this.min.kbService.getAnswerTextByMediaName(this.min.instance.instanceId, filename);
|
||||
|
||||
if (message === null) {
|
||||
await this.sendToDeviceEx(user.userSystemId, `File ${filename} not found in any .gbkb published. Check the name or publish again the associated .gbkb.`,
|
||||
locale);
|
||||
locale);
|
||||
} else {
|
||||
await this.min.conversationalService.sendMarkdownToMobile(this.min, null, user.userSystemId, message);
|
||||
}
|
||||
} else if (text === '/qt') {
|
||||
// TODO: Transfers only in pt-br for now.
|
||||
await this.sendToDeviceEx(manualUser.userSystemId, Messages[this.locale].notify_end_transfer(this.min.instance.botId), locale);
|
||||
await this.sendToDeviceEx(user.agentSystemId, Messages[this.locale].notify_end_transfer(this.min.instance.botId), locale);
|
||||
await this.sendToDeviceEx(manualUser.userSystemId,
|
||||
Messages[this.locale].notify_end_transfer(this.min.instance.botId), locale);
|
||||
await this.sendToDeviceEx(user.agentSystemId,
|
||||
Messages[this.locale].notify_end_transfer(this.min.instance.botId), locale);
|
||||
|
||||
await sec.updateCurrentAgent(manualUser.userSystemId, this.min.instance.instanceId, null);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
GBLog.info(`HUMAN AGENT (${id}) TO USER ${manualUser.userSystemId}: ${text}`);
|
||||
this.sendToDeviceEx(manualUser.userSystemId, `${manualUser.agentSystemId}: ${text}`, locale);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (user.agentMode === "human") {
|
||||
let agent = await sec.getUserFromSystemId(user.agentSystemId);
|
||||
} else if (user.agentMode === 'human') {
|
||||
const agent = await sec.getUserFromSystemId(user.agentSystemId);
|
||||
if (text === '/t') {
|
||||
await this.sendToDeviceEx(user.userSystemId, `Você já está sendo atendido por ${agent.userSystemId}.`, locale);
|
||||
}
|
||||
else if (text === '/qt' || text === "Sair" || text === "Fechar") {
|
||||
} else if (text === '/qt' || text === 'Sair' || text === 'Fechar') {
|
||||
// TODO: Transfers only in pt-br for now.
|
||||
await this.sendToDeviceEx(id, Messages[this.locale].notify_end_transfer(this.min.instance.botId), locale);
|
||||
await this.sendToDeviceEx(id,
|
||||
Messages[this.locale].notify_end_transfer(this.min.instance.botId), locale);
|
||||
await this.sendToDeviceEx(user.agentSystemId, Messages[this.locale].notify_end_transfer(this.min.instance.botId), locale);
|
||||
|
||||
await sec.updateCurrentAgent(id, this.min.instance.instanceId, null);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
GBLog.info(`USER (${id}) TO AGENT ${user.userSystemId}: ${text}`);
|
||||
this.sendToDeviceEx(user.agentSystemId, `Bot: ${this.min.instance.botId}\n${id}: ${text}`, locale);
|
||||
}
|
||||
|
||||
}
|
||||
else if (user.agentMode === "bot" || user.agentMode === null || user.agentMode === undefined) {
|
||||
} else if (user.agentMode === 'bot' || user.agentMode === null || user.agentMode === undefined) {
|
||||
|
||||
if (WhatsappDirectLine.conversationIds[from] === undefined) {
|
||||
GBLog.info(`GBWhatsapp: Starting new conversation on Bot.`);
|
||||
|
@ -267,8 +266,7 @@ export class WhatsappDirectLine extends GBService {
|
|||
|
||||
this.inputMessage(client, conversationId, text, from, fromName);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
GBLog.warn(`Inconsistencty found: Invalid agentMode on User Table: ${user.agentMode}`);
|
||||
}
|
||||
|
||||
|
@ -410,7 +408,7 @@ export class WhatsappDirectLine extends GBService {
|
|||
|
||||
public async sendTextAsAudioToDevice(to, msg) {
|
||||
|
||||
let url = await GBConversationalService.getAudioBufferFromText(
|
||||
const url = await GBConversationalService.getAudioBufferFromText(
|
||||
this.min.instance.speechKey,
|
||||
this.min.instance.cloudLocation,
|
||||
msg, this.locale
|
||||
|
@ -419,18 +417,6 @@ export class WhatsappDirectLine extends GBService {
|
|||
await this.sendFileToDevice(to, url, 'Audio', msg);
|
||||
}
|
||||
|
||||
private async sendToDeviceEx(to, text, locale) {
|
||||
const minBoot = GBServer.globals.minBoot as any;
|
||||
|
||||
text = await minBoot.conversationalService.translate(
|
||||
minBoot,
|
||||
text,
|
||||
locale
|
||||
);
|
||||
await this.sendToDevice(to, text);
|
||||
|
||||
}
|
||||
|
||||
public async sendToDevice(to: string, msg: string) {
|
||||
|
||||
const cmd = '/audio ';
|
||||
|
@ -464,4 +450,16 @@ export class WhatsappDirectLine extends GBService {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async sendToDeviceEx(to, text, locale) {
|
||||
const minBoot = GBServer.globals.minBoot as any;
|
||||
|
||||
text = await minBoot.conversationalService.translate(
|
||||
minBoot,
|
||||
text,
|
||||
locale
|
||||
);
|
||||
await this.sendToDevice(to, text);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
10
src/app.ts
10
src/app.ts
|
@ -39,8 +39,8 @@
|
|||
const express = require('express');
|
||||
const bodyParser = require('body-parser');
|
||||
import * as fs from 'fs';
|
||||
let mkdirp = require('mkdirp');
|
||||
let Path = require('path');
|
||||
const mkdirp = require('mkdirp');
|
||||
const Path = require('path');
|
||||
|
||||
import { GBLog, GBMinInstance, IGBCoreService, IGBInstance, IGBPackage } from 'botlib';
|
||||
import { GBAdminService } from '../packages/admin.gbapp/services/GBAdminService';
|
||||
|
@ -137,7 +137,7 @@ export class GBServer {
|
|||
await core.initStorage();
|
||||
} catch (error) {
|
||||
GBLog.verbose(`Error initializing storage: ${error}`);
|
||||
GBServer.globals.bootInstance =
|
||||
GBServer.globals.bootInstance =
|
||||
await core.createBootInstance(core, azureDeployer, GBServer.globals.publicAddress);
|
||||
await core.initStorage();
|
||||
}
|
||||
|
@ -150,9 +150,9 @@ export class GBServer {
|
|||
GBServer.globals.sysPackages = await core.loadSysPackages(core);
|
||||
await core.checkStorage(azureDeployer);
|
||||
await deployer.deployPackages(core, server, GBServer.globals.appPackages);
|
||||
|
||||
|
||||
GBLog.info(`Publishing instances...`);
|
||||
let instances: IGBInstance[] = await core.loadAllInstances(
|
||||
const instances: IGBInstance[] = await core.loadAllInstances(
|
||||
core,
|
||||
azureDeployer,
|
||||
GBServer.globals.publicAddress
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"allowJs": false,
|
||||
"allowJs": true,
|
||||
"downlevelIteration": true,
|
||||
"baseUrl": "./",
|
||||
"declaration": false,
|
||||
|
|
27
tslint.json
27
tslint.json
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"defaultSeverity": "warning",
|
||||
"extends": ["tslint:recommended", "tslint-microsoft-contrib"],
|
||||
"extends": [
|
||||
"tslint:recommended",
|
||||
"tslint-microsoft-contrib"
|
||||
],
|
||||
"linterOptions": {
|
||||
"exclude": [
|
||||
"libraries/botframework-connector/src/generated/**/*",
|
||||
|
@ -9,7 +12,9 @@
|
|||
"./packages/**/*.gbdialog"
|
||||
]
|
||||
},
|
||||
"rulesDirectory": ["node_modules/tslint-microsoft-contrib"],
|
||||
"rulesDirectory": [
|
||||
"node_modules/tslint-microsoft-contrib"
|
||||
],
|
||||
"jsRules": {},
|
||||
"rules": {
|
||||
"newline-per-chained-call": false,
|
||||
|
@ -19,10 +24,20 @@
|
|||
"typedef": false,
|
||||
"variable-name": false,
|
||||
"no-parameter-properties": false,
|
||||
"max-line-length": [true, { "limit": 120, "ignore-pattern": "^\\s+\\*" }],
|
||||
"await-promise": [true, "Bluebird"],
|
||||
"max-line-length": [
|
||||
true,
|
||||
{
|
||||
"limit": 120,
|
||||
"ignore-pattern": "^\\s+\\*"
|
||||
}
|
||||
],
|
||||
"await-promise": [
|
||||
true,
|
||||
"Bluebird"
|
||||
],
|
||||
"no-reserved-keywords": false,
|
||||
"no-unnecessary-class": false,
|
||||
"no-string-literal": false,
|
||||
"no-require-imports": false,
|
||||
"function-name": false,
|
||||
"no-relative-imports": false,
|
||||
|
@ -38,6 +53,6 @@
|
|||
"switch-final-break": false,
|
||||
"no-parameter-reassignment": false,
|
||||
"export-name": false,
|
||||
"no-backbone-get-set-outside-model": false
|
||||
"no-backbone-get-set-outside-model": false
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue