Compare commits
231 commits
rodrigorod
...
main
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b5bf44fd70 | ||
![]() |
864107fca0 | ||
![]() |
2695b54460 | ||
![]() |
27dde0f4f0 | ||
![]() |
e6ec0d2e9e | ||
300b5dc258 | |||
![]() |
9201d7a262 | ||
![]() |
fb24bbd98e | ||
![]() |
58ebbe880c | ||
![]() |
d21b1747d6 | ||
![]() |
26eb714e2c | ||
![]() |
5c3b24dadd | ||
![]() |
a33ed106f7 | ||
![]() |
afe9e6c7ab | ||
![]() |
3afdbb1ddb | ||
![]() |
f245de43b2 | ||
![]() |
619a0e11b9 | ||
![]() |
f71c803f2c | ||
![]() |
3d5c30a3b0 | ||
![]() |
9d95e4f8c1 | ||
![]() |
cbdf3664bb | ||
![]() |
0d5a4aee3c | ||
![]() |
1d20dd83b0 | ||
![]() |
2e42c36ecb | ||
![]() |
2da1e99c0d | ||
![]() |
30fa9ec5db | ||
![]() |
e68eccffd4 | ||
![]() |
910d78765a | ||
![]() |
e17ad407ff | ||
![]() |
75b0e0a9c8 | ||
![]() |
0b748d68fb | ||
![]() |
215bd1b699 | ||
![]() |
aa606c0d90 | ||
![]() |
b0517c9c94 | ||
![]() |
51831d2f24 | ||
![]() |
25e688aed9 | ||
![]() |
f232bdbaac | ||
![]() |
43242cb433 | ||
![]() |
2b2ab3a42e | ||
![]() |
e2382ccddc | ||
![]() |
53710da2a7 | ||
![]() |
4e6e34e978 | ||
![]() |
3abbec63a7 | ||
![]() |
b6ba7d5a3d | ||
![]() |
2f605f101c | ||
![]() |
2ee0f0f7ec | ||
![]() |
8d83dc214a | ||
![]() |
4c28404578 | ||
![]() |
0f0f8d610e | ||
![]() |
5e492d590e | ||
![]() |
24d2b10afb | ||
![]() |
bb05685767 | ||
![]() |
83107fbf91 | ||
![]() |
1ca61954a4 | ||
![]() |
c5f522d7d7 | ||
![]() |
f078881b0d | ||
![]() |
1ef6cbb032 | ||
![]() |
e3992b34af | ||
![]() |
525703052d | ||
![]() |
f34a4f25d0 | ||
![]() |
7ababd7a80 | ||
![]() |
320e401cad | ||
![]() |
2a61c07cd1 | ||
![]() |
b5034f9167 | ||
![]() |
c200456e38 | ||
![]() |
3ce1d1e152 | ||
![]() |
b7f9c07faf | ||
![]() |
7f7397b192 | ||
![]() |
4db5e10b15 | ||
![]() |
32183519d2 | ||
![]() |
a6e3722a2a | ||
![]() |
1b65edc213 | ||
![]() |
6f6dfca9c2 | ||
![]() |
7175ab550b | ||
![]() |
30460100d9 | ||
![]() |
c6ddaa8ec9 | ||
![]() |
4d850362d2 | ||
![]() |
0cb49684e6 | ||
![]() |
feb7939387 | ||
![]() |
ec8b0d44df | ||
![]() |
e3ac4f58b3 | ||
![]() |
9e08cb5e64 | ||
![]() |
d4ad69c4b0 | ||
![]() |
b5369ad15c | ||
![]() |
4f8067108f | ||
![]() |
a003f5297c | ||
![]() |
638534e31f | ||
![]() |
7c05a95054 | ||
![]() |
47e3c7648b | ||
![]() |
d55a16aa80 | ||
![]() |
2feee016ca | ||
![]() |
9fe9444c69 | ||
![]() |
84f2b7bd9b | ||
![]() |
449774c2d2 | ||
![]() |
827b4451a8 | ||
![]() |
46176fe2f3 | ||
![]() |
c599932c10 | ||
![]() |
b6be0b5418 | ||
![]() |
bc5e18c4f0 | ||
![]() |
380f2ce83a | ||
![]() |
8e58038295 | ||
![]() |
79ca7e1da0 | ||
![]() |
0364526fc6 | ||
![]() |
ce78abdceb | ||
![]() |
bc0aa7627e | ||
![]() |
ea224b4937 | ||
![]() |
31b7d5d59e | ||
![]() |
87802e4249 | ||
![]() |
eb9ddb7ead | ||
![]() |
d2851aabd6 | ||
![]() |
7035c6799f | ||
![]() |
0a69ff1d8b | ||
![]() |
ffdea65c59 | ||
![]() |
6d75b4997b | ||
![]() |
6e141e25a7 | ||
![]() |
70c2d7c0d5 | ||
![]() |
8ffc62ed67 | ||
![]() |
97862e54a5 | ||
![]() |
7594cea1e0 | ||
![]() |
56504beea3 | ||
![]() |
081cd8a8b6 | ||
![]() |
e300fcda60 | ||
![]() |
2617409867 | ||
![]() |
905dc5642e | ||
![]() |
0d89750a57 | ||
![]() |
ba750a289f | ||
![]() |
0e74502cc1 | ||
![]() |
61d8cfe93c | ||
![]() |
dbc1611b74 | ||
![]() |
e7241cde67 | ||
![]() |
a8f4643d9c | ||
![]() |
d3c62ba406 | ||
![]() |
dd14d83f98 | ||
![]() |
3ab6b9c8e7 | ||
![]() |
5f2472ced2 | ||
![]() |
c07fd1cbd8 | ||
![]() |
672d8b905f | ||
![]() |
277ce61619 | ||
![]() |
337848b241 | ||
![]() |
00ed68281e | ||
![]() |
9d44b7f3f5 | ||
![]() |
7835a8ede8 | ||
![]() |
8742c736a4 | ||
![]() |
935503400d | ||
![]() |
d30ec7e85b | ||
![]() |
83bd0f5b13 | ||
![]() |
60d4028cf5 | ||
![]() |
a533e1fbd9 | ||
![]() |
42b718a4b3 | ||
![]() |
759caba765 | ||
![]() |
1b6dcb061b | ||
![]() |
98e6badbb2 | ||
![]() |
8584e43cc7 | ||
![]() |
49203c3abb | ||
![]() |
1421600cc5 | ||
![]() |
294efd42f1 | ||
![]() |
d921be4435 | ||
![]() |
195ac0e411 | ||
![]() |
296365ea3f | ||
![]() |
3a1af21e6f | ||
![]() |
7326727540 | ||
![]() |
f2bf5bc047 | ||
![]() |
b7c34446da | ||
![]() |
337f93848f | ||
![]() |
c3ea648279 | ||
![]() |
d83bb86af3 | ||
![]() |
47debcf2e7 | ||
![]() |
dbdb75c4d6 | ||
![]() |
c80eabb066 | ||
![]() |
5fe45a04f7 | ||
![]() |
e557eaa24f | ||
![]() |
8cdc814199 | ||
![]() |
beffc53463 | ||
![]() |
4521f6c342 | ||
![]() |
bb3a6a7a84 | ||
![]() |
592c25492d | ||
![]() |
23ed6f8932 | ||
![]() |
0f2f369a2b | ||
![]() |
d5d0f235a7 | ||
![]() |
091c9825bf | ||
![]() |
5183a2bdca | ||
![]() |
be3ba92429 | ||
![]() |
fe1f5d5150 | ||
![]() |
760cb807cc | ||
![]() |
b9db5840c9 | ||
![]() |
b8a9740792 | ||
![]() |
8a8884da64 | ||
![]() |
9978e35f33 | ||
![]() |
ffd7b52ade | ||
![]() |
a693265cb1 | ||
![]() |
614539a0b4 | ||
![]() |
292d396eeb | ||
![]() |
36667b5c4b | ||
![]() |
61e72cd186 | ||
![]() |
52dbc5a109 | ||
![]() |
4010fca0cf | ||
![]() |
f5a383dd1a | ||
![]() |
a6d3ec38b3 | ||
![]() |
54b2b6a56e | ||
![]() |
a654b9a35c | ||
![]() |
e17f4c8800 | ||
![]() |
8aff53ef86 | ||
![]() |
8028c821cb | ||
![]() |
fb5aeca78c | ||
![]() |
8ae34432b9 | ||
![]() |
fbedd78c74 | ||
![]() |
d3ae8dd487 | ||
![]() |
ded9026e91 | ||
![]() |
4298303ea4 | ||
![]() |
632010310b | ||
![]() |
f6a1cf2820 | ||
![]() |
41803803d5 | ||
![]() |
745819b732 | ||
![]() |
57b83aba2b | ||
![]() |
c97a6ec0bf | ||
![]() |
b751dbb418 | ||
![]() |
fc7c4c5be1 | ||
![]() |
76a4656ad6 | ||
![]() |
e32261ec1d | ||
![]() |
5817f5ead6 | ||
![]() |
31301e29bc | ||
![]() |
4be13899f5 | ||
![]() |
284cdac428 | ||
![]() |
d39200568b | ||
![]() |
6d7e8ff909 | ||
![]() |
c83fa6d74b | ||
![]() |
3bd3d72b48 | ||
![]() |
2275f34291 | ||
![]() |
ab54059d2b | ||
![]() |
996caba2df | ||
![]() |
50cfc07966 |
163 changed files with 51907 additions and 4755 deletions
|
@ -1,2 +0,0 @@
|
||||||
[config]
|
|
||||||
command = bash ./deploy.sh
|
|
46
.forgejo/workflows/node.yaml
Normal file
46
.forgejo/workflows/node.yaml
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
name: GBCI
|
||||||
|
run: git config --global http.sslVerify false
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "main" ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ "main" ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: gbo
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Disable SSL verification (temporary)
|
||||||
|
run: git config --global http.sslVerify false
|
||||||
|
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
# - name: Setup Node.js
|
||||||
|
# uses: actions/setup-node@v4
|
||||||
|
# with:
|
||||||
|
# node-version: '20'
|
||||||
|
# cache: 'npm'
|
||||||
|
|
||||||
|
- name: Copy files to deployment location
|
||||||
|
run: |
|
||||||
|
echo "[General Bots Deployer] Copying files to deploy location..."
|
||||||
|
sudo rm -rf /opt/gbo/bin/bot/botserver/dist
|
||||||
|
sudo cp -r ./* /opt/gbo/bin/bot/botserver
|
||||||
|
|
||||||
|
|
||||||
|
- name: Building BotServer
|
||||||
|
run: |
|
||||||
|
echo "[General Bots Deployer] Building BotServer..."
|
||||||
|
# rm -rf /opt/gbo/bin/bot/botserver/node_modules
|
||||||
|
cd /opt/gbo/bin/bot/botserver
|
||||||
|
sudo npm ci --production
|
||||||
|
npm run build-server
|
||||||
|
npm run build-gbui
|
||||||
|
|
||||||
|
|
||||||
|
- name: Restart Bots Deployer
|
||||||
|
run: |
|
||||||
|
echo "[General Bots Deployer] Restarting..."
|
||||||
|
lxc restart pragmatismo-bot
|
9
.github/ISSUE_TEMPLATE.md
vendored
9
.github/ISSUE_TEMPLATE.md
vendored
|
@ -1,9 +0,0 @@
|
||||||
<!-- File a GitHub issue only for bugs or feature requests related to the code **in this repository**. For other topics you can get more information in the README file. -->
|
|
||||||
|
|
||||||
### Observed Results:
|
|
||||||
|
|
||||||
<!-- This could be a description, error output, steps to reproduce, a feature missed, etc. -->
|
|
||||||
|
|
||||||
### Expected behavior:
|
|
||||||
|
|
||||||
<!-- What did you expect to happen? -->
|
|
35
.github/ISSUE_TEMPLATE/bug_report.md
vendored
35
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -1,35 +0,0 @@
|
||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Create a report to help us improve
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Describe the bug**
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
|
|
||||||
**To Reproduce**
|
|
||||||
Steps to reproduce the behavior:
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '....'
|
|
||||||
3. Scroll down to '....'
|
|
||||||
4. See error
|
|
||||||
|
|
||||||
**Expected behavior**
|
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
|
|
||||||
**Screenshots**
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
|
|
||||||
**Desktop (please complete the following information):**
|
|
||||||
- OS: [e.g. iOS]
|
|
||||||
- Browser [e.g. chrome, safari]
|
|
||||||
- Version [e.g. 22]
|
|
||||||
|
|
||||||
**Smartphone (please complete the following information):**
|
|
||||||
- Device: [e.g. iPhone6]
|
|
||||||
- OS: [e.g. iOS8.1]
|
|
||||||
- Browser [e.g. stock browser, safari]
|
|
||||||
- Version [e.g. 22]
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context about the problem here.
|
|
7
.github/ISSUE_TEMPLATE/custom.md
vendored
7
.github/ISSUE_TEMPLATE/custom.md
vendored
|
@ -1,7 +0,0 @@
|
||||||
---
|
|
||||||
name: Custom issue template
|
|
||||||
about: Describe this issue template's purpose here.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
|
@ -1,17 +0,0 @@
|
||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest an idea for this project
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
|
||||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
|
||||||
A clear and concise description of what you want to happen.
|
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context or screenshots about the feature request here.
|
|
2
.github/ISSUE_TEMPLATE/requirement
vendored
2
.github/ISSUE_TEMPLATE/requirement
vendored
|
@ -1,2 +0,0 @@
|
||||||
**Description**
|
|
||||||
A clear and concise description of what the requirement is.
|
|
16
.github/PULL_REQUEST_TEMPLATE.md
vendored
16
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
@ -1,16 +0,0 @@
|
||||||
### Changes description
|
|
||||||
|
|
||||||
<!-- Describe results, user mentions, screenshots, screencast (gif) -->
|
|
||||||
|
|
||||||
### Checklist
|
|
||||||
|
|
||||||
Please check if your PR fulfills the following specifications:
|
|
||||||
|
|
||||||
- [ ] Tests for the changes have been done
|
|
||||||
- [ ] Docs have been added/updated
|
|
||||||
|
|
||||||
### References
|
|
||||||
|
|
||||||
<!-- issues related (for reference or to be closed) and/or links of discuss -->
|
|
||||||
|
|
||||||
Closes #N/A
|
|
3
.github/invite-contributors.yml
vendored
3
.github/invite-contributors.yml
vendored
|
@ -1,3 +0,0 @@
|
||||||
isOutside: true
|
|
||||||
# Team Name
|
|
||||||
team: contributors
|
|
44
.github/settings.yml
vendored
44
.github/settings.yml
vendored
|
@ -1,44 +0,0 @@
|
||||||
repository:
|
|
||||||
name: botserver
|
|
||||||
description: botserver
|
|
||||||
homepage: http://pragmatismo.cloud/general-bots
|
|
||||||
topics: node-module
|
|
||||||
private: false
|
|
||||||
has_issues: true
|
|
||||||
has_wiki: false
|
|
||||||
has_downloads: true
|
|
||||||
default_branch: develop
|
|
||||||
allow_squash_merge: true
|
|
||||||
allow_merge_commit: false
|
|
||||||
allow_rebase_merge: true
|
|
||||||
labels:
|
|
||||||
- name: bug
|
|
||||||
color: f44336
|
|
||||||
- name: build
|
|
||||||
color: 795548
|
|
||||||
- name: ci
|
|
||||||
color: fbca04
|
|
||||||
- name: documentation
|
|
||||||
color: 607d8b
|
|
||||||
- name: duplicate
|
|
||||||
color: 9e9e9e
|
|
||||||
- name: feature
|
|
||||||
color: 3f51b5
|
|
||||||
- name: invalid
|
|
||||||
color: cddc39
|
|
||||||
- name: performance
|
|
||||||
color: 009688
|
|
||||||
- name: question
|
|
||||||
color: ff5722
|
|
||||||
- name: refactor
|
|
||||||
color: 9c27b0
|
|
||||||
- name: style
|
|
||||||
color: 2196f3
|
|
||||||
- name: test
|
|
||||||
color: 8bc34a
|
|
||||||
- name: wontfix
|
|
||||||
color: ffffff
|
|
||||||
- name: help wanted
|
|
||||||
color: 33aa3f
|
|
||||||
- name: good first issue
|
|
||||||
color: 7057ff
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -25,9 +25,10 @@ GB.log
|
||||||
gb.log
|
gb.log
|
||||||
GB.log.json
|
GB.log.json
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
package-lock.json
|
|
||||||
yarn-lock.json
|
yarn-lock.json
|
||||||
logo.svg
|
logo.svg
|
||||||
screenshot.png
|
screenshot.png
|
||||||
data.db
|
data.db
|
||||||
.wwebjs_cache
|
.wwebjs_cache
|
||||||
|
*doula*
|
||||||
|
*botpoc*
|
33
.travis.yml
33
.travis.yml
|
@ -1,33 +0,0 @@
|
||||||
dist: focal
|
|
||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- 19.7.0
|
|
||||||
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email: false
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- npm run build
|
|
||||||
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- main
|
|
||||||
- /^greenkeeper/.*$/
|
|
||||||
except:
|
|
||||||
- /^v\d+\.\d+\.\d+$/
|
|
||||||
|
|
||||||
after_success:
|
|
||||||
- npm install -g travis-deploy-once
|
|
||||||
- npm run travis-deploy-once "npm run semantic-release"
|
|
||||||
- npm pack
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
|
|
||||||
- provider: pages
|
|
||||||
skip_cleanup: true
|
|
||||||
local_dir: docs/reference
|
|
||||||
github_token: $GITHUB_TOKEN
|
|
||||||
on:
|
|
||||||
tags: false
|
|
||||||
branch: main
|
|
30
.vscode/launch.json
vendored
30
.vscode/launch.json
vendored
|
@ -1,30 +0,0 @@
|
||||||
{
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"type": "node",
|
|
||||||
"request": "launch",
|
|
||||||
"sourceMaps": true,
|
|
||||||
"name": "Debug Program",
|
|
||||||
"runtimeExecutable": "node",
|
|
||||||
"program": "${workspaceRoot}/boot.mjs",
|
|
||||||
"cwd": "${workspaceRoot}",
|
|
||||||
"env": {
|
|
||||||
"NODE_ENV": "development",
|
|
||||||
"NODE_NO_WARNINGS": "1"
|
|
||||||
},
|
|
||||||
"args": [
|
|
||||||
"--require", "${workspaceRoot}/suppress-node-warnings.cjs"
|
|
||||||
],
|
|
||||||
"skipFiles": [
|
|
||||||
"node_modules/**/*.js",
|
|
||||||
"<node_internals>/**"
|
|
||||||
],
|
|
||||||
"outFiles": [
|
|
||||||
"${workspaceRoot}/dist/**/*.js"
|
|
||||||
],
|
|
||||||
"stopOnEntry": false,
|
|
||||||
"console": "integratedTerminal"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"git.ignoreLimitWarning": true,
|
|
||||||
"cmake.ignoreCMakeListsMissing": true
|
|
||||||
}
|
|
30
.vscode/tasks.json
vendored
30
.vscode/tasks.json
vendored
|
@ -1,30 +0,0 @@
|
||||||
{
|
|
||||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
|
||||||
// for the documentation about the tasks.json format
|
|
||||||
"version": "2.0.0",
|
|
||||||
"tasks": [
|
|
||||||
{
|
|
||||||
"type": "typescript",
|
|
||||||
"tsconfig": "tsconfig.json",
|
|
||||||
"option": "watch",
|
|
||||||
"problemMatcher": [
|
|
||||||
"$tsc-watch"
|
|
||||||
],
|
|
||||||
"group": {
|
|
||||||
"kind": "build",
|
|
||||||
"isDefault": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "typescript",
|
|
||||||
"tsconfig": "tsconfig.json",
|
|
||||||
"problemMatcher": [
|
|
||||||
"$tsc"
|
|
||||||
],
|
|
||||||
"group": {
|
|
||||||
"kind": "build",
|
|
||||||
"isDefault": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -32,7 +32,7 @@ In general, things we find useful when reviewing suggestions are:
|
||||||
## Contributing bug fixes
|
## Contributing bug fixes
|
||||||
|
|
||||||
General Bots is current in early preview. We're still accepting contributions in the form of bug fixes.
|
General Bots is current in early preview. We're still accepting contributions in the form of bug fixes.
|
||||||
A bug must have an issue tracking it in the issue tracker that has been approved by the pragmatismo.cloud team. Your pull request should include a link to the bug that you are fixing. If you've submitted a PR for a bug, please post a comment in the bug to avoid duplication of effort.
|
A bug must have an issue tracking it in the issue tracker that has been approved by the pragmatismo.com.br team. Your pull request should include a link to the bug that you are fixing. If you've submitted a PR for a bug, please post a comment in the bug to avoid duplication of effort.
|
||||||
|
|
||||||
## Contributing features
|
## Contributing features
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ Please open an issue with the `Schema` label to get a discussion started.
|
||||||
|
|
||||||
## Legal
|
## Legal
|
||||||
|
|
||||||
We appreciate community contributions to code repositories open sourced by pragmatismo.cloud. By signing a contributor license agreement, we ensure that the community is free to use your contributions.
|
We appreciate community contributions to code repositories open sourced by pragmatismo.com.br. By signing a contributor license agreement, we ensure that the community is free to use your contributions.
|
||||||
|
|
||||||
## Housekeeping
|
## Housekeeping
|
||||||
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
# General Bots Features
|
|
||||||
|
|
||||||
| Feature | BF | GB |
|
|
||||||
|----------------------------------------------------------------------------|----|----|
|
|
||||||
| Use of conversational administration to manage bot packages (Talk to admin)| - | X |
|
|
||||||
| F5 to run on VSCode | - | X |
|
|
||||||
| Isolated code on packages | - | X |
|
|
||||||
| Breaking changes protected | - | X |
|
|
2
LICENSE
2
LICENSE
|
@ -1,5 +1,5 @@
|
||||||
General Bots is licensed under a dual license. To check which license
|
General Bots is licensed under a dual license. To check which license
|
||||||
edition of General bots you have installed, please ask info@pragmatismo.cloud
|
edition of General bots you have installed, please ask info@pragmatismo.com.br
|
||||||
informing your Customer ID.
|
informing your Customer ID.
|
||||||
|
|
||||||
If you modify this Program, or any covered work, by combining it
|
If you modify this Program, or any covered work, by combining it
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
|
|
||||||
# Localization in General Bots
|
|
||||||
|
|
||||||
## .gbapp
|
|
||||||
|
|
||||||
The localization is done by adding a strings.ts file to the root of the .gbapp package.
|
|
||||||
|
|
107
README.md
107
README.md
|
@ -1,5 +1,5 @@
|
||||||
### Key Facts
|
### Key Facts
|
||||||
- AGPL License (to use as custom-label SaaS)
|
- LLM Orchestrator AGPL licensed (to use as custom-label SaaS, contributing back)
|
||||||
- True community governance
|
- True community governance
|
||||||
- No single corporate control
|
- No single corporate control
|
||||||
- 5+ years of stability
|
- 5+ years of stability
|
||||||
|
@ -7,10 +7,13 @@
|
||||||
- Enterprise-grad
|
- Enterprise-grad
|
||||||
- Hosted locally or Multicloud
|
- Hosted locally or Multicloud
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
<a href="https://github.com/generalbots/botserver/graphs/contributors">
|
<a href="https://github.com/generalbots/botserver/graphs/contributors">
|
||||||
<img src="https://contrib.rocks/image?repo=generalbots/botserver" />
|
<img src="https://contrib.rocks/image?repo=generalbots/botserver" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
| Area | Status |
|
| Area | Status |
|
||||||
|------------------------------|----------------------------------------------------------------------------------------------------|
|
|------------------------------|----------------------------------------------------------------------------------------------------|
|
||||||
|
@ -19,16 +22,15 @@
|
||||||
| Management | [](https://gitHub.com/GeneralBots/BotServer/graphs/commit-activity) |
|
| Management | [](https://gitHub.com/GeneralBots/BotServer/graphs/commit-activity) |
|
||||||
| Security | [](https://snyk.io/test/github/GeneralBots/BotServer) |
|
| Security | [](https://snyk.io/test/github/GeneralBots/BotServer) |
|
||||||
| Building & Quality | [](https://coveralls.io/github/GeneralBots/BotServer) [](https://github.com/prettier/prettier) |
|
| Building & Quality | [](https://coveralls.io/github/GeneralBots/BotServer) [](https://github.com/prettier/prettier) |
|
||||||
| Packaging | [](https://badge.fury.io) [](https://david-dm.org) [](http://commitizen.github.io/cz-cli/) |
|
| Packaging | [](https://badge.fury.io) [](http://commitizen.github.io/cz-cli/) |
|
||||||
| Samples | [BASIC](https://github.com/GeneralBots/BotServer/tree/master/packages/default.gbdialog) or [](https://github.com/GeneralBots/AzureADPasswordReset.gbapp)
|
| Samples | [BASIC](https://github.com/GeneralBots/BotServer/tree/master/packages/default.gbdialog) or [](https://github.com/GeneralBots/AzureADPasswordReset.gbapp)
|
||||||
| [Docker Image](https://github.com/lpicanco/docker-botserver)  <br/> *Provided by [@lpicanco](https://github.com/lpicanco/docker-botserver)* |
|
| [Docker Image](https://github.com/lpicanco/docker-botserver)  <br/> *Provided by [@lpicanco](https://github.com/lpicanco/docker-botserver)* |
|
||||||
|
|
||||||
General Bots
|
# General Bots
|
||||||
------------------
|
|
||||||
|
|
||||||

|
)
|
||||||
|
|
||||||
General Bot is a strongly typed package based chat bot server focused in convention over configuration and code-less approaches, which brings software packages and application server concepts to help parallel bot development.
|
General Bot is a strongly typed LLM conversational platform package based chat bot server focused in convention over configuration and code-less approaches, which brings software packages and application server concepts to help parallel bot development.
|
||||||
|
|
||||||
## What is a Bot Server?
|
## What is a Bot Server?
|
||||||
|
|
||||||
|
@ -42,9 +44,78 @@ advanced fashion writing custom code in editors like Visual Studio Code, Atom or
|
||||||
|
|
||||||
Everyone can create bots by just copying and pasting some files and using their
|
Everyone can create bots by just copying and pasting some files and using their
|
||||||
favorite tools from Office (or any text editor) or Photoshop (or any image
|
favorite tools from Office (or any text editor) or Photoshop (or any image
|
||||||
editor). BASIC can be used to build custom dialogs so Bot can be extended just like VBA for Excel (currently in alpha).
|
editor). LLM and BASIC can be mixed used to build custom dialogs so Bot can be extended just like VBA for Excel.
|
||||||
|
|
||||||

|
## Getting Started
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
Before you embark on your General Bots journey, ensure you have the following tools installed:
|
||||||
|
|
||||||
|
- **Node.js (version 20 or later)**: General Bots leverages the latest features of Node.js to provide a robust and efficient runtime environment. Download it from [nodejs.org](https://nodejs.org/en/download/).
|
||||||
|
- **Git (latest stable version)**: Essential for version control and collaborating on bot projects. Get it from [git-scm.com](https://git-scm.com/downloads).
|
||||||
|
|
||||||
|
### Quick Start Guide
|
||||||
|
|
||||||
|
Follow these steps to get your General Bots server up and running:
|
||||||
|
|
||||||
|
1. Clone the repository:
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/GeneralBots/BotServer
|
||||||
|
```
|
||||||
|
This command creates a local copy of the General Bots server repository on your machine.
|
||||||
|
|
||||||
|
2. Navigate to the project directory:
|
||||||
|
```bash
|
||||||
|
cd BotServer
|
||||||
|
```
|
||||||
|
This changes your current directory to the newly cloned BotServer folder.
|
||||||
|
|
||||||
|
3. Install dependencies and start the server:
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
npm run start
|
||||||
|
```
|
||||||
|
The `npm install` command installs all necessary dependencies for the project. `npm run start` builds your bot server locally and serves it through a development server.
|
||||||
|
|
||||||
|
### Accessing Your Bot
|
||||||
|
|
||||||
|
Once the server is running, you can access your bot at `http://localhost:4242/`. This local server allows you to interact with your bot and test its functionality in real-time. If you want to publish
|
||||||
|
without password, define [ADMIN_OPEN_PUBLISH](https://github.com/GeneralBots/BotBook/master/docs/chapter-07-gbot-reference#enviroment-variables-reference) as true in BotServer .env file.
|
||||||
|
|
||||||
|
To publish bot packages and initiate a conversation with the bot, use the command:
|
||||||
|
|
||||||
|
```
|
||||||
|
/publish
|
||||||
|
```
|
||||||
|
This command prepares your bot packages for use and allows you to start interacting with your bot immediately.
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
|
||||||
|
### 1. Project Structure
|
||||||
|
|
||||||
|
The General Bots server follows a modular architecture designed for flexibility and scalability. Here's an overview of the main directories:
|
||||||
|
|
||||||
|
```
|
||||||
|
BotServer/
|
||||||
|
├── packages/
|
||||||
|
│ ├── core.gbapp/ # Core bot functionality
|
||||||
|
│ ├── kb.gbapp/ # Knowledge base packages
|
||||||
|
├── src / # Main entry point
|
||||||
|
└── package.json # Project configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
This structure allows for easy navigation and management of different aspects of your bot project.
|
||||||
|
|
||||||
|
### 2. Creating Custom Packages
|
||||||
|
|
||||||
|
One of the strengths of General Bots is its extensibility. You can create custom packages to enhance your bot's capabilities:
|
||||||
|
|
||||||
|
- **.gbkb (Knowledge Base packages)**: Store and manage your bot's knowledge and responses.
|
||||||
|
- **.gbtheme (Theme packages)**: Customize the visual appearance of your bot interface.
|
||||||
|
- **.gbapp (Application packages)**: Add new features and functionalities to your bot.
|
||||||
|
|
||||||
|
Each package type has its own structure and purpose, which we'll explore in depth in their respective chapters.
|
||||||
|
|
||||||
## Samples
|
## Samples
|
||||||
|
|
||||||
|
@ -76,18 +147,12 @@ SEND FILE img
|
||||||
|
|
||||||
## Guide
|
## Guide
|
||||||
|
|
||||||
[Read the General Bots BotBook Guide](https://github.com/GeneralBots/BotBook/tree/master/book).
|
[Read the General Bots BotBook Guide](https://docs.pragmatismo.com.br)
|
||||||
|
|
||||||
# Videos
|
# Videos
|
||||||
|
|
||||||
Now with the General Bots server you can press F5 on Visual Studio to get a bot factory on your environment* published on November 10th, 2018.
|
7 AI General Bots LLM Templates for Goodness
|
||||||
|
[https://www.youtube.com/watch?v=KJgvUPXi3Fw](https://www.youtube.com/watch?v=KJgvUPXi3Fw)
|
||||||
[](https://www.youtube.com/watch?v=AfKTwljoMOs)
|
|
||||||
|
|
||||||
See how easy is to use 'hear' and 'talk' to build Microsoft BOT Framework v4 logic with plain BASIC * published on December 3rd, 2018.
|
|
||||||
|
|
||||||
[](https://www.youtube.com/watch?v=yX1sF9n9628)
|
|
||||||
|
|
||||||
|
|
||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
|
@ -96,14 +161,14 @@ See our [Contribution Guidelines](https://github.com/pragmatismo-io/BotServer/bl
|
||||||
|
|
||||||
# Reporting Security Issues
|
# Reporting Security Issues
|
||||||
|
|
||||||
Security issues and bugs should be reported privately, via email, to the pragmatismo.cloud Security
|
Security issues and bugs should be reported privately, via email, to the pragmatismo.com.br Security
|
||||||
team at [security@pragmatismo.cloud](mailto:security@pragmatismo.cloud). You should
|
team at [security@pragmatismo.com.br](mailto:security@pragmatismo.com.br). You should
|
||||||
receive a response within 24 hours. If for some reason you do not, please follow up via
|
receive a response within 24 hours. If for some reason you do not, please follow up via
|
||||||
email to ensure we received your original message.
|
email to ensure we received your original message.
|
||||||
|
|
||||||
# License & Warranty
|
# License & Warranty
|
||||||
|
|
||||||
General Bot Copyright (c) pragmatismo.cloud. All rights reserved.
|
General Bot Copyright (c) pragmatismo.com.br. All rights reserved.
|
||||||
Licensed under the AGPL-3.0.
|
Licensed under the AGPL-3.0.
|
||||||
|
|
||||||
According to our dual licensing model, this program can be used either
|
According to our dual licensing model, this program can be used either
|
||||||
|
@ -119,7 +184,7 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU Affero General Public License for more details.
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
"General Bot" is a registered trademark of pragmatismo.cloud.
|
"General Bot" is a registered trademark of pragmatismo.com.br.
|
||||||
The licensing of the program under the AGPLv3 does not imply a
|
The licensing of the program under the AGPLv3 does not imply a
|
||||||
trademark license. Therefore any rights, title and interest in
|
trademark license. Therefore any rights, title and interest in
|
||||||
our trademarks remain entirely with us.
|
our trademarks remain entirely with us.
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
# Roadmap
|
|
||||||
|
|
||||||
| Title | Priority | Release | Status |
|
|
||||||
|-------------------------------|------------------------------------------------------------------------------------------------------------|---------|--------|
|
|
||||||
| Isolation of .gbapp per .gbot | Today .gbapp loaded is shared across all bot instances and must be associated to one or more individually. | Medium | 2019Q4 |
|
|
||||||
| Python based .gbapps | Write conversational login in Python | Low | - |
|
|
|
@ -1,7 +0,0 @@
|
||||||
# General Bots Server Samples
|
|
||||||
|
|
||||||
| Sample | Description |
|
|
||||||
|--------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
||||||
| [IntranetBotQuickStart-gbai](https://github.com/pragmatismo-io/IntranetBotQuickStart.gbai) | Free modules from General Bots Intranet based bot. |
|
|
||||||
| [AzureADPasswordReset-gbapp](https://github.com/pragmatismo-io/AzureADPasswordReset.gbapp) | Custom General Bot App (gbapp) for resetting an user password in Azure Active Directory, Office 365, Dynamics 365 or any app published through Azure AD. |
|
|
||||||
| [ProjectOnline.gbkb](https://github.com/pragmatismo-io/ProjectOnline.gbkb) | The .gbkb file demonstring a Knowledge Base for pragmatismo.cloud KBot for Microsoft Project. |
|
|
|
@ -20,7 +20,7 @@ Review process
|
||||||
|
|
||||||
We will review this policy yearly.
|
We will review this policy yearly.
|
||||||
In the meantime, if you have any questions, suggestions
|
In the meantime, if you have any questions, suggestions
|
||||||
or feedback, please contact security@pragmatismo.cloud
|
or feedback, please contact security@pragmatismo.com.br
|
||||||
|
|
||||||
|
|
||||||
We will only classify information which is necessary for the completion of our duties. We will also limit
|
We will only classify information which is necessary for the completion of our duties. We will also limit
|
||||||
|
@ -58,4 +58,4 @@ any other tasks that could result in a conflict of interest.
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
You can expect to get an update on a reported vulnerability in a day or two.
|
You can expect to get an update on a reported vulnerability in a day or two.
|
||||||
security@pragmatismo.cloud
|
security@pragmatismo.com.br
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
},
|
},
|
||||||
"servers": [
|
"servers": [
|
||||||
{
|
{
|
||||||
"url": "https://gb.pragmatismo.cloud/api",
|
"url": "https://generalbots.online/api",
|
||||||
"description": "General Bots Online"
|
"description": "General Bots Online"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
2
boot.mjs
2
boot.mjs
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
process.stdout.write(`General Bots VM: node@${process.version.replace('v', '')}, ${process.platform} ${process.arch} `);
|
process.stdout.write(`General Bots 5 VM: node@${process.version.replace('v', '')}, ${process.platform} ${process.arch} `);
|
||||||
|
|
||||||
import fs from 'fs/promises';
|
import fs from 'fs/promises';
|
||||||
import os from 'node:os';
|
import os from 'node:os';
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"groups": {
|
|
||||||
"default": {
|
|
||||||
"packages": [
|
|
||||||
"package.json",
|
|
||||||
"packages/default.gbui/package.json"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
BIN
logo.png
Normal file
BIN
logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
48942
package-lock.json
generated
Normal file
48942
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
16
package.json
16
package.json
|
@ -102,7 +102,7 @@
|
||||||
"@semantic-release/git": "10.0.1",
|
"@semantic-release/git": "10.0.1",
|
||||||
"@sendgrid/mail": "8.1.3",
|
"@sendgrid/mail": "8.1.3",
|
||||||
"@sequelize/core": "7.0.0-alpha.37",
|
"@sequelize/core": "7.0.0-alpha.37",
|
||||||
"@types/node": "22.5.2",
|
"@sequelize/postgres": "^7.0.0-alpha.43",
|
||||||
"@types/validator": "13.12.1",
|
"@types/validator": "13.12.1",
|
||||||
"adm-zip": "0.5.16",
|
"adm-zip": "0.5.16",
|
||||||
"ai2html": "^0.121.1",
|
"ai2html": "^0.121.1",
|
||||||
|
@ -113,6 +113,7 @@
|
||||||
"async-promises": "0.2.3",
|
"async-promises": "0.2.3",
|
||||||
"async-retry": "1.3.3",
|
"async-retry": "1.3.3",
|
||||||
"basic-auth": "2.0.1",
|
"basic-auth": "2.0.1",
|
||||||
|
"bcrypt": "^5.1.1",
|
||||||
"billboard.js": "3.13.0",
|
"billboard.js": "3.13.0",
|
||||||
"bluebird": "3.7.2",
|
"bluebird": "3.7.2",
|
||||||
"body-parser": "1.20.2",
|
"body-parser": "1.20.2",
|
||||||
|
@ -169,11 +170,13 @@
|
||||||
"langchain": "0.2.17",
|
"langchain": "0.2.17",
|
||||||
"language-tags": "1.0.9",
|
"language-tags": "1.0.9",
|
||||||
"line-replace": "2.0.1",
|
"line-replace": "2.0.1",
|
||||||
|
"livekit-server-sdk": "^2.12.0",
|
||||||
"lodash": "4.17.21",
|
"lodash": "4.17.21",
|
||||||
"luxon": "3.5.0",
|
"luxon": "3.5.0",
|
||||||
"mammoth": "1.8.0",
|
"mammoth": "1.8.0",
|
||||||
"mariadb": "3.3.1",
|
"mariadb": "3.3.1",
|
||||||
"mime-types": "2.1.35",
|
"mime-types": "2.1.35",
|
||||||
|
"minio": "^8.0.4",
|
||||||
"moment": "2.30.1",
|
"moment": "2.30.1",
|
||||||
"ms-rest-azure": "3.0.2",
|
"ms-rest-azure": "3.0.2",
|
||||||
"mysql": "^2.18.1",
|
"mysql": "^2.18.1",
|
||||||
|
@ -183,6 +186,7 @@
|
||||||
"node-html-parser": "6.1.13",
|
"node-html-parser": "6.1.13",
|
||||||
"node-nlp": "4.27.0",
|
"node-nlp": "4.27.0",
|
||||||
"node-tesseract-ocr": "2.2.1",
|
"node-tesseract-ocr": "2.2.1",
|
||||||
|
"nodemailer": "6.10.1",
|
||||||
"nodemon": "^3.1.7",
|
"nodemon": "^3.1.7",
|
||||||
"npm": "10.8.3",
|
"npm": "10.8.3",
|
||||||
"open": "10.1.0",
|
"open": "10.1.0",
|
||||||
|
@ -192,7 +196,7 @@
|
||||||
"pdf-parse": "1.1.1",
|
"pdf-parse": "1.1.1",
|
||||||
"pdf-to-png-converter": "3.3.0",
|
"pdf-to-png-converter": "3.3.0",
|
||||||
"pdfjs-dist": "4.6.82",
|
"pdfjs-dist": "4.6.82",
|
||||||
"pdfkit": "0.15.0",
|
"pg": "^8.13.1",
|
||||||
"phone": "3.1.50",
|
"phone": "3.1.50",
|
||||||
"pizzip": "3.1.7",
|
"pizzip": "3.1.7",
|
||||||
"pptxtemplater": "1.0.5",
|
"pptxtemplater": "1.0.5",
|
||||||
|
@ -221,6 +225,9 @@
|
||||||
"sqlite3": "5.1.7",
|
"sqlite3": "5.1.7",
|
||||||
"ssr-for-bots": "1.0.1-c",
|
"ssr-for-bots": "1.0.1-c",
|
||||||
"strict-password-generator": "1.1.2",
|
"strict-password-generator": "1.1.2",
|
||||||
|
"stripe": "^18.0.0",
|
||||||
|
"super-strong-password-generator": "2.0.2",
|
||||||
|
"super-strong-password-generator-es": "2.0.2",
|
||||||
"svg2img": "^1.0.0-beta.2",
|
"svg2img": "^1.0.0-beta.2",
|
||||||
"swagger-client": "3.29.2",
|
"swagger-client": "3.29.2",
|
||||||
"swagger-ui-dist": "5.17.14",
|
"swagger-ui-dist": "5.17.14",
|
||||||
|
@ -248,6 +255,9 @@
|
||||||
"zod-to-json-schema": "3.23.2"
|
"zod-to-json-schema": "3.23.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/lodash": "^4.17.20",
|
||||||
|
"@types/node": "^24.1.0",
|
||||||
|
"@types/node-fetch": "^2.6.12",
|
||||||
"@types/qrcode": "1.5.5",
|
"@types/qrcode": "1.5.5",
|
||||||
"@types/url-join": "4.0.3",
|
"@types/url-join": "4.0.3",
|
||||||
"@typescript-eslint/eslint-plugin": "8.4.0",
|
"@typescript-eslint/eslint-plugin": "8.4.0",
|
||||||
|
@ -261,8 +271,6 @@
|
||||||
"prettier-standard": "16.4.1",
|
"prettier-standard": "16.4.1",
|
||||||
"semantic-release": "24.1.0",
|
"semantic-release": "24.1.0",
|
||||||
"simple-commit-message": "4.1.3",
|
"simple-commit-message": "4.1.3",
|
||||||
"super-strong-password-generator": "2.0.2",
|
|
||||||
"super-strong-password-generator-es": "2.0.2",
|
|
||||||
"travis-deploy-once": "5.0.11",
|
"travis-deploy-once": "5.0.11",
|
||||||
"tslint": "6.1.3",
|
"tslint": "6.1.3",
|
||||||
"tsx": "^4.19.1",
|
"tsx": "^4.19.1",
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -47,6 +47,7 @@ import { SecService } from '../../security.gbapp/services/SecService.js';
|
||||||
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
|
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
|
||||||
import { GBServer } from '../../../src/app.js';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
|
import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
|
||||||
|
import { GBUtil } from '../../../src/util.js';
|
||||||
|
|
||||||
|
|
||||||
class AdminDialog extends IGBDialog {
|
class AdminDialog extends IGBDialog {
|
||||||
|
@ -86,7 +87,7 @@ class AdminDialog extends IGBDialog {
|
||||||
const locale = step.context.activity.locale;
|
const locale = step.context.activity.locale;
|
||||||
const sensitive = step.context.activity['originalText'];
|
const sensitive = step.context.activity['originalText'];
|
||||||
|
|
||||||
if (sensitive === min.instance.adminPass) {
|
if (await GBUtil.comparePassword( sensitive, min.instance.adminPass)) {
|
||||||
await min.conversationalService.sendText(min, step, Messages[locale].welcome);
|
await min.conversationalService.sendText(min, step, Messages[locale].welcome);
|
||||||
|
|
||||||
return await step.endDialog(true);
|
return await step.endDialog(true);
|
||||||
|
@ -120,7 +121,7 @@ class AdminDialog extends IGBDialog {
|
||||||
const locale = step.context.activity.locale;
|
const locale = step.context.activity.locale;
|
||||||
const sensitive = step.context.activity['originalText'];
|
const sensitive = step.context.activity['originalText'];
|
||||||
|
|
||||||
if (sensitive === min.instance.adminPass) {
|
if (await GBUtil.comparePassword( sensitive, min.instance.adminPass)) {
|
||||||
await min.conversationalService.sendText(min, step, Messages[locale].welcome);
|
await min.conversationalService.sendText(min, step, Messages[locale].welcome);
|
||||||
|
|
||||||
return await min.conversationalService.prompt(min, step, Messages[locale].which_task);
|
return await min.conversationalService.prompt(min, step, Messages[locale].which_task);
|
||||||
|
@ -292,6 +293,8 @@ class AdminDialog extends IGBDialog {
|
||||||
await min.conversationalService.sendText(min, step, `Starting publishing for ${botId} packages...`);
|
await min.conversationalService.sendText(min, step, `Starting publishing for ${botId} packages...`);
|
||||||
packages.push(`${botId}.gbot`);
|
packages.push(`${botId}.gbot`);
|
||||||
packages.push(`${botId}.gbtheme`);
|
packages.push(`${botId}.gbtheme`);
|
||||||
|
packages.push(`${botId}.gbdrive`);
|
||||||
|
packages.push(`${botId}.gbdata`);
|
||||||
packages.push(`${botId}.gbkb`);
|
packages.push(`${botId}.gbkb`);
|
||||||
packages.push(`${botId}.gbdialog`);
|
packages.push(`${botId}.gbdialog`);
|
||||||
skipError = true;
|
skipError = true;
|
||||||
|
@ -304,6 +307,8 @@ class AdminDialog extends IGBDialog {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
packageName.toLowerCase() === 'gbdialog' ||
|
packageName.toLowerCase() === 'gbdialog' ||
|
||||||
|
packageName.toLowerCase() === 'gbdrive' ||
|
||||||
|
packageName.toLowerCase() === 'gbdata' ||
|
||||||
packageName.toLowerCase() === 'gbkb' ||
|
packageName.toLowerCase() === 'gbkb' ||
|
||||||
packageName.toLowerCase() === 'gbot' ||
|
packageName.toLowerCase() === 'gbot' ||
|
||||||
packageName.toLowerCase() === 'gbtheme'
|
packageName.toLowerCase() === 'gbtheme'
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -168,7 +168,7 @@ export class GBAdminService implements IGBAdminService {
|
||||||
) {
|
) {
|
||||||
const packageName = text.split(' ')[1];
|
const packageName = text.split(' ')[1];
|
||||||
|
|
||||||
const folderName = text.split(' ')[2];
|
const folderName = text.substring(text.indexOf(packageName) + packageName.length + 1);
|
||||||
const packageType = path.extname(folderName).substr(1);
|
const packageType = path.extname(folderName).substr(1);
|
||||||
const gbaiPath = GBUtil.getGBAIPath(min.instance.botId, packageType, null);
|
const gbaiPath = GBUtil.getGBAIPath(min.instance.botId, packageType, null);
|
||||||
const localFolder = path.join('work', gbaiPath);
|
const localFolder = path.join('work', gbaiPath);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
export const Messages = {
|
export const Messages = {
|
||||||
'en-US': {
|
'en-US': {
|
||||||
authenticate: 'Please, authenticate:',
|
authenticate: 'Please, authenticate:',
|
||||||
welcome: 'Welcome to pragmatismo.cloud GeneralBots Administration.',
|
welcome: 'Welcome to pragmatismo.com.br GeneralBots Administration.',
|
||||||
which_task: 'Which task do you wanna run now?',
|
which_task: 'Which task do you wanna run now?',
|
||||||
working: command => `I'm working on ${command}...`,
|
working: command => `I'm working on ${command}...`,
|
||||||
finished_working: 'Done.',
|
finished_working: 'Done.',
|
||||||
|
@ -26,7 +26,7 @@ export const Messages = {
|
||||||
},
|
},
|
||||||
'pt-BR': {
|
'pt-BR': {
|
||||||
authenticate: 'Please, authenticate:',
|
authenticate: 'Please, authenticate:',
|
||||||
welcome: 'Welcome to pragmatismo.cloud GeneralBots Administration.',
|
welcome: 'Welcome to pragmatismo.com.br GeneralBots Administration.',
|
||||||
which_task: 'Which task do you wanna run now?',
|
which_task: 'Which task do you wanna run now?',
|
||||||
working: command => `I'm working on ${command}...`,
|
working: command => `I'm working on ${command}...`,
|
||||||
finished_working: 'Done.',
|
finished_working: 'Done.',
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -111,7 +111,7 @@ export class StartDialog {
|
||||||
instance.cloudLocation = location;
|
instance.cloudLocation = location;
|
||||||
instance.marketplaceId = appId;
|
instance.marketplaceId = appId;
|
||||||
instance.marketplacePassword = appPassword;
|
instance.marketplacePassword = appPassword;
|
||||||
instance.adminPass = GBAdminService.getRndPassword();
|
instance.adminPass = await GBUtil.hashPassword(GBAdminService.getRndPassword());
|
||||||
|
|
||||||
return { instance, credentials, subscriptionId , installationDeployer};
|
return { instance, credentials, subscriptionId , installationDeployer};
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -518,7 +518,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
instance.nlpAuthoringKey = authoringKey;
|
instance.nlpAuthoringKey = authoringKey;
|
||||||
instance.marketplaceId = appId;
|
instance.marketplaceId = appId;
|
||||||
instance.marketplacePassword = appPassword;
|
instance.marketplacePassword = appPassword;
|
||||||
instance.adminPass = GBAdminService.getRndPassword();
|
instance.adminPass = await GBUtil.hashPassword(GBAdminService.getRndPassword());
|
||||||
|
|
||||||
const credentials = await GBAdminService.getADALCredentialsFromUsername(username, password);
|
const credentials = await GBAdminService.getADALCredentialsFromUsername(username, password);
|
||||||
// tslint:disable-next-line:no-http-string
|
// tslint:disable-next-line:no-http-string
|
||||||
|
@ -986,7 +986,6 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
appSettings: [
|
appSettings: [
|
||||||
{ name: 'WEBSITES_CONTAINER_START_TIME_LIMIT', value: `${WebSiteResponseTimeout}` },
|
{ name: 'WEBSITES_CONTAINER_START_TIME_LIMIT', value: `${WebSiteResponseTimeout}` },
|
||||||
{ name: 'WEBSITE_NODE_DEFAULT_VERSION', value: await GBAdminService.getNodeVersion() },
|
{ name: 'WEBSITE_NODE_DEFAULT_VERSION', value: await GBAdminService.getNodeVersion() },
|
||||||
{ name: 'ADMIN_PASS', value: `${instance.adminPass}` },
|
|
||||||
{ name: 'BOT_ID', value: `${instance.botId}` },
|
{ name: 'BOT_ID', value: `${instance.botId}` },
|
||||||
{ name: 'CLOUD_SUBSCRIPTIONID', value: `${instance.cloudSubscriptionId}` },
|
{ name: 'CLOUD_SUBSCRIPTIONID', value: `${instance.cloudSubscriptionId}` },
|
||||||
{ name: 'CLOUD_LOCATION', value: `${instance.cloudLocation}` },
|
{ name: 'CLOUD_LOCATION', value: `${instance.cloudLocation}` },
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -30,7 +30,6 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import sgMail from '@sendgrid/mail';
|
|
||||||
import { ActivityTypes } from 'botbuilder';
|
import { ActivityTypes } from 'botbuilder';
|
||||||
import { GBLog, GBMinInstance } from 'botlib';
|
import { GBLog, GBMinInstance } from 'botlib';
|
||||||
import * as df from 'date-diff';
|
import * as df from 'date-diff';
|
||||||
|
@ -43,7 +42,7 @@ import mime from 'mime-types';
|
||||||
import tesseract from 'node-tesseract-ocr';
|
import tesseract from 'node-tesseract-ocr';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
import puppeteer from 'puppeteer';
|
import puppeteer, { executablePath } from 'puppeteer';
|
||||||
import qrcode from 'qrcode';
|
import qrcode from 'qrcode';
|
||||||
import urlJoin from 'url-join';
|
import urlJoin from 'url-join';
|
||||||
import pkg from 'whatsapp-web.js';
|
import pkg from 'whatsapp-web.js';
|
||||||
|
@ -61,6 +60,8 @@ import { ChartServices } from './ChartServices.js';
|
||||||
import { GBVMService } from './GBVMService.js';
|
import { GBVMService } from './GBVMService.js';
|
||||||
import { SystemKeywords } from './SystemKeywords.js';
|
import { SystemKeywords } from './SystemKeywords.js';
|
||||||
import { WebAutomationServices } from './WebAutomationServices.js';
|
import { WebAutomationServices } from './WebAutomationServices.js';
|
||||||
|
import { Client } from 'minio';
|
||||||
|
import nodemailer from 'nodemailer';
|
||||||
const { List, Buttons } = pkg;
|
const { List, Buttons } = pkg;
|
||||||
|
|
||||||
|
|
||||||
|
@ -93,7 +94,11 @@ export class DialogKeywords {
|
||||||
|
|
||||||
// Launch Puppeteer to render the chart
|
// Launch Puppeteer to render the chart
|
||||||
|
|
||||||
const browser = await puppeteer.launch();
|
const browser = await puppeteer.launch({
|
||||||
|
headless: process.env.CHROME_HEADLESS === 'true',
|
||||||
|
executablePath: process.env.CHROME_PATH ? process.env.CHROME_PATH : executablePath(),
|
||||||
|
}
|
||||||
|
);
|
||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
|
|
||||||
// Load Billboard.js styles and scripts
|
// Load Billboard.js styles and scripts
|
||||||
|
@ -573,7 +578,6 @@ export class DialogKeywords {
|
||||||
// tslint:disable-next-line:no-console
|
// tslint:disable-next-line:no-console
|
||||||
|
|
||||||
GBLogEx.info(min, `[E-mail]: to:${to},subject: ${subject},body: ${body}.`);
|
GBLogEx.info(min, `[E-mail]: to:${to},subject: ${subject},body: ${body}.`);
|
||||||
const emailToken = process.env.EMAIL_API_KEY;
|
|
||||||
|
|
||||||
// Inline word document used as e-mail body.
|
// Inline word document used as e-mail body.
|
||||||
|
|
||||||
|
@ -582,24 +586,36 @@ export class DialogKeywords {
|
||||||
body = result.value;
|
body = result.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (emailToken) {
|
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
||||||
return new Promise<any>((resolve, reject) => {
|
|
||||||
sgMail.setApiKey(emailToken);
|
const transporter = nodemailer.createTransport({
|
||||||
const msg = {
|
host: process.env.EMAIL_SERVER || 'localhost',
|
||||||
to: to,
|
port: parseInt(process.env.EMAIL_PORT || '587', 10),
|
||||||
|
secure: false,
|
||||||
|
auth: {
|
||||||
|
user: process.env.EMAIL_USER ,
|
||||||
|
pass: process.env.EMAIL_PASS ,
|
||||||
|
},
|
||||||
|
tls: {
|
||||||
|
rejectUnauthorized: (process.env.EMAIL_REJECT_UNAUTHORIZED === 'true'),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const mailOptions = {
|
||||||
from: process.env.EMAIL_FROM,
|
from: process.env.EMAIL_FROM,
|
||||||
|
to: to,
|
||||||
subject: subject,
|
subject: subject,
|
||||||
text: body,
|
text: body,
|
||||||
html: body
|
html: body,
|
||||||
|
// headers: {
|
||||||
|
// 'List-Unsubscribe': `<mailto:${config.unsubscribeEmail}?subject=Unsubscribe>`,
|
||||||
|
// 'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click'
|
||||||
|
// }
|
||||||
};
|
};
|
||||||
sgMail.send(msg, false, (err, res) => {
|
|
||||||
if (err) {
|
await transporter.sendMail(mailOptions);
|
||||||
reject(err);
|
GBLogEx.info(min, `E-mail ${to} (${subject}) sent via NodeMailer.`);
|
||||||
} else {
|
|
||||||
resolve(res);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
let { client } = await GBDeployer.internalGetDriveClient(min);
|
let { client } = await GBDeployer.internalGetDriveClient(min);
|
||||||
|
|
||||||
|
@ -710,7 +726,8 @@ export class DialogKeywords {
|
||||||
|
|
||||||
// Checks access.
|
// Checks access.
|
||||||
|
|
||||||
const filters = ['People.xlsx', `${role}=x`, `id=${user.userSystemId}`];
|
const file = process.env.GB_MODE === 'legacy' ? 'People.xlsx' : 'people.csv';
|
||||||
|
const filters = [file, `${role}=x`, `id=${user.userSystemId}`];
|
||||||
const people = await sys.find({ pid, handle: null, args: filters });
|
const people = await sys.find({ pid, handle: null, args: filters });
|
||||||
|
|
||||||
if (!people) {
|
if (!people) {
|
||||||
|
@ -1087,7 +1104,7 @@ export class DialogKeywords {
|
||||||
// In case of unmatch, asks the person to try again.
|
// In case of unmatch, asks the person to try again.
|
||||||
|
|
||||||
if (result === null) {
|
if (result === null) {
|
||||||
await this.talk({ pid, text: `Escolha por favor um dos itens sugeridos.` });
|
await this.talk({ pid, text: `Digite por favor um dos itens sugeridos ou uma parte do texto.` });
|
||||||
return await this.hear({ pid, kind, args });
|
return await this.hear({ pid, kind, args });
|
||||||
}
|
}
|
||||||
} else if (kind === 'file') {
|
} else if (kind === 'file') {
|
||||||
|
@ -1495,7 +1512,7 @@ export class DialogKeywords {
|
||||||
else {
|
else {
|
||||||
|
|
||||||
|
|
||||||
if (GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
|
|
||||||
const ext = path.extname(filename);
|
const ext = path.extname(filename);
|
||||||
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
||||||
|
@ -1520,17 +1537,52 @@ export class DialogKeywords {
|
||||||
'cache',
|
'cache',
|
||||||
`${fileOnly.replace(/\s/gi, '')}-${GBAdminService.getNumberIdentifier()}.${ext}`
|
`${fileOnly.replace(/\s/gi, '')}-${GBAdminService.getNumberIdentifier()}.${ext}`
|
||||||
);
|
);
|
||||||
await fs.writeFile(localName, buf, { encoding: null });
|
await fs.writeFile(localName, new Uint8Array(buf), { encoding: null });
|
||||||
|
|
||||||
url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
||||||
|
} else if (GBConfigService.get('GB_MODE') === 'gbcluster') {
|
||||||
|
|
||||||
|
|
||||||
|
const ext = path.extname(filename);
|
||||||
|
|
||||||
|
|
||||||
|
const fileUrl = urlJoin('/', `${min.botId}.gbdrive`, filename);
|
||||||
|
GBLogEx.info(min, `Direct send from .gbdrive: ${fileUrl} to ${mobile}.`);
|
||||||
|
|
||||||
|
const fileOnly = fileUrl.substring(fileUrl.lastIndexOf('/') + 1);
|
||||||
|
|
||||||
|
const minioClient = new Client({
|
||||||
|
endPoint: process.env.DRIVE_SERVER || 'localhost',
|
||||||
|
port: parseInt(process.env.DRIVE_PORT || '9000', 10),
|
||||||
|
useSSL: process.env.DRIVE_USE_SSL === 'true',
|
||||||
|
accessKey: process.env.DRIVE_ACCESSKEY,
|
||||||
|
secretKey: process.env.DRIVE_SECRET,
|
||||||
|
});
|
||||||
|
|
||||||
|
const bucketName = (process.env.DRIVE_ORG_PREFIX + min.botId + '.gbai').toLowerCase();
|
||||||
|
localName = path.join(
|
||||||
|
'work',
|
||||||
|
gbaiName,
|
||||||
|
'cache',
|
||||||
|
`${GBAdminService.getNumberIdentifier()}-${fileOnly}`
|
||||||
|
);
|
||||||
|
|
||||||
|
await minioClient.fGetObject(bucketName, fileUrl, localName);
|
||||||
|
|
||||||
|
|
||||||
|
url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
||||||
|
GBLogEx.info(min, `Exposing ${localName} to ${url}...`);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
else {
|
else {
|
||||||
const gbdriveName = GBUtil.getGBAIPath(min.botId, 'gbdrive');
|
const gbdriveName = GBUtil.getGBAIPath(min.botId, 'gbdrive');
|
||||||
localName = path.join(GBConfigService.get('STORAGE_LIBRARY'), gbdriveName, filename);
|
localName = path.join(GBConfigService.get('STORAGE_LIBRARY'), gbdriveName, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (localName.endsWith('.pdf')) {
|
if (localName.endsWith('.image.pdf')) {
|
||||||
|
GBLogEx.info(min, `Converting PDF to images...`);
|
||||||
const pngs = await GBUtil.pdfPageAsImage(min, localName, undefined);
|
const pngs = await GBUtil.pdfPageAsImage(min, localName, undefined);
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(pngs, async png => {
|
await CollectionUtil.asyncForEach(pngs, async png => {
|
||||||
|
@ -1548,8 +1600,11 @@ export class DialogKeywords {
|
||||||
contentUrl: url
|
contentUrl: url
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!isNaN(mobile)) {
|
if (!isNaN(mobile)) {
|
||||||
await min.whatsAppDirectLine.sendFileToDevice(mobile, url, filename, caption, undefined, true);
|
await min.whatsAppDirectLine.sendFileToDevice(mobile, url, filename, caption, undefined, true, true);
|
||||||
} else {
|
} else {
|
||||||
await min.conversationalService['sendOnConversation'](min, user, reply);
|
await min.conversationalService['sendOnConversation'](min, user, reply);
|
||||||
}
|
}
|
||||||
|
@ -1568,8 +1623,10 @@ export class DialogKeywords {
|
||||||
const buf = await fs.readFile(filename);
|
const buf = await fs.readFile(filename);
|
||||||
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
||||||
const localName = path.join('work', gbaiName, 'cache', `tmp${GBAdminService.getRndReadableIdentifier()}.${ext}`);
|
const localName = path.join('work', gbaiName, 'cache', `tmp${GBAdminService.getRndReadableIdentifier()}.${ext}`);
|
||||||
await fs.writeFile(localName, buf, { encoding: null });
|
|
||||||
url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
||||||
|
|
||||||
|
|
||||||
|
await fs.writeFile(localName, new Uint8Array(buf), { encoding: null });
|
||||||
}
|
}
|
||||||
|
|
||||||
const contentType = mime.lookup(url);
|
const contentType = mime.lookup(url);
|
||||||
|
@ -1581,8 +1638,8 @@ export class DialogKeywords {
|
||||||
contentUrl: url
|
contentUrl: url
|
||||||
});
|
});
|
||||||
|
|
||||||
if (channel === 'omnichannel' || !user) {
|
if (!isNaN(mobile)) {
|
||||||
await min.conversationalService.sendFile(min, null, mobile, url, caption);
|
await min.whatsAppDirectLine.sendFileToDevice(mobile, url, filename, caption, undefined, false);
|
||||||
} else {
|
} else {
|
||||||
await min.conversationalService['sendOnConversation'](min, user, reply);
|
await min.conversationalService['sendOnConversation'](min, user, reply);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -39,6 +39,7 @@ import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
import { ScheduleServices } from './ScheduleServices.js';
|
import { ScheduleServices } from './ScheduleServices.js';
|
||||||
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
|
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
|
||||||
import urlJoin from 'url-join';
|
import urlJoin from 'url-join';
|
||||||
|
import { PostgresDialect } from '@sequelize/postgres';
|
||||||
import { NodeVM, VMScript } from 'vm2';
|
import { NodeVM, VMScript } from 'vm2';
|
||||||
import { createVm2Pool } from './vm2-process/index.js';
|
import { createVm2Pool } from './vm2-process/index.js';
|
||||||
import { watch } from 'fs';
|
import { watch } from 'fs';
|
||||||
|
@ -149,7 +150,7 @@ export class GBVMService extends GBService {
|
||||||
let mainName = GBVMService.getMethodNameFromVBSFilename(filename);
|
let mainName = GBVMService.getMethodNameFromVBSFilename(filename);
|
||||||
min.scriptMap[filename] = mainName;
|
min.scriptMap[filename] = mainName;
|
||||||
|
|
||||||
if (writeVBS && GBConfigService.get('STORAGE_NAME')) {
|
if (writeVBS && GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
let text = await this.getTextFromWord(folder, wordFile);
|
let text = await this.getTextFromWord(folder, wordFile);
|
||||||
|
|
||||||
// Write VBS file without pragma keywords.
|
// Write VBS file without pragma keywords.
|
||||||
|
@ -204,7 +205,7 @@ export class GBVMService extends GBService {
|
||||||
"author": "${min.botId} owner.",
|
"author": "${min.botId} owner.",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"yaml": "2.4.2",
|
|
||||||
"encoding": "0.1.13",
|
"encoding": "0.1.13",
|
||||||
"isomorphic-fetch": "3.0.0",
|
"isomorphic-fetch": "3.0.0",
|
||||||
"punycode": "2.1.1",
|
"punycode": "2.1.1",
|
||||||
|
@ -250,7 +251,97 @@ export class GBVMService extends GBService {
|
||||||
|
|
||||||
const encrypt: boolean = GBConfigService.get('STORAGE_ENCRYPT') === 'true';
|
const encrypt: boolean = GBConfigService.get('STORAGE_ENCRYPT') === 'true';
|
||||||
const acquire = parseInt(GBConfigService.get('STORAGE_ACQUIRE_TIMEOUT'));
|
const acquire = parseInt(GBConfigService.get('STORAGE_ACQUIRE_TIMEOUT'));
|
||||||
const sequelizeOptions = {
|
let sequelizeOptions;
|
||||||
|
|
||||||
|
|
||||||
|
// Simple function to convert all object keys to lowercase
|
||||||
|
const toLowerCase = (obj) => {
|
||||||
|
if (!obj) return obj;
|
||||||
|
if (typeof obj !== 'object') return obj;
|
||||||
|
|
||||||
|
return Object.keys(obj).reduce((acc, key) => {
|
||||||
|
acc[key.toLowerCase()] = obj[key];
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dialect === 'postgres') {
|
||||||
|
|
||||||
|
sequelizeOptions = {
|
||||||
|
host: host,
|
||||||
|
port: port,
|
||||||
|
logging: logging as boolean,
|
||||||
|
dialect: dialect,
|
||||||
|
dialectOptions: {
|
||||||
|
ssl: false,
|
||||||
|
application_name: 'General Bots',
|
||||||
|
connectTimeout: 10000,
|
||||||
|
query_timeout: 10000,
|
||||||
|
statement_timeout: 10000,
|
||||||
|
idle_in_transaction_session_timeout: 10000,
|
||||||
|
|
||||||
|
},
|
||||||
|
pool: {
|
||||||
|
max: 1,
|
||||||
|
min: 0,
|
||||||
|
idle: 10000,
|
||||||
|
evict: 10000,
|
||||||
|
acquire: acquire
|
||||||
|
},
|
||||||
|
define: {
|
||||||
|
// Disable timestamps globally
|
||||||
|
timestamps: false,
|
||||||
|
// Prevent createdAt/updatedAt from being selected
|
||||||
|
defaultScope: {
|
||||||
|
attributes: {
|
||||||
|
exclude: ['createdAt', 'updatedAt']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Convert all table names to lowercase
|
||||||
|
freezeTableName: true,
|
||||||
|
hooks: {
|
||||||
|
beforeSave: (options) => {
|
||||||
|
if (options.where) {
|
||||||
|
options.where = toLowerCase(options.where);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeDestroy: (options) => {
|
||||||
|
if (options.where) {
|
||||||
|
options.where = toLowerCase(options.where);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeFind: (options) => {
|
||||||
|
if (options.where) {
|
||||||
|
options.where = toLowerCase(options.where);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeDefine: (attributes, options) => {
|
||||||
|
// Convert model name and table name to lowercase
|
||||||
|
if (options.modelName) {
|
||||||
|
options.modelName = options.modelName.toLowerCase();
|
||||||
|
}
|
||||||
|
if (options.tableName) {
|
||||||
|
options.tableName = options.tableName.toLowerCase();
|
||||||
|
} else {
|
||||||
|
options.tableName = options.modelName.toLowerCase();
|
||||||
|
} for (const attr in attributes) {
|
||||||
|
const lowered = attr.toLowerCase();
|
||||||
|
if (attr !== lowered) {
|
||||||
|
attributes[lowered] = attributes[attr];
|
||||||
|
delete attributes[attr];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
sequelizeOptions = {
|
||||||
define: {
|
define: {
|
||||||
charset: 'utf8',
|
charset: 'utf8',
|
||||||
collate: 'utf8_general_ci',
|
collate: 'utf8_general_ci',
|
||||||
|
@ -270,16 +361,17 @@ export class GBVMService extends GBService {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
pool: {
|
pool: {
|
||||||
max: 5,
|
max: 1,
|
||||||
min: 0,
|
min: 0,
|
||||||
idle: 10000,
|
idle: 10000,
|
||||||
evict: 10000,
|
evict: 10000,
|
||||||
acquire: acquire
|
acquire: acquire
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (!min[connectionName]) {
|
if (!min[connectionName]) {
|
||||||
GBLogEx.info(min, `Loading data connection ${connectionName}...`);
|
GBLogEx.info(min, `Loading data connection ${connectionName} (${dialect})...`);
|
||||||
min[connectionName] = new Sequelize(storageName, username, password, sequelizeOptions);
|
min[connectionName] = new Sequelize(storageName, username, password, sequelizeOptions);
|
||||||
min[connectionName]['gbconnection'] = con;
|
min[connectionName]['gbconnection'] = con;
|
||||||
}
|
}
|
||||||
|
@ -717,7 +809,13 @@ export class GBVMService extends GBService {
|
||||||
|
|
||||||
if (!table && !talk && !systemPrompt) {
|
if (!table && !talk && !systemPrompt) {
|
||||||
for (let j = 0; j < keywords.length; j++) {
|
for (let j = 0; j < keywords.length; j++) {
|
||||||
line = line.replace(keywords[j][0], keywords[j][1]); // TODO: Investigate delay here.
|
const oldLine = line;
|
||||||
|
line = line.replace(keywords[j][0], keywords[j][1]);
|
||||||
|
|
||||||
|
if(line != oldLine){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -936,7 +1034,7 @@ export class GBVMService extends GBService {
|
||||||
let result;
|
let result;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!GBConfigService.get('GBVM')) {
|
if (GBConfigService.get('GBVM') !== false) {
|
||||||
return await (async () => {
|
return await (async () => {
|
||||||
return await new Promise((resolve) => {
|
return await new Promise((resolve) => {
|
||||||
sandbox['resolve'] = resolve;
|
sandbox['resolve'] = resolve;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -128,12 +128,13 @@ export class ImageProcessingServices {
|
||||||
// Make a request to the image generation endpoint
|
// Make a request to the image generation endpoint
|
||||||
|
|
||||||
const response = await client.images.generate({
|
const response = await client.images.generate({
|
||||||
model: '',
|
|
||||||
prompt: prompt,
|
|
||||||
n: 1,
|
|
||||||
size: '1024x1024'
|
|
||||||
});
|
|
||||||
|
|
||||||
|
prompt: prompt,
|
||||||
|
n: 1, // Don't include for DALL-E 3 (always generates 1 image)
|
||||||
|
style: 'vivid', // optional ('natural' or 'vivid')
|
||||||
|
size: '1024x1024',
|
||||||
|
quality: 'standard', // optional
|
||||||
|
});
|
||||||
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
||||||
const localName = path.join('work', gbaiName, 'cache', `DALL-E${GBAdminService.getRndReadableIdentifier()}.png`);
|
const localName = path.join('work', gbaiName, 'cache', `DALL-E${GBAdminService.getRndReadableIdentifier()}.png`);
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -522,6 +522,14 @@ export class KeywordsExpressions {
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
keywords[i++] = [
|
||||||
|
/^\s*(LOG)(\s*)(.*)/gim,
|
||||||
|
($0, $1, $2, $3) => {
|
||||||
|
const params = this.getParams($3, ['obj']);
|
||||||
|
return `await sys.log ({pid: pid, ${params}})`;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
keywords[i++] = [
|
keywords[i++] = [
|
||||||
/^\s*(.*)\=\s*(DIR)(\s*)(.*)/gim,
|
/^\s*(.*)\=\s*(DIR)(\s*)(.*)/gim,
|
||||||
($0, $1, $2, $3, $4) => {
|
($0, $1, $2, $3, $4) => {
|
||||||
|
@ -572,6 +580,14 @@ export class KeywordsExpressions {
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
keywords[i++] = [
|
||||||
|
/^\s*hear (\w+\$*) as\s*number/gim,
|
||||||
|
($0, $1) => {
|
||||||
|
return `${$1} = await dk.hear({pid: pid, kind:"integer"})`;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
keywords[i++] = [
|
keywords[i++] = [
|
||||||
/^\s*hear (\w+\$*) as\s*integer/gim,
|
/^\s*hear (\w+\$*) as\s*integer/gim,
|
||||||
($0, $1) => {
|
($0, $1) => {
|
||||||
|
@ -906,6 +922,15 @@ export class KeywordsExpressions {
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
keywords[i++] = [
|
||||||
|
/^\s*(POST TO INSTAGRAM)(\s*)(.*)/gim,
|
||||||
|
($0, $1, $2, $3) => {
|
||||||
|
const params = this.getParams($3, ['username', 'password', 'imagePath', 'caption']);
|
||||||
|
return `await sys.postToInstagram ({pid: pid, ${params}})`;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
keywords[i++] = [
|
keywords[i++] = [
|
||||||
/^\s*((?:[a-z]+.?)(?:(?:\w+).)(?:\w+)*)\s*=\s*(datediff)(\s*)(.*)/gim,
|
/^\s*((?:[a-z]+.?)(?:(?:\w+).)(?:\w+)*)\s*=\s*(datediff)(\s*)(.*)/gim,
|
||||||
($0, $1, $2, $3, $4) => {
|
($0, $1, $2, $3, $4) => {
|
||||||
|
@ -1287,7 +1312,7 @@ export class KeywordsExpressions {
|
||||||
keywords[i++] = [
|
keywords[i++] = [
|
||||||
/^\s*((?:[a-z]+.?)(?:(?:\w+).)(?:\w+)*)\s*=\s*(.*)\s*as\s*pdf/gim,
|
/^\s*((?:[a-z]+.?)(?:(?:\w+).)(?:\w+)*)\s*=\s*(.*)\s*as\s*pdf/gim,
|
||||||
($0, $1, $2) => {
|
($0, $1, $2) => {
|
||||||
return `${$1} = await sys.asPdf({pid: pid, data: ${$2})`;
|
return `${$1} = await sys.asPdf({pid: pid, data: ${$2}})`;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1299,13 +1324,13 @@ export class KeywordsExpressions {
|
||||||
];
|
];
|
||||||
|
|
||||||
keywords[i++] = [
|
keywords[i++] = [
|
||||||
/^\s*(save)(\s*)(.*\.xlsx)(.*)/gim,
|
/^\s*(save)(\s*)(.*\.(xlsx|csv))(.*)/gim,
|
||||||
($0, $1, $2, $3, $4) => {
|
($0, $1, $2, $3, $4, $5) => {
|
||||||
$3 = $3.replace(/\'/g, '');
|
$3 = $3.replace(/\'/g, '');
|
||||||
$3 = $3.replace(/\"/g, '');
|
$3 = $3.replace(/\"/g, '');
|
||||||
$3 = $3.replace(/\`/g, '');
|
$3 = $3.replace(/\`/g, '');
|
||||||
$4 = $4.substr(2);
|
$5 = $5.substr(2);
|
||||||
return `await sys.save({pid: pid, file: "${$3}", args: [${$4}]})`;
|
return `await sys.save({pid: pid, file: "${$3}", args: [${$5}]})`;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -29,49 +29,53 @@
|
||||||
\*****************************************************************************/
|
\*****************************************************************************/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { setFlagsFromString } from 'v8';
|
|
||||||
import { runInNewContext } from 'vm';
|
|
||||||
import { IgApiClient } from 'instagram-private-api';
|
|
||||||
import { readFile } from 'fs';
|
|
||||||
import ai2html from 'ai2html';
|
|
||||||
import path, { resolve } from 'path';
|
|
||||||
import { GBLog, GBMinInstance } from 'botlib';
|
|
||||||
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
|
|
||||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
|
||||||
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js';
|
|
||||||
import { GBDeployer } from '../../core.gbapp/services/GBDeployer.js';
|
|
||||||
import { DialogKeywords } from './DialogKeywords.js';
|
|
||||||
import { GBServer } from '../../../src/app.js';
|
|
||||||
import { GBVMService } from './GBVMService.js';
|
|
||||||
import fs from 'fs/promises';
|
|
||||||
import { GBSSR } from '../../core.gbapp/services/GBSSR.js';
|
|
||||||
import urlJoin from 'url-join';
|
|
||||||
import Excel from 'exceljs';
|
|
||||||
import { BufferWindowMemory } from 'langchain/memory';
|
|
||||||
import csvdb from 'csv-database';
|
|
||||||
import { Sequelize, QueryTypes, DataTypes } from '@sequelize/core';
|
|
||||||
import packagePath from 'path';
|
|
||||||
import ComputerVisionClient from '@azure/cognitiveservices-computervision';
|
import ComputerVisionClient from '@azure/cognitiveservices-computervision';
|
||||||
import ApiKeyCredentials from '@azure/ms-rest-js';
|
import ApiKeyCredentials from '@azure/ms-rest-js';
|
||||||
import alasql from 'alasql';
|
|
||||||
import PizZip from 'pizzip';
|
|
||||||
import Docxtemplater from 'docxtemplater';
|
|
||||||
import pptxTemplaterModule from 'pptxtemplater';
|
|
||||||
import _ from 'lodash';
|
|
||||||
import { pdfToPng, PngPageOutput } from 'pdf-to-png-converter';
|
|
||||||
import ImageModule from 'open-docxtemplater-image-module';
|
|
||||||
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService.js';
|
|
||||||
import { WebAutomationServices } from './WebAutomationServices.js';
|
|
||||||
import { KeywordsExpressions } from './KeywordsExpressions.js';
|
|
||||||
import { ChatServices } from '../../llm.gblib/services/ChatServices.js';
|
|
||||||
import mime from 'mime-types';
|
|
||||||
import { SecService } from '../../security.gbapp/services/SecService.js';
|
|
||||||
import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
|
|
||||||
import retry from 'async-retry';
|
|
||||||
import { BlobServiceClient, BlockBlobClient, StorageSharedKeyCredential } from '@azure/storage-blob';
|
import { BlobServiceClient, BlockBlobClient, StorageSharedKeyCredential } from '@azure/storage-blob';
|
||||||
|
import { DataTypes, Sequelize } from '@sequelize/core';
|
||||||
|
import ai2html from 'ai2html';
|
||||||
|
import alasql from 'alasql';
|
||||||
|
import retry from 'async-retry';
|
||||||
|
import { GBLog } from 'botlib';
|
||||||
|
import csvdb from 'csv-database';
|
||||||
|
import Docxtemplater from 'docxtemplater';
|
||||||
|
import Excel from 'exceljs';
|
||||||
import { Page } from 'facebook-nodejs-business-sdk';
|
import { Page } from 'facebook-nodejs-business-sdk';
|
||||||
|
import fs from 'fs/promises';
|
||||||
|
import { IgApiClient } from 'instagram-private-api';
|
||||||
|
import { BufferWindowMemory } from 'langchain/memory';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import mime from 'mime-types';
|
||||||
|
import ImageModule from 'open-docxtemplater-image-module';
|
||||||
|
import path from 'path';
|
||||||
|
import { pdfToPng, PngPageOutput } from 'pdf-to-png-converter';
|
||||||
|
import PizZip from 'pizzip';
|
||||||
|
import pptxTemplaterModule from 'pptxtemplater';
|
||||||
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
|
import urlJoin from 'url-join';
|
||||||
|
import { setFlagsFromString } from 'v8';
|
||||||
|
import { runInNewContext } from 'vm';
|
||||||
|
import { GBServer } from '../../../src/app.js';
|
||||||
|
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js';
|
||||||
|
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
|
||||||
|
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService.js';
|
||||||
|
import { GBDeployer } from '../../core.gbapp/services/GBDeployer.js';
|
||||||
|
import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
|
||||||
|
import { GBSSR } from '../../core.gbapp/services/GBSSR.js';
|
||||||
|
import { ChatServices } from '../../llm.gblib/services/ChatServices.js';
|
||||||
|
import { SecService } from '../../security.gbapp/services/SecService.js';
|
||||||
|
import { DialogKeywords } from './DialogKeywords.js';
|
||||||
|
import { GBVMService } from './GBVMService.js';
|
||||||
|
import { KeywordsExpressions } from './KeywordsExpressions.js';
|
||||||
|
import { WebAutomationServices } from './WebAutomationServices.js';
|
||||||
|
import { exec } from 'child_process';
|
||||||
|
import util from 'util';
|
||||||
|
|
||||||
|
// Promisify the exec function for async/await usage
|
||||||
|
const execPromise = util.promisify(exec);
|
||||||
|
|
||||||
import { md5 } from 'js-md5';
|
import { md5 } from 'js-md5';
|
||||||
|
import { Client } from 'minio';
|
||||||
import { GBUtil } from '../../../src/util.js';
|
import { GBUtil } from '../../../src/util.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -362,8 +366,42 @@ export class SystemKeywords {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async asPDF({ pid, data }) {
|
private async convertWithLibreOffice(pid, inputPath) {
|
||||||
let file = await this.renderTable(pid, data, true, false);
|
const { min } = await DialogKeywords.getProcessInfo(pid);
|
||||||
|
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
||||||
|
const localName = path.join('work', gbaiName, 'cache', `img${GBAdminService.getRndReadableIdentifier()}.pdf`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// LibreOffice command for conversion using localName as output
|
||||||
|
const command = `libreoffice --headless --convert-to pdf --outdir "${path.dirname(localName)}" "${inputPath}"`;
|
||||||
|
|
||||||
|
GBLogEx.info(min, `Executing: ${command}`);
|
||||||
|
const { stdout, stderr } = await execPromise(command);
|
||||||
|
|
||||||
|
if (stderr) {
|
||||||
|
GBLogEx.error(min, `LibreOffice stderr: ${stderr}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
GBLogEx.info(min, `LibreOffice stdout: ${stdout}`);
|
||||||
|
|
||||||
|
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
||||||
|
|
||||||
|
return { localName, url };
|
||||||
|
} catch (error) {
|
||||||
|
GBLogEx.error(min, `Error converting file to PDF: ${error}`);
|
||||||
|
throw new Error('PDF conversion failed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async asPdf({ pid, data }) {
|
||||||
|
let file;
|
||||||
|
|
||||||
|
if (data.url) {
|
||||||
|
file = await this.convertWithLibreOffice(pid, data.localName);
|
||||||
|
} else {
|
||||||
|
file = await this.renderTable(pid, data, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,7 +429,7 @@ export class SystemKeywords {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
stream.on('data', chunk => chunks.push(chunk));
|
stream.on('data', chunk => chunks.push(chunk));
|
||||||
stream.on('error', reject);
|
stream.on('error', reject);
|
||||||
stream.on('end', () => resolve(Buffer.concat(chunks)));
|
stream.on('end', () => resolve(Buffer.concat(chunks.map(chunk => new Uint8Array(chunk)))));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -415,7 +453,7 @@ export class SystemKeywords {
|
||||||
const buffer = pngPages[0].content;
|
const buffer = pngPages[0].content;
|
||||||
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
||||||
|
|
||||||
await fs.writeFile(localName, buffer, { encoding: null });
|
await fs.writeFile(localName, new Uint8Array(buffer), { encoding: null });
|
||||||
|
|
||||||
return { localName: localName, url: url, data: buffer };
|
return { localName: localName, url: url, data: buffer };
|
||||||
}
|
}
|
||||||
|
@ -708,7 +746,7 @@ export class SystemKeywords {
|
||||||
// Writes it to disk and calculate hash.
|
// Writes it to disk and calculate hash.
|
||||||
|
|
||||||
const data = await response.arrayBuffer();
|
const data = await response.arrayBuffer();
|
||||||
await fs.writeFile(localName, Buffer.from(data), { encoding: null });
|
await fs.writeFile(localName, new Uint8Array(Buffer.from(data)), { encoding: null });
|
||||||
const hash = new Uint8Array(md5.array(data));
|
const hash = new Uint8Array(md5.array(data));
|
||||||
|
|
||||||
// Performs uploading passing local hash.
|
// Performs uploading passing local hash.
|
||||||
|
@ -785,7 +823,7 @@ export class SystemKeywords {
|
||||||
const minRef = min;
|
const minRef = min;
|
||||||
|
|
||||||
await retry(
|
await retry(
|
||||||
async (bail) => {
|
async bail => {
|
||||||
const t = this.getTableFromName(tableName, minRef);
|
const t = this.getTableFromName(tableName, minRef);
|
||||||
try {
|
try {
|
||||||
await t.bulkCreate(rowsDest);
|
await t.bulkCreate(rowsDest);
|
||||||
|
@ -837,7 +875,13 @@ export class SystemKeywords {
|
||||||
/**
|
/**
|
||||||
* Saves the content of several variables to a new row in a tabular file.
|
* Saves the content of several variables to a new row in a tabular file.
|
||||||
*
|
*
|
||||||
* @example SAVE "customers.xlsx", name, email, phone, address, city, state, country
|
* @example SAVE "customers.csv", name, email, phone, address, city, state, country
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Saves the content of several variables to a new row in a tabular file.
|
||||||
|
*
|
||||||
|
* @example SAVE "customers.csv", id, name, email, phone
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public async save({ pid, file, args }): Promise<any> {
|
public async save({ pid, file, args }): Promise<any> {
|
||||||
|
@ -847,6 +891,89 @@ export class SystemKeywords {
|
||||||
|
|
||||||
const { min } = await DialogKeywords.getProcessInfo(pid);
|
const { min } = await DialogKeywords.getProcessInfo(pid);
|
||||||
GBLogEx.info(min, `Saving '${file}' (SAVE). Args: ${args.join(',')}.`);
|
GBLogEx.info(min, `Saving '${file}' (SAVE). Args: ${args.join(',')}.`);
|
||||||
|
|
||||||
|
// Handle gbcluster mode with Minio storage
|
||||||
|
if (GBConfigService.get('GB_MODE') === 'gbcluster') {
|
||||||
|
const fileUrl = urlJoin('/', `${min.botId}.gbdata`, file);
|
||||||
|
GBLogEx.info(min, `Direct data from .csv: ${fileUrl}.`);
|
||||||
|
|
||||||
|
const fileOnly = fileUrl.substring(fileUrl.lastIndexOf('/') + 1);
|
||||||
|
|
||||||
|
const minioClient = new Client({
|
||||||
|
endPoint: process.env.DRIVE_SERVER || 'localhost',
|
||||||
|
port: parseInt(process.env.DRIVE_PORT || '9000', 10),
|
||||||
|
useSSL: process.env.DRIVE_USE_SSL === 'true',
|
||||||
|
accessKey: process.env.DRIVE_ACCESSKEY,
|
||||||
|
secretKey: process.env.DRIVE_SECRET
|
||||||
|
});
|
||||||
|
|
||||||
|
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
||||||
|
const bucketName = (process.env.DRIVE_ORG_PREFIX + min.botId + '.gbai').toLowerCase();
|
||||||
|
const localName = path.join(
|
||||||
|
'work',
|
||||||
|
gbaiName,
|
||||||
|
'cache',
|
||||||
|
`${fileOnly.replace(/\s/gi, '')}-${GBAdminService.getNumberIdentifier()}.csv`
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Lock the file for editing
|
||||||
|
await this.lockFile(minioClient, bucketName, fileUrl);
|
||||||
|
|
||||||
|
// Download the file
|
||||||
|
await minioClient.fGetObject(bucketName, fileUrl, localName);
|
||||||
|
|
||||||
|
// Read the CSV file
|
||||||
|
let csvData = await fs.readFile(localName, 'utf8');
|
||||||
|
let rows = csvData.split('\n').filter(row => row.trim() !== '');
|
||||||
|
|
||||||
|
// Check if first column is ID
|
||||||
|
const headers = rows.length > 0 ? rows[0].split(',') : [];
|
||||||
|
const hasIdColumn = headers.length > 0 && headers[0].toLowerCase() === 'id';
|
||||||
|
|
||||||
|
// If ID exists in args[0] and we have an ID column, try to find and update the row
|
||||||
|
let rowUpdated = false;
|
||||||
|
if (hasIdColumn && args[0]) {
|
||||||
|
for (let i = 1; i < rows.length; i++) {
|
||||||
|
const rowValues = rows[i].split(',');
|
||||||
|
if (rowValues[0] === args[0]) {
|
||||||
|
// Update existing row
|
||||||
|
rows[i] = args.join(',');
|
||||||
|
rowUpdated = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no row was updated, add a new row
|
||||||
|
if (!rowUpdated) {
|
||||||
|
rows.push(args.join(','));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write back to the file
|
||||||
|
await fs.writeFile(localName, rows.join('\n'));
|
||||||
|
|
||||||
|
// Upload the updated file
|
||||||
|
await minioClient.fPutObject(bucketName, fileUrl, localName);
|
||||||
|
|
||||||
|
GBLogEx.info(min, `Successfully saved data to Minio storage: ${fileUrl}`);
|
||||||
|
} catch (error) {
|
||||||
|
GBLogEx.error(min, `Error saving to Minio storage: ${error.message}`);
|
||||||
|
throw error;
|
||||||
|
} finally {
|
||||||
|
// Ensure the file is unlocked
|
||||||
|
await this.unlockFile(minioClient, bucketName, fileUrl);
|
||||||
|
// Clean up the local file
|
||||||
|
try {
|
||||||
|
await fs.unlink(localName);
|
||||||
|
} catch (cleanupError) {
|
||||||
|
GBLogEx.info(min, `Could not clean up local file: ${cleanupError.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Original legacy mode handling
|
||||||
let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
||||||
const botId = min.instance.botId;
|
const botId = min.instance.botId;
|
||||||
const packagePath = GBUtil.getGBAIPath(botId, 'gbdata');
|
const packagePath = GBUtil.getGBAIPath(botId, 'gbdata');
|
||||||
|
@ -859,13 +986,11 @@ export class SystemKeywords {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.cause === 404) {
|
if (e.cause === 404) {
|
||||||
// Creates the file.
|
// Creates the file.
|
||||||
|
|
||||||
const blank = path.join(process.env.PWD, 'blank.xlsx');
|
const blank = path.join(process.env.PWD, 'blank.xlsx');
|
||||||
const data = await fs.readFile(blank);
|
const data = await fs.readFile(blank);
|
||||||
await client.api(`${baseUrl}/drive/root:/${packagePath}/${file}:/content`).put(data);
|
await client.api(`${baseUrl}/drive/root:/${packagePath}/${file}:/content`).put(data);
|
||||||
|
|
||||||
// Tries to open again.
|
// Tries to open again.
|
||||||
|
|
||||||
document = await this.internalGetDocument(client, baseUrl, packagePath, file);
|
document = await this.internalGetDocument(client, baseUrl, packagePath, file);
|
||||||
sheets = await client.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets`).get();
|
sheets = await client.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets`).get();
|
||||||
} else {
|
} else {
|
||||||
|
@ -876,51 +1001,44 @@ export class SystemKeywords {
|
||||||
let address;
|
let address;
|
||||||
let body = { values: [[]] };
|
let body = { values: [[]] };
|
||||||
|
|
||||||
// Processes FILTER option to ensure parallel SET calls.
|
// TODO: Check if first column is ID
|
||||||
|
// const firstCell = await client
|
||||||
|
// .api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A1:A1')`)
|
||||||
|
// .get();
|
||||||
|
|
||||||
const filter = await DialogKeywords.getOption({ pid, name: 'filter' });
|
// const hasIdColumn = firstCell.text.toLowerCase() === 'id';
|
||||||
if (filter) {
|
|
||||||
// Creates id row.
|
|
||||||
|
|
||||||
body.values[0][0] = 'id';
|
// // If ID exists in args[0] and we have an ID column, try to find and update the row
|
||||||
const addressId = 'A1:A1';
|
// let rowUpdated = false;
|
||||||
await client
|
// if (hasIdColumn && args[0]) {
|
||||||
.api(
|
// const allRows = await client
|
||||||
`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='${addressId}')`
|
// .api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/usedRange`)
|
||||||
)
|
// .get();
|
||||||
.patch(body);
|
|
||||||
body.values[0][0] = undefined;
|
|
||||||
|
|
||||||
// FINDs the filtered row to be updated.
|
// for (let i = 1; i < allRows.values.length; i++) {
|
||||||
|
// if (allRows.values[i][0] === args[0]) {
|
||||||
const row = await this.find({ pid, handle: null, args: [file, filter] });
|
// // Update existing row
|
||||||
if (row) {
|
// address = `A${i + 1}:${this.numberToLetters(args.length - 1)}${i + 1}`;
|
||||||
address = `A${row['line']}:${this.numberToLetters(args.length)}${row['line']}`;
|
// for (let j = 0; j < args.length; j++) {
|
||||||
}
|
// body.values[0][j] = args[j];
|
||||||
}
|
// }
|
||||||
|
// rowUpdated = true;
|
||||||
// Editing or saving detection.
|
// break;
|
||||||
|
// }
|
||||||
if (!address) {
|
// }
|
||||||
|
// }
|
||||||
|
const rowUpdated = false;
|
||||||
|
// If no row was updated, add a new row
|
||||||
|
if (!rowUpdated) {
|
||||||
await client
|
await client
|
||||||
.api(
|
.api(
|
||||||
`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A2:DX2')/insert`
|
`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A2:DX2')/insert`
|
||||||
)
|
)
|
||||||
.post({});
|
.post({});
|
||||||
address = `A2:${this.numberToLetters(args.length - 1)}2`;
|
address = `A2:${this.numberToLetters(args.length - 1)}2`;
|
||||||
|
for (let j = 0; j < args.length; j++) {
|
||||||
|
body.values[0][j] = args[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fills rows object to call sheet API.
|
|
||||||
|
|
||||||
for (let index = 0; index < args.length; index++) {
|
|
||||||
let value = args[index];
|
|
||||||
if (value && (await this.isValidDate({ pid, dt: value }))) {
|
|
||||||
value = `'${value}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If filter is defined, skips id column.
|
|
||||||
|
|
||||||
body.values[0][filter ? index + 1 : index] = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await retry(
|
await retry(
|
||||||
|
@ -946,6 +1064,30 @@ export class SystemKeywords {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper methods for Minio file locking (unchanged)
|
||||||
|
private async lockFile(minioClient: Client, bucketName: string, filePath: string): Promise<void> {
|
||||||
|
const lockFile = `${filePath}.lock`;
|
||||||
|
try {
|
||||||
|
await minioClient.statObject(bucketName, lockFile);
|
||||||
|
throw new Error(`File ${filePath} is currently locked for editing`);
|
||||||
|
} catch (error) {
|
||||||
|
if (error.code === 'NotFound') {
|
||||||
|
// Create lock file
|
||||||
|
await minioClient.putObject(bucketName, lockFile, 'locked');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async unlockFile(minioClient: Client, bucketName: string, filePath: string): Promise<void> {
|
||||||
|
const lockFile = `${filePath}.lock`;
|
||||||
|
try {
|
||||||
|
await minioClient.removeObject(bucketName, lockFile);
|
||||||
|
} catch (error) {
|
||||||
|
GBLog.error(`Error removing lock file: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Retrives the content of a cell in a tabular file.
|
* Retrives the content of a cell in a tabular file.
|
||||||
*
|
*
|
||||||
|
@ -1128,7 +1270,7 @@ export class SystemKeywords {
|
||||||
const localName = path.join('work', gbaiName, 'cache', `csv${GBAdminService.getRndReadableIdentifier()}.csv`);
|
const localName = path.join('work', gbaiName, 'cache', `csv${GBAdminService.getRndReadableIdentifier()}.csv`);
|
||||||
const url = file['@microsoft.graph.downloadUrl'];
|
const url = file['@microsoft.graph.downloadUrl'];
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
await fs.writeFile(localName, Buffer.from(await response.arrayBuffer()), { encoding: null });
|
await fs.writeFile(localName, new Uint8Array(Buffer.from(await response.arrayBuffer())), { encoding: null });
|
||||||
|
|
||||||
var workbook = new Excel.Workbook();
|
var workbook = new Excel.Workbook();
|
||||||
let worksheet = await workbook.csv.readFile(localName);
|
let worksheet = await workbook.csv.readFile(localName);
|
||||||
|
@ -1175,11 +1317,47 @@ export class SystemKeywords {
|
||||||
} else if (file.indexOf('.csv') !== -1) {
|
} else if (file.indexOf('.csv') !== -1) {
|
||||||
let res;
|
let res;
|
||||||
let packagePath = GBUtil.getGBAIPath(min.botId, `gbdata`);
|
let packagePath = GBUtil.getGBAIPath(min.botId, `gbdata`);
|
||||||
const csvFile = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath, file);
|
|
||||||
|
let csvFile = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath, file);
|
||||||
|
if (GBConfigService.get('GB_MODE') === 'gbcluster') {
|
||||||
|
const fileUrl = urlJoin('/', `${min.botId}.gbdata`, file);
|
||||||
|
GBLogEx.info(min, `Direct data from .csv: ${fileUrl}.`);
|
||||||
|
|
||||||
|
const fileOnly = fileUrl.substring(fileUrl.lastIndexOf('/') + 1);
|
||||||
|
|
||||||
|
const minioClient = new Client({
|
||||||
|
endPoint: process.env.DRIVE_SERVER || 'localhost',
|
||||||
|
port: parseInt(process.env.DRIVE_PORT || '9000', 10),
|
||||||
|
useSSL: process.env.DRIVE_USE_SSL === 'true',
|
||||||
|
accessKey: process.env.DRIVE_ACCESSKEY,
|
||||||
|
secretKey: process.env.DRIVE_SECRET
|
||||||
|
});
|
||||||
|
|
||||||
|
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
||||||
|
const bucketName = (process.env.DRIVE_ORG_PREFIX + min.botId + '.gbai').toLowerCase();
|
||||||
|
const localName = path.join(
|
||||||
|
process.env.PWD,
|
||||||
|
'work',
|
||||||
|
gbaiName,
|
||||||
|
'cache',
|
||||||
|
`${fileOnly.replace(/\s/gi, '')}-${GBAdminService.getNumberIdentifier()}.csv`
|
||||||
|
);
|
||||||
|
|
||||||
|
await minioClient.fGetObject(bucketName, fileUrl, localName);
|
||||||
|
|
||||||
|
csvFile = localName;
|
||||||
|
GBLogEx.info(min, `Downloaded .csv: ${csvFile}.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
GBLogEx.info(min, `Reading .csv: ${csvFile}.`);
|
||||||
const data = await fs.readFile(csvFile, 'utf8');
|
const data = await fs.readFile(csvFile, 'utf8');
|
||||||
|
|
||||||
const firstLine = data.split('\n')[0];
|
const firstLine = data.split('\n')[0];
|
||||||
const headers = firstLine.split(',');
|
const headers = firstLine.split(',');
|
||||||
const db = await csvdb(csvFile, headers, ',');
|
const db = await csvdb(csvFile, headers, ',');
|
||||||
|
|
||||||
|
GBLogEx.info(min, `READ .csv: ${csvFile}.`);
|
||||||
|
|
||||||
if (args[0]) {
|
if (args[0]) {
|
||||||
const systemFilter = await SystemKeywords.getFilter(args[0]);
|
const systemFilter = await SystemKeywords.getFilter(args[0]);
|
||||||
let filter = {};
|
let filter = {};
|
||||||
|
@ -1189,6 +1367,8 @@ export class SystemKeywords {
|
||||||
res = await db.get();
|
res = await db.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GBLogEx.info(min, `ROWS: ${res.length}.`);
|
||||||
|
|
||||||
return res.length > 1 ? res : res[0];
|
return res.length > 1 ? res : res[0];
|
||||||
} else {
|
} else {
|
||||||
const t = this.getTableFromName(file, min);
|
const t = this.getTableFromName(file, min);
|
||||||
|
@ -1698,13 +1878,9 @@ export class SystemKeywords {
|
||||||
const srcPath = urlJoin(root, src);
|
const srcPath = urlJoin(root, src);
|
||||||
const dstPath = urlJoin(packagePath, dest);
|
const dstPath = urlJoin(packagePath, dest);
|
||||||
|
|
||||||
|
|
||||||
if (path.extname(srcPath) === 'ai') {
|
if (path.extname(srcPath) === 'ai') {
|
||||||
|
|
||||||
// TODO: To be done.
|
// TODO: To be done.
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Checks if the destination contains subfolders that
|
// Checks if the destination contains subfolders that
|
||||||
// need to be created.
|
// need to be created.
|
||||||
|
|
||||||
|
@ -1985,35 +2161,98 @@ export class SystemKeywords {
|
||||||
*
|
*
|
||||||
* Fills a .docx or .pptx with template data.
|
* Fills a .docx or .pptx with template data.
|
||||||
*
|
*
|
||||||
* doc = FILL "templates/template.docx", data
|
* doc = FILL "templates/template.docx" WITH data
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public async fill({ pid, templateName, data }) {
|
private async getTemplateBuffer(min: any, gbaiName: string, templateName: string): Promise<Buffer> {
|
||||||
const { min, user } = await DialogKeywords.getProcessInfo(pid);
|
|
||||||
const botId = min.instance.botId;
|
const botId = min.instance.botId;
|
||||||
const gbaiName = GBUtil.getGBAIPath(botId, 'gbdata');
|
|
||||||
let localName;
|
|
||||||
|
|
||||||
// Downloads template from .gbdrive.
|
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
|
// Legacy mode - using Microsoft Graph API
|
||||||
let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
const { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
||||||
let packagePath = '/' + urlJoin(gbaiName, `${botId}.gbdrive`);
|
const packagePath = '/' + urlJoin(gbaiName, `${botId}.gbdrive`);
|
||||||
let template = await this.internalGetDocument(client, baseUrl, packagePath, templateName);
|
const template = await this.internalGetDocument(client, baseUrl, packagePath, templateName);
|
||||||
let url = template['@microsoft.graph.downloadUrl'];
|
const url = template['@microsoft.graph.downloadUrl'];
|
||||||
const res = await fetch(url);
|
const res = await fetch(url);
|
||||||
let buf: any = Buffer.from(await res.arrayBuffer());
|
return Buffer.from(await res.arrayBuffer());
|
||||||
localName = path.join('work', gbaiName, 'cache', `tmp${GBAdminService.getRndReadableIdentifier()}.docx`);
|
} else if (GBConfigService.get('GB_MODE') === 'gbcluster') {
|
||||||
await fs.writeFile(localName, buf, { encoding: null });
|
// GBCluster mode - using MinIO
|
||||||
|
const minioClient = this.createMinioClient();
|
||||||
|
const bucketName = (process.env.DRIVE_ORG_PREFIX + botId + '.gbai').toLowerCase();
|
||||||
|
const filePath = urlJoin(gbaiName, `${botId}.gbdrive`, templateName);
|
||||||
|
|
||||||
// Replace image path on all elements of data.
|
return new Promise((resolve, reject) => {
|
||||||
|
const chunks: Uint8Array[] = [];
|
||||||
|
minioClient
|
||||||
|
.getObject(bucketName, filePath)
|
||||||
|
.then(stream => {
|
||||||
|
stream.on('data', chunk => chunks.push(new Uint8Array(chunk)));
|
||||||
|
stream.on('end', () => resolve(Buffer.concat(chunks)));
|
||||||
|
stream.on('error', reject);
|
||||||
|
})
|
||||||
|
.catch(reject);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Default mode - direct filesystem access
|
||||||
|
const gbdriveName = GBUtil.getGBAIPath(botId, 'gbdrive');
|
||||||
|
const templatePath = path.join(GBConfigService.get('STORAGE_LIBRARY'), gbdriveName, templateName);
|
||||||
|
return fs.readFile(templatePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getImageBuffer(min: any, gbaiName: string, imagePath: string): Promise<Buffer> {
|
||||||
|
const botId = min.instance.botId;
|
||||||
|
|
||||||
|
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
|
const { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
||||||
|
let packagePath = urlJoin(gbaiName, `${botId}.gbdrive`);
|
||||||
|
if (imagePath.indexOf('/') !== -1) {
|
||||||
|
packagePath = '/' + urlJoin(packagePath, path.dirname(imagePath));
|
||||||
|
imagePath = path.basename(imagePath);
|
||||||
|
}
|
||||||
|
const ref = await this.internalGetDocument(client, baseUrl, packagePath, imagePath);
|
||||||
|
const url = ref['@microsoft.graph.downloadUrl'];
|
||||||
|
const response = await fetch(url);
|
||||||
|
return Buffer.from(await response.arrayBuffer());
|
||||||
|
} else if (GBConfigService.get('GB_MODE') === 'gbcluster') {
|
||||||
|
const minioClient = this.createMinioClient();
|
||||||
|
const bucketName = (process.env.DRIVE_ORG_PREFIX + botId + '.gbai').toLowerCase();
|
||||||
|
const filePath = urlJoin(gbaiName, `${botId}.gbdrive`, imagePath);
|
||||||
|
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
const chunks: Buffer[] = [];
|
||||||
|
try {
|
||||||
|
const stream = await minioClient.getObject(bucketName, filePath);
|
||||||
|
stream.on('data', chunk => chunks.push(chunk));
|
||||||
|
stream.on('end', () => resolve(Buffer.concat(chunks)));
|
||||||
|
stream.on('error', reject);
|
||||||
|
} catch (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const gbdriveName = GBUtil.getGBAIPath(botId, 'gbdrive');
|
||||||
|
const fullPath = path.join(GBConfigService.get('STORAGE_LIBRARY'), gbdriveName, imagePath);
|
||||||
|
return fs.readFile(fullPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private createMinioClient(): Client {
|
||||||
|
return new Client({
|
||||||
|
endPoint: process.env.DRIVE_SERVER || 'localhost',
|
||||||
|
port: parseInt(process.env.DRIVE_PORT || '9000', 10),
|
||||||
|
useSSL: process.env.DRIVE_USE_SSL === 'true',
|
||||||
|
accessKey: process.env.DRIVE_ACCESSKEY,
|
||||||
|
secretKey: process.env.DRIVE_SECRET
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async processImagesInData(min: any, gbaiName: string, data: any): Promise<any[]> {
|
||||||
const images = [];
|
const images = [];
|
||||||
let index = 0;
|
let index = 0;
|
||||||
packagePath = path.join(gbaiName, 'cache', `tmp${GBAdminService.getRndReadableIdentifier()}.docx`);
|
|
||||||
url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
|
||||||
|
|
||||||
const traverseDataToInjectImageUrl = async o => {
|
const traverseDataToInjectImageUrl = async (o: any) => {
|
||||||
for (var i in o) {
|
for (const i in o) {
|
||||||
let value = o[i];
|
let value = o[i];
|
||||||
|
|
||||||
if (value && value.gbarray) {
|
if (value && value.gbarray) {
|
||||||
|
@ -2022,112 +2261,84 @@ export class SystemKeywords {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const kind of ['png', 'jpg', 'jpeg']) {
|
for (const kind of ['png', 'jpg', 'jpeg']) {
|
||||||
if (value.endsWith && value.endsWith(`.${kind}`)) {
|
if (value?.endsWith?.(`.${kind}`)) {
|
||||||
const { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
const imageBuffer = await this.getImageBuffer(min, gbaiName, value);
|
||||||
|
|
||||||
packagePath = urlJoin(gbaiName, `${botId}.gbdrive`);
|
|
||||||
if (value.indexOf('/') !== -1) {
|
|
||||||
packagePath = '/' + urlJoin(packagePath, path.dirname(value));
|
|
||||||
value = path.basename(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ref = await this.internalGetDocument(client, baseUrl, packagePath, value);
|
|
||||||
let url = ref['@microsoft.graph.downloadUrl'];
|
|
||||||
const imageName = path.join(
|
const imageName = path.join(
|
||||||
'work',
|
'work',
|
||||||
gbaiName,
|
gbaiName,
|
||||||
'cache',
|
'cache',
|
||||||
`tmp${GBAdminService.getRndReadableIdentifier()}-${value}.png`
|
`tmp${GBAdminService.getRndReadableIdentifier()}-${path.basename(value)}.png`
|
||||||
);
|
);
|
||||||
const response = await fetch(url);
|
await fs.writeFile(imageName, new Uint8Array(imageBuffer), { encoding: null });
|
||||||
const buf = Buffer.from(await response.arrayBuffer());
|
|
||||||
await fs.writeFile(imageName, buf, { encoding: null });
|
|
||||||
|
|
||||||
const getNormalSize = ({ width, height, orientation }) => {
|
const getNormalSize = ({ width, height, orientation }: any) => {
|
||||||
return (orientation || 0) >= 5 ? [height, width] : [width, height];
|
return (orientation || 0) >= 5 ? [height, width] : [width, height];
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: sharp. const metadata = await sharp(buf).metadata();
|
|
||||||
const size = getNormalSize({
|
const size = getNormalSize({
|
||||||
width: 400,
|
width: 400,
|
||||||
height: 400,
|
height: 400,
|
||||||
orientation: '0'
|
orientation: '0'
|
||||||
});
|
});
|
||||||
url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(imageName));
|
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(imageName));
|
||||||
images[index++] = { url: url, size: size, buf: buf };
|
images[index++] = { url, size, buf: imageBuffer };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (o[i] !== null && typeof o[i] == 'object') {
|
|
||||||
|
if (o[i] !== null && typeof o[i] === 'object') {
|
||||||
await traverseDataToInjectImageUrl(o[i]);
|
await traverseDataToInjectImageUrl(o[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
await traverseDataToInjectImageUrl(data);
|
||||||
|
return images;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async fill({ pid, templateName, data }) {
|
||||||
|
const { min, user } = await DialogKeywords.getProcessInfo(pid);
|
||||||
|
const botId = min.instance.botId;
|
||||||
|
const gbaiName = GBUtil.getGBAIPath(botId);
|
||||||
|
|
||||||
|
// Get template buffer based on GB_MODE
|
||||||
|
const templateBuffer = await this.getTemplateBuffer(min, gbaiName, templateName);
|
||||||
|
|
||||||
|
// Process images in data
|
||||||
|
const images = await this.processImagesInData(min, gbaiName, data);
|
||||||
|
|
||||||
|
// Prepare local file
|
||||||
|
const localName = path.join('work', gbaiName, 'cache', `tmp${GBAdminService.getRndReadableIdentifier()}.docx`);
|
||||||
|
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
||||||
|
|
||||||
|
// Prepare docxtemplater options
|
||||||
let indexImage = 0;
|
let indexImage = 0;
|
||||||
var opts = {
|
const opts = {
|
||||||
fileType: 'docx',
|
fileType: 'docx',
|
||||||
centered: false,
|
centered: false,
|
||||||
getImage: (tagValue, tagName) => {
|
getImage: () => images[indexImage].buf,
|
||||||
return images[indexImage].buf;
|
getSize: () => images[indexImage++].size
|
||||||
},
|
|
||||||
getSize: (img, tagValue, tagName) => {
|
|
||||||
return images[indexImage++].size;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Loads the file as binary content.
|
// Process the template
|
||||||
|
const zip = new PizZip(templateBuffer);
|
||||||
let zip = new PizZip(buf);
|
const doc = new Docxtemplater();
|
||||||
let doc = new Docxtemplater();
|
|
||||||
doc.setOptions({ paragraphLoop: true, linebreaks: true });
|
doc.setOptions({ paragraphLoop: true, linebreaks: true });
|
||||||
doc.loadZip(zip);
|
doc.loadZip(zip);
|
||||||
|
|
||||||
if (localName.endsWith('.pptx')) {
|
if (localName.endsWith('.pptx')) {
|
||||||
doc.attachModule(pptxTemplaterModule);
|
doc.attachModule(pptxTemplaterModule);
|
||||||
}
|
}
|
||||||
|
|
||||||
doc.attachModule(new ImageModule(opts));
|
doc.attachModule(new ImageModule(opts));
|
||||||
|
doc.render(data);
|
||||||
|
|
||||||
await traverseDataToInjectImageUrl(data);
|
const outputBuffer = doc.getZip().generate({ type: 'nodebuffer', compression: 'DEFLATE' });
|
||||||
doc.setData(data).render();
|
await fs.writeFile(localName, new Uint8Array(outputBuffer), { encoding: null });
|
||||||
|
|
||||||
buf = doc.getZip().generate({ type: 'nodebuffer', compression: 'DEFLATE' });
|
return { localName, url, data: outputBuffer };
|
||||||
await fs.writeFile(localName, buf, { encoding: null });
|
|
||||||
|
|
||||||
return { localName: localName, url: url, data: buf };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public screenCapture(pid) {
|
public screenCapture(pid) {}
|
||||||
// scrcpy Disabled
|
|
||||||
// function captureImage({ x, y, w, h }) {
|
|
||||||
// const pic = robot.screen.capture(x, y, w, h)
|
|
||||||
// const width = pic.byteWidth / pic.bytesPerPixel // pic.width is sometimes wrong!
|
|
||||||
// const height = pic.height
|
|
||||||
// const image = new Jimp(width, height)
|
|
||||||
// let red, green, blue
|
|
||||||
// pic.image.forEach((byte, i) => {
|
|
||||||
// switch (i % 4) {
|
|
||||||
// case 0: return blue = byte
|
|
||||||
// case 1: return green = byte
|
|
||||||
// case 2: return red = byte
|
|
||||||
// case 3:
|
|
||||||
// image.bitmap.data[i - 3] = red
|
|
||||||
// image.bitmap.data[i - 2] = green
|
|
||||||
// image.bitmap.data[i - 1] = blue
|
|
||||||
// image.bitmap.data[i] = 255
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// return image
|
|
||||||
// }
|
|
||||||
// let file = 'out.png';
|
|
||||||
// captureImage({ x: 60, y: 263, w: 250, h: 83 }).write(file)
|
|
||||||
// const config = {
|
|
||||||
// lang: "eng",
|
|
||||||
// oem: 1,
|
|
||||||
// psm: 3,
|
|
||||||
// }
|
|
||||||
// tesseract.recognize(file, config).then(value => {
|
|
||||||
// console.log(value);
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
|
|
||||||
private numberToLetters(num) {
|
private numberToLetters(num) {
|
||||||
let letters = '';
|
let letters = '';
|
||||||
|
@ -2478,12 +2689,11 @@ export class SystemKeywords {
|
||||||
GBLogEx.info(min, `BlueSky Automation: ${text}.`);
|
GBLogEx.info(min, `BlueSky Automation: ${text}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
public async answer({ pid, text }) {
|
public async answer({ pid, text }) {
|
||||||
const { min, user } = await DialogKeywords.getProcessInfo(pid);
|
const { min, user } = await DialogKeywords.getProcessInfo(pid);
|
||||||
const answer = await ChatServices.answerByLLM(pid, min, user, text)
|
const answer = await ChatServices.answerByLLM(pid, min, user, text);
|
||||||
GBLogEx.info(min, `ANSWER ${text} TO ${answer}`);
|
GBLogEx.info(min, `ANSWER ${text} TO ${answer}`);
|
||||||
return answer.answer;
|
return answer.answer;
|
||||||
}
|
}
|
||||||
|
@ -2495,9 +2705,9 @@ export class SystemKeywords {
|
||||||
*/
|
*/
|
||||||
public async rewrite({ pid, text }) {
|
public async rewrite({ pid, text }) {
|
||||||
const { min, user } = await DialogKeywords.getProcessInfo(pid);
|
const { min, user } = await DialogKeywords.getProcessInfo(pid);
|
||||||
const prompt = `Rewrite this sentence in a better way: ${text}`;
|
const prompt = `${text}`;
|
||||||
const answer = await ChatServices.invokeLLM(min, prompt);
|
const answer = await ChatServices.invokeLLM(min, prompt);
|
||||||
GBLogEx.info(min, `REWRITE ${text} TO ${answer}`);
|
GBLogEx.info(min, `REWRITE ${text} TO ${answer.text}`);
|
||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2558,7 +2768,7 @@ export class SystemKeywords {
|
||||||
|
|
||||||
const buf = Buffer.from(data.Payment.QrCodeBase64Image, 'base64');
|
const buf = Buffer.from(data.Payment.QrCodeBase64Image, 'base64');
|
||||||
const localName = path.join('work', gbaiName, 'cache', `qr${GBAdminService.getRndReadableIdentifier()}.png`);
|
const localName = path.join('work', gbaiName, 'cache', `qr${GBAdminService.getRndReadableIdentifier()}.png`);
|
||||||
await fs.writeFile(localName, buf, { encoding: null });
|
await fs.writeFile(localName, new Uint8Array(buf), { encoding: null });
|
||||||
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
||||||
|
|
||||||
GBLogEx.info(min, `GBPay: ${data.MerchantOrderId} OK: ${url}.`);
|
GBLogEx.info(min, `GBPay: ${data.MerchantOrderId} OK: ${url}.`);
|
||||||
|
@ -2647,7 +2857,6 @@ export class SystemKeywords {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getExtensionInfo(ext: any): Promise<any> {
|
public async getExtensionInfo(ext: any): Promise<any> {
|
||||||
|
|
||||||
// TODO: Load exts.
|
// TODO: Load exts.
|
||||||
|
|
||||||
let array = []; // exts.filter((v, i, a) => a[i]['extension'] === ext);
|
let array = []; // exts.filter((v, i, a) => a[i]['extension'] === ext);
|
||||||
|
@ -2726,7 +2935,7 @@ export class SystemKeywords {
|
||||||
try {
|
try {
|
||||||
let data;
|
let data;
|
||||||
|
|
||||||
if (GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
||||||
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
||||||
let packagePath = '/' + urlJoin(gbaiName, `${min.botId}.gbdrive`);
|
let packagePath = '/' + urlJoin(gbaiName, `${min.botId}.gbdrive`);
|
||||||
|
@ -2791,7 +3000,7 @@ export class SystemKeywords {
|
||||||
|
|
||||||
// Criação de um arquivo temporário para enviar
|
// Criação de um arquivo temporário para enviar
|
||||||
const tempFilePath = path.resolve('temp_image.jpg');
|
const tempFilePath = path.resolve('temp_image.jpg');
|
||||||
await fs.writeFile(tempFilePath, imageBuffer);
|
await fs.writeFile(tempFilePath, new Uint8Array(imageBuffer));
|
||||||
|
|
||||||
// Publicação da imagem
|
// Publicação da imagem
|
||||||
const page = new Page(pageId);
|
const page = new Page(pageId);
|
||||||
|
@ -2908,17 +3117,16 @@ export class SystemKeywords {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async convertAI2HTML(aiFilePath) {
|
public async convertAI2HTML(aiFilePath) {
|
||||||
|
|
||||||
// Convert the AI file to HTML and assets
|
// Convert the AI file to HTML and assets
|
||||||
const result = await ai2html.convertFile(aiFilePath, {
|
const result = await ai2html.convertFile(aiFilePath, {
|
||||||
outputFormat: 'html',
|
outputFormat: 'html',
|
||||||
outputWriteMethod: 'write-file',
|
outputWriteMethod: 'write-file',
|
||||||
outputPath: path.dirname(aiFilePath),
|
outputPath: path.dirname(aiFilePath),
|
||||||
useDocumentSettings: true,
|
useDocumentSettings: true
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get the generated HTML file path
|
// Get the generated HTML file path
|
||||||
const htmlFilePath = result.outputFiles.find((file) => file.endsWith('.html')).filePath;
|
const htmlFilePath = result.outputFiles.find(file => file.endsWith('.html')).filePath;
|
||||||
|
|
||||||
// Read the HTML content
|
// Read the HTML content
|
||||||
const htmlContent = await fs.readFile(htmlFilePath, 'utf8');
|
const htmlContent = await fs.readFile(htmlFilePath, 'utf8');
|
||||||
|
@ -2930,10 +3138,8 @@ export class SystemKeywords {
|
||||||
await fs.writeFile(cacheFilePath, htmlContent);
|
await fs.writeFile(cacheFilePath, htmlContent);
|
||||||
|
|
||||||
return cacheFilePath;
|
return cacheFilePath;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async refreshDataSourceCache({ pid, connectionName }) {
|
public async refreshDataSourceCache({ pid, connectionName }) {
|
||||||
const { min, user, params, step } = await DialogKeywords.getProcessInfo(pid);
|
const { min, user, params, step } = await DialogKeywords.getProcessInfo(pid);
|
||||||
|
|
||||||
|
@ -2959,25 +3165,25 @@ export class SystemKeywords {
|
||||||
const tables = await GBUtil.listTables(dialect, con);
|
const tables = await GBUtil.listTables(dialect, con);
|
||||||
|
|
||||||
// Function to map source database datatypes to SQLite-compatible datatypes
|
// Function to map source database datatypes to SQLite-compatible datatypes
|
||||||
const mapToSQLiteType = (columnType) => {
|
const mapToSQLiteType = columnType => {
|
||||||
const typeMapping = {
|
const typeMapping = {
|
||||||
'VARCHAR': DataTypes.STRING,
|
VARCHAR: DataTypes.STRING,
|
||||||
'CHAR': DataTypes.STRING,
|
CHAR: DataTypes.STRING,
|
||||||
'TEXT': DataTypes.TEXT,
|
TEXT: DataTypes.TEXT,
|
||||||
'TINYINT': DataTypes.INTEGER,
|
TINYINT: DataTypes.INTEGER,
|
||||||
'SMALLINT': DataTypes.INTEGER,
|
SMALLINT: DataTypes.INTEGER,
|
||||||
'MEDIUMINT': DataTypes.INTEGER,
|
MEDIUMINT: DataTypes.INTEGER,
|
||||||
'INT': DataTypes.INTEGER,
|
INT: DataTypes.INTEGER,
|
||||||
'INTEGER': DataTypes.INTEGER,
|
INTEGER: DataTypes.INTEGER,
|
||||||
'BIGINT': DataTypes.BIGINT,
|
BIGINT: DataTypes.BIGINT,
|
||||||
'FLOAT': DataTypes.FLOAT,
|
FLOAT: DataTypes.FLOAT,
|
||||||
'DOUBLE': DataTypes.DOUBLE,
|
DOUBLE: DataTypes.DOUBLE,
|
||||||
'DECIMAL': DataTypes.DECIMAL,
|
DECIMAL: DataTypes.DECIMAL,
|
||||||
'DATE': DataTypes.DATE,
|
DATE: DataTypes.DATE,
|
||||||
'DATETIME': DataTypes.DATE,
|
DATETIME: DataTypes.DATE,
|
||||||
'TIMESTAMP': DataTypes.DATE,
|
TIMESTAMP: DataTypes.DATE,
|
||||||
'BLOB': DataTypes.BLOB,
|
BLOB: DataTypes.BLOB,
|
||||||
'BOOLEAN': DataTypes.BOOLEAN,
|
BOOLEAN: DataTypes.BOOLEAN
|
||||||
// Add more mappings as needed
|
// Add more mappings as needed
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
"title": "Default General Bot",
|
"title": "Default General Bot",
|
||||||
"description": "Default General Bot",
|
"description": "Default General Bot",
|
||||||
"whoAmIVideo": "TODO.mp4",
|
"whoAmIVideo": "TODO.mp4",
|
||||||
"author": "pragmatismo.cloud",
|
"author": "pragmatismo.com.br",
|
||||||
"license": "AGPL",
|
"license": "AGPL",
|
||||||
"engineName": "guaribas-1.0.0"
|
"engineName": "guaribas-1.0.0"
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -65,8 +65,7 @@ export class WelcomeDialog extends IGBDialog {
|
||||||
async step => {
|
async step => {
|
||||||
if (
|
if (
|
||||||
GBServer.globals.entryPointDialog !== null &&
|
GBServer.globals.entryPointDialog !== null &&
|
||||||
min.instance.botId === GBConfigService.get('BOT_ID') &&
|
min.instance.botId === GBConfigService.get('BOT_ID')
|
||||||
step.context.activity.channelId === 'webchat'
|
|
||||||
) {
|
) {
|
||||||
return step.replaceDialog(GBServer.globals.entryPointDialog);
|
return step.replaceDialog(GBServer.globals.entryPointDialog);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -86,7 +86,7 @@ export class GBConfigService {
|
||||||
value = this.getServerPort();
|
value = this.getServerPort();
|
||||||
break;
|
break;
|
||||||
case 'GBVM':
|
case 'GBVM':
|
||||||
value = false;
|
value = true;
|
||||||
break;
|
break;
|
||||||
case 'STORAGE_NAME':
|
case 'STORAGE_NAME':
|
||||||
value = null;
|
value = null;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -43,6 +43,7 @@ import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js';
|
||||||
import { SecService } from '../../security.gbapp/services/SecService.js';
|
import { SecService } from '../../security.gbapp/services/SecService.js';
|
||||||
import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService.js';
|
import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService.js';
|
||||||
import { MicrosoftAppCredentials } from 'botframework-connector';
|
import { MicrosoftAppCredentials } from 'botframework-connector';
|
||||||
|
import { DocxLoader } from '@langchain/community/document_loaders/fs/docx';
|
||||||
import { GBConfigService } from './GBConfigService.js';
|
import { GBConfigService } from './GBConfigService.js';
|
||||||
import { CollectionUtil, AzureText } from 'pragmatismo-io-framework';
|
import { CollectionUtil, AzureText } from 'pragmatismo-io-framework';
|
||||||
import { GuaribasUser } from '../../security.gbapp/models/index.js';
|
import { GuaribasUser } from '../../security.gbapp/models/index.js';
|
||||||
|
@ -52,7 +53,7 @@ import { createWriteStream, createReadStream } from 'fs';
|
||||||
import fs from 'fs/promises';
|
import fs from 'fs/promises';
|
||||||
import twilio from 'twilio';
|
import twilio from 'twilio';
|
||||||
import Nexmo from 'nexmo';
|
import Nexmo from 'nexmo';
|
||||||
import { join } from 'path';
|
import path, { join } from 'path';
|
||||||
import shell from 'any-shell-escape';
|
import shell from 'any-shell-escape';
|
||||||
import { exec } from 'child_process';
|
import { exec } from 'child_process';
|
||||||
import prism from 'prism-media';
|
import prism from 'prism-media';
|
||||||
|
@ -646,6 +647,15 @@ export class GBConversationalService {
|
||||||
text.toLowerCase().endsWith('.png') ||
|
text.toLowerCase().endsWith('.png') ||
|
||||||
text.toLowerCase().endsWith('.mp4') ||
|
text.toLowerCase().endsWith('.mp4') ||
|
||||||
text.toLowerCase().endsWith('.mov');
|
text.toLowerCase().endsWith('.mov');
|
||||||
|
|
||||||
|
if (text.endsWith('-zap')) {
|
||||||
|
let packagePath = GBUtil.getGBAIPath(min.botId, `gbkb`);
|
||||||
|
const localName = path.join('work', packagePath, 'articles', text + '.docx');
|
||||||
|
let loader = new DocxLoader(localName);
|
||||||
|
let doc = await loader.load();
|
||||||
|
text = doc[0].pageContent;
|
||||||
|
template = template + '_docx';
|
||||||
|
}
|
||||||
let mediaFile = !isMedia ? /(.*)\n/gim.exec(text)[0].trim() : text;
|
let mediaFile = !isMedia ? /(.*)\n/gim.exec(text)[0].trim() : text;
|
||||||
let mediaType = mediaFile.toLowerCase().endsWith('.mp4') || text.toLowerCase().endsWith('.mov') ? 'video' : 'image';
|
let mediaType = mediaFile.toLowerCase().endsWith('.mp4') || text.toLowerCase().endsWith('.mov') ? 'video' : 'image';
|
||||||
|
|
||||||
|
@ -1280,7 +1290,7 @@ export class GBConversationalService {
|
||||||
* Sends a message in a user with an already started conversation (got ConversationReference set)
|
* Sends a message in a user with an already started conversation (got ConversationReference set)
|
||||||
*/
|
*/
|
||||||
public async sendOnConversation(min: GBMinInstance, user: GuaribasUser, message: any) {
|
public async sendOnConversation(min: GBMinInstance, user: GuaribasUser, message: any) {
|
||||||
if (GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
const ref = JSON.parse(user.conversationReference);
|
const ref = JSON.parse(user.conversationReference);
|
||||||
MicrosoftAppCredentials.trustServiceUrl(ref.serviceUrl);
|
MicrosoftAppCredentials.trustServiceUrl(ref.serviceUrl);
|
||||||
await min.bot['continueConversation'](ref, async t1 => {
|
await min.bot['continueConversation'](ref, async t1 => {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -67,6 +67,7 @@ import { GBDeployer } from './GBDeployer.js';
|
||||||
import { SystemKeywords } from '../../basic.gblib/services/SystemKeywords.js';
|
import { SystemKeywords } from '../../basic.gblib/services/SystemKeywords.js';
|
||||||
import csvdb from 'csv-database';
|
import csvdb from 'csv-database';
|
||||||
import { SaaSPackage } from '../../saas.gbapp/index.js';
|
import { SaaSPackage } from '../../saas.gbapp/index.js';
|
||||||
|
import { Client } from 'minio';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GBCoreService contains main logic for handling storage services related
|
* GBCoreService contains main logic for handling storage services related
|
||||||
|
@ -121,27 +122,44 @@ export class GBCoreService implements IGBCoreService {
|
||||||
public async initStorage(): Promise<any> {
|
public async initStorage(): Promise<any> {
|
||||||
this.dialect = GBConfigService.get('STORAGE_DIALECT');
|
this.dialect = GBConfigService.get('STORAGE_DIALECT');
|
||||||
|
|
||||||
|
let port: number | undefined;
|
||||||
let host: string | undefined;
|
let host: string | undefined;
|
||||||
let database: string | undefined;
|
let database: string | undefined;
|
||||||
let username: string | undefined;
|
let username: string | undefined;
|
||||||
let password: string | undefined;
|
let password: string | undefined;
|
||||||
let storage: string | undefined;
|
let storage: string | undefined;
|
||||||
|
|
||||||
if (this.dialect === 'mssql') {
|
|
||||||
|
if (!['mssql', 'postgres', 'sqlite'].includes(this.dialect)) {
|
||||||
|
throw new Error(`Unknown or unsupported dialect: ${this.dialect}.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (this.dialect === 'mssql' || this.dialect === 'postgres') {
|
||||||
host = GBConfigService.get('STORAGE_SERVER');
|
host = GBConfigService.get('STORAGE_SERVER');
|
||||||
database = GBConfigService.get('STORAGE_NAME');
|
database = GBConfigService.get('STORAGE_NAME');
|
||||||
username = GBConfigService.get('STORAGE_USERNAME');
|
username = GBConfigService.get('STORAGE_USERNAME');
|
||||||
password = GBConfigService.get('STORAGE_PASSWORD');
|
password = GBConfigService.get('STORAGE_PASSWORD');
|
||||||
|
|
||||||
|
const portStr = GBConfigService.get('STORAGE_PORT');
|
||||||
|
port = portStr ? parseInt(portStr, 10) : undefined;
|
||||||
|
|
||||||
|
if (!host || !database || !username || !password || !port) {
|
||||||
|
throw new Error(`Missing required configuration for ${this.dialect}.`);
|
||||||
|
}
|
||||||
} else if (this.dialect === 'sqlite') {
|
} else if (this.dialect === 'sqlite') {
|
||||||
storage = GBConfigService.get('STORAGE_FILE');
|
storage = GBConfigService.get('STORAGE_FILE');
|
||||||
|
|
||||||
|
if (!storage) {
|
||||||
|
throw new Error('STORAGE_FILE is required for SQLite.');
|
||||||
|
}
|
||||||
|
|
||||||
if (!(await GBUtil.exists(storage))) {
|
if (!(await GBUtil.exists(storage))) {
|
||||||
process.env.STORAGE_SYNC = 'true';
|
process.env.STORAGE_SYNC = 'true';
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
throw new Error(`Unknown dialect: ${this.dialect}.`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const logging: boolean | Function =
|
const logging: boolean | Function =
|
||||||
GBConfigService.get('STORAGE_LOGGING') === 'true'
|
GBConfigService.get('STORAGE_LOGGING') === 'true'
|
||||||
? (str: string): void => {
|
? (str: string): void => {
|
||||||
|
@ -149,34 +167,41 @@ export class GBCoreService implements IGBCoreService {
|
||||||
}
|
}
|
||||||
: false;
|
: false;
|
||||||
|
|
||||||
|
|
||||||
const encrypt: boolean = GBConfigService.get('STORAGE_ENCRYPT') === 'true';
|
const encrypt: boolean = GBConfigService.get('STORAGE_ENCRYPT') === 'true';
|
||||||
|
|
||||||
const acquire = parseInt(GBConfigService.get('STORAGE_ACQUIRE_TIMEOUT'));
|
|
||||||
|
const acquireStr = GBConfigService.get('STORAGE_ACQUIRE_TIMEOUT');
|
||||||
|
const acquire = acquireStr ? parseInt(acquireStr, 10) : 10000; // Valor padrão de 10 segundos
|
||||||
|
|
||||||
|
|
||||||
const sequelizeOptions: SequelizeOptions = {
|
const sequelizeOptions: SequelizeOptions = {
|
||||||
define: {
|
define: {
|
||||||
freezeTableName: true,
|
freezeTableName: true,
|
||||||
timestamps: false
|
timestamps: false,
|
||||||
},
|
},
|
||||||
host: host,
|
host: host,
|
||||||
|
port: port,
|
||||||
logging: logging as boolean,
|
logging: logging as boolean,
|
||||||
dialect: this.dialect as Dialect,
|
dialect: this.dialect as Dialect,
|
||||||
storage: storage,
|
storage: storage,
|
||||||
quoteIdentifiers: false, // set case-insensitive
|
quoteIdentifiers: this.dialect === 'postgres',
|
||||||
dialectOptions: {
|
dialectOptions: this.dialect === 'mssql' ? {
|
||||||
options: {
|
options: {
|
||||||
trustServerCertificate: true,
|
trustServerCertificate: true,
|
||||||
encrypt: encrypt
|
encrypt: encrypt,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
} : {},
|
||||||
pool: {
|
pool: {
|
||||||
max: 5,
|
max: 5,
|
||||||
min: 0,
|
min: 0,
|
||||||
idle: 10000,
|
idle: 10000,
|
||||||
evict: 10000,
|
evict: 10000,
|
||||||
acquire: acquire
|
acquire: acquire,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
this.sequelize = new Sequelize(database, username, password, sequelizeOptions);
|
this.sequelize = new Sequelize(database, username, password, sequelizeOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,12 +277,15 @@ export class GBCoreService implements IGBCoreService {
|
||||||
const options = {
|
const options = {
|
||||||
where: {
|
where: {
|
||||||
[Op.or]: and
|
[Op.or]: and
|
||||||
}
|
},
|
||||||
|
order: [['instanceId', 'ASC']]
|
||||||
};
|
};
|
||||||
return await GuaribasInstance.findAll(options);
|
return await GuaribasInstance.findAll(options as any);
|
||||||
} else {
|
} else {
|
||||||
const options = { where: { state: 'active' } };
|
const options = { where: { state: 'active' } ,
|
||||||
return await GuaribasInstance.findAll(options);
|
|
||||||
|
order: [['instanceId', 'ASC']]};
|
||||||
|
return await GuaribasInstance.findAll(options as any);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,7 +323,6 @@ export class GBCoreService implements IGBCoreService {
|
||||||
public async writeEnv(instance: IGBInstance) {
|
public async writeEnv(instance: IGBInstance) {
|
||||||
const env = `
|
const env = `
|
||||||
ADDITIONAL_DEPLOY_PATH=
|
ADDITIONAL_DEPLOY_PATH=
|
||||||
ADMIN_PASS=${instance.adminPass}
|
|
||||||
BOT_ID=${instance.botId}
|
BOT_ID=${instance.botId}
|
||||||
CLOUD_SUBSCRIPTIONID=${instance.cloudSubscriptionId}
|
CLOUD_SUBSCRIPTIONID=${instance.cloudSubscriptionId}
|
||||||
CLOUD_LOCATION=${instance.cloudLocation}
|
CLOUD_LOCATION=${instance.cloudLocation}
|
||||||
|
@ -675,7 +702,7 @@ await fs.writeFile('.env', env);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async setConfig(min, name: string, value: any): Promise<any> {
|
public async setConfig(min, name: string, value: any): Promise<any> {
|
||||||
if (GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
// Handles calls for BASIC persistence on sheet files.
|
// Handles calls for BASIC persistence on sheet files.
|
||||||
GBLog.info(`Defining Config.xlsx variable ${name}= '${value}'...`);
|
GBLog.info(`Defining Config.xlsx variable ${name}= '${value}'...`);
|
||||||
|
|
||||||
|
@ -723,8 +750,8 @@ await fs.writeFile('.env', env);
|
||||||
await client
|
await client
|
||||||
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='${address}')`)
|
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='${address}')`)
|
||||||
.patch(body);
|
.patch(body);
|
||||||
|
}
|
||||||
} else {
|
else if (GBConfigService.get('GB_MODE') === 'local') {
|
||||||
let packagePath = GBUtil.getGBAIPath(min.botId, `gbot`);
|
let packagePath = GBUtil.getGBAIPath(min.botId, `gbot`);
|
||||||
const config = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath, 'config.csv');
|
const config = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath, 'config.csv');
|
||||||
|
|
||||||
|
@ -836,8 +863,31 @@ await fs.writeFile('.env', env);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ensureFolders(instances, deployer: GBDeployer) {
|
public async ensureFolders(instances, deployer: GBDeployer) {
|
||||||
|
const storageMode = process.env.GB_MODE;
|
||||||
let libraryPath = GBConfigService.get('STORAGE_LIBRARY');
|
let libraryPath = GBConfigService.get('STORAGE_LIBRARY');
|
||||||
|
|
||||||
|
if (storageMode === 'gbcluster') {
|
||||||
|
const minioClient = new Client({
|
||||||
|
endPoint: process.env.DRIVE_SERVER,
|
||||||
|
port: parseInt(process.env.DRIVE_PORT),
|
||||||
|
useSSL: process.env.DRIVE_USE_SSL === 'true',
|
||||||
|
accessKey: process.env.DRIVE_ACCESSKEY,
|
||||||
|
secretKey: process.env.DRIVE_SECRET,
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.syncBotStorage(instances, 'default', deployer, libraryPath);
|
||||||
|
|
||||||
|
const bucketStream = await minioClient.listBuckets();
|
||||||
|
|
||||||
|
for await (const bucket of bucketStream) {
|
||||||
|
if (bucket.name.endsWith('.gbai') && bucket.name.startsWith(process.env.DRIVE_ORG_PREFIX)) {
|
||||||
|
|
||||||
|
const botId = bucket.name.replace('.gbai', '').replace(process.env.DRIVE_ORG_PREFIX, '');
|
||||||
|
await this.syncBotStorage(instances, botId, deployer, libraryPath);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (!(await GBUtil.exists(libraryPath))) {
|
if (!(await GBUtil.exists(libraryPath))) {
|
||||||
mkdirp.sync(libraryPath);
|
mkdirp.sync(libraryPath);
|
||||||
}
|
}
|
||||||
|
@ -845,20 +895,24 @@ await fs.writeFile('.env', env);
|
||||||
await this.syncBotStorage(instances, 'default', deployer, libraryPath);
|
await this.syncBotStorage(instances, 'default', deployer, libraryPath);
|
||||||
|
|
||||||
const files = await fs.readdir(libraryPath);
|
const files = await fs.readdir(libraryPath);
|
||||||
await CollectionUtil.asyncForEach(files, async file => {
|
await CollectionUtil.asyncForEach(files, async (file) => {
|
||||||
if (file.trim().toLowerCase() !== 'default.gbai' && file.charAt(0) !== '_') {
|
if (file.trim().toLowerCase() !== 'default.gbai' && file.charAt(0) !== '_') {
|
||||||
let botId = file.replace(/\.gbai/, '');
|
let botId = file.replace(/\.gbai/, '');
|
||||||
|
|
||||||
await this.syncBotStorage(instances, botId, deployer, libraryPath);
|
await this.syncBotStorage(instances, botId, deployer, libraryPath);
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async syncBotStorage(instances: any, botId: any, deployer: GBDeployer, libraryPath: string) {
|
private async syncBotStorage(instances: any, botId: any, deployer: GBDeployer, libraryPath: string) {
|
||||||
|
|
||||||
|
|
||||||
let instance = instances.find(p => p.botId.toLowerCase().trim() === botId.toLowerCase().trim());
|
let instance = instances.find(p => p.botId.toLowerCase().trim() === botId.toLowerCase().trim());
|
||||||
|
|
||||||
|
if (process.env.GB_MODE === 'local') {
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
GBLog.info(`Importing package ${botId}...`);
|
GBLog.info(`Importing package ${botId}.gbai...`);
|
||||||
|
|
||||||
// Creates a bot.
|
// Creates a bot.
|
||||||
|
|
||||||
|
@ -866,46 +920,16 @@ await fs.writeFile('.env', env);
|
||||||
email = null;
|
email = null;
|
||||||
|
|
||||||
instance = await deployer.deployBlankBot(botId, mobile, email);
|
instance = await deployer.deployBlankBot(botId, mobile, email);
|
||||||
|
instances.push(instance);
|
||||||
const gbaiPath = path.join(libraryPath, `${botId}.gbai`);
|
const gbaiPath = path.join(libraryPath, `${botId}.gbai`);
|
||||||
|
|
||||||
if (!(await GBUtil.exists(gbaiPath))) {
|
if (!(await GBUtil.exists(gbaiPath))) {
|
||||||
fs.mkdir(gbaiPath, { recursive: true });
|
fs.mkdir(gbaiPath, { recursive: true });
|
||||||
|
|
||||||
const base = path.join(process.env.PWD, 'templates', 'default.gbai');
|
|
||||||
|
|
||||||
fs.cp(path.join(base, `default.gbkb`), path.join(gbaiPath, `default.gbkb`), {
|
|
||||||
errorOnExist: false,
|
|
||||||
force: true,
|
|
||||||
recursive: true
|
|
||||||
});
|
|
||||||
fs.cp(path.join(base, `default.gbot`), path.join(gbaiPath, `default.gbot`), {
|
|
||||||
errorOnExist: false,
|
|
||||||
force: true,
|
|
||||||
recursive: true
|
|
||||||
});
|
|
||||||
fs.cp(path.join(base, `default.gbtheme`), path.join(gbaiPath, `default.gbtheme`), {
|
|
||||||
errorOnExist: false,
|
|
||||||
force: true,
|
|
||||||
recursive: true
|
|
||||||
});
|
|
||||||
fs.cp(path.join(base, `default.gbdata`), path.join(gbaiPath, `default.gbdata`), {
|
|
||||||
errorOnExist: false,
|
|
||||||
force: true,
|
|
||||||
recursive: true
|
|
||||||
});
|
|
||||||
fs.cp(path.join(base, `default.gbdialog`), path.join(gbaiPath, `default.gbdialog`), {
|
|
||||||
errorOnExist: false,
|
|
||||||
force: true,
|
|
||||||
recursive: true
|
|
||||||
});
|
|
||||||
fs.cp(path.join(base, `default.gbdrive`), path.join(gbaiPath, `default.gbdrive`), {
|
|
||||||
errorOnExist: false,
|
|
||||||
force: true,
|
|
||||||
recursive: true
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
public static async createWebDavServer(minInstances: GBMinInstance[]) {
|
public static async createWebDavServer(minInstances: GBMinInstance[]) {
|
||||||
const userManager = new webdav.SimpleUserManager();
|
const userManager = new webdav.SimpleUserManager();
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -39,6 +39,8 @@ import express from 'express';
|
||||||
import child_process from 'child_process';
|
import child_process from 'child_process';
|
||||||
import { rimraf } from 'rimraf';
|
import { rimraf } from 'rimraf';
|
||||||
import urlJoin from 'url-join';
|
import urlJoin from 'url-join';
|
||||||
|
import { Client } from 'minio';
|
||||||
|
|
||||||
import fs from 'fs/promises';
|
import fs from 'fs/promises';
|
||||||
import { GBError, GBLog, GBMinInstance, IGBCoreService, IGBDeployer, IGBInstance, IGBPackage } from 'botlib';
|
import { GBError, GBLog, GBMinInstance, IGBCoreService, IGBDeployer, IGBInstance, IGBPackage } from 'botlib';
|
||||||
import { AzureSearch } from 'pragmatismo-io-framework';
|
import { AzureSearch } from 'pragmatismo-io-framework';
|
||||||
|
@ -47,7 +49,7 @@ import { GBServer } from '../../../src/app.js';
|
||||||
import { GBVMService } from '../../basic.gblib/services/GBVMService.js';
|
import { GBVMService } from '../../basic.gblib/services/GBVMService.js';
|
||||||
import Excel from 'exceljs';
|
import Excel from 'exceljs';
|
||||||
import asyncPromise from 'async-promises';
|
import asyncPromise from 'async-promises';
|
||||||
import { GuaribasPackage } from '../models/GBModel.js';
|
import { GuaribasInstance, GuaribasPackage } from '../models/GBModel.js';
|
||||||
import { GBAdminService } from './../../admin.gbapp/services/GBAdminService.js';
|
import { GBAdminService } from './../../admin.gbapp/services/GBAdminService.js';
|
||||||
import { AzureDeployerService } from './../../azuredeployer.gbapp/services/AzureDeployerService.js';
|
import { AzureDeployerService } from './../../azuredeployer.gbapp/services/AzureDeployerService.js';
|
||||||
import { KBService } from './../../kb.gbapp/services/KBService.js';
|
import { KBService } from './../../kb.gbapp/services/KBService.js';
|
||||||
|
@ -220,7 +222,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
const instance = await this.importer.createBotInstance(botId);
|
const instance = await this.importer.createBotInstance(botId);
|
||||||
const bootInstance = GBServer.globals.bootInstance;
|
const bootInstance = GBServer.globals.bootInstance;
|
||||||
|
|
||||||
if (GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
// Gets the access token to perform service operations.
|
// Gets the access token to perform service operations.
|
||||||
|
|
||||||
const accessToken = await (GBServer.globals.minBoot.adminService as any)['acquireElevatedToken'](
|
const accessToken = await (GBServer.globals.minBoot.adminService as any)['acquireElevatedToken'](
|
||||||
|
@ -232,13 +234,14 @@ export class GBDeployer implements IGBDeployer {
|
||||||
|
|
||||||
const service = await AzureDeployerService.createInstance(this);
|
const service = await AzureDeployerService.createInstance(this);
|
||||||
const application = await service.createApplication(accessToken, botId);
|
const application = await service.createApplication(accessToken, botId);
|
||||||
|
|
||||||
// Fills new instance base information and get App secret.
|
// Fills new instance base information and get App secret.
|
||||||
|
|
||||||
instance.marketplaceId = (application as any).appId;
|
instance.marketplaceId = (application as any).appId;
|
||||||
instance.marketplacePassword = await service.createApplicationSecret(accessToken, (application as any).id);
|
instance.marketplacePassword = await service.createApplicationSecret(accessToken, (application as any).id);
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.adminPass = GBAdminService.getRndPassword();
|
instance.adminPass = await GBUtil.hashPassword(GBAdminService.getRndPassword());
|
||||||
instance.title = botId;
|
instance.title = botId;
|
||||||
instance.activationCode = instance.botId.substring(0, 15);
|
instance.activationCode = instance.botId.substring(0, 15);
|
||||||
instance.state = 'active';
|
instance.state = 'active';
|
||||||
|
@ -249,13 +252,14 @@ export class GBDeployer implements IGBDeployer {
|
||||||
// Saves bot information to the store.
|
// Saves bot information to the store.
|
||||||
|
|
||||||
await this.core.saveInstance(instance);
|
await this.core.saveInstance(instance);
|
||||||
if (GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
await this.deployBotOnAzure(instance, GBServer.globals.publicAddress);
|
await this.deployBotOnAzure(instance, GBServer.globals.publicAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Makes available bot to the channels and .gbui interfaces.
|
// Makes available bot to the channels and .gbui interfaces.
|
||||||
|
|
||||||
await GBServer.globals.minService.mountBot(instance);
|
const min = await GBServer.globals.minService.mountBot(instance);
|
||||||
|
GBServer.globals.minInstances.push(min);
|
||||||
|
|
||||||
// Creates remaining objects on the cloud and updates instance information.
|
// Creates remaining objects on the cloud and updates instance information.
|
||||||
|
|
||||||
|
@ -266,9 +270,22 @@ export class GBDeployer implements IGBDeployer {
|
||||||
* Verifies if bot exists on bot catalog.
|
* Verifies if bot exists on bot catalog.
|
||||||
*/
|
*/
|
||||||
public async botExists(botId: string): Promise<boolean> {
|
public async botExists(botId: string): Promise<boolean> {
|
||||||
|
|
||||||
|
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
||||||
|
const where = { botId: botId };
|
||||||
|
|
||||||
|
return await GuaribasInstance.findOne({
|
||||||
|
where: where
|
||||||
|
}) !== null;
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
const service = await AzureDeployerService.createInstance(this);
|
const service = await AzureDeployerService.createInstance(this);
|
||||||
|
|
||||||
return await service.botExists(botId);
|
return await service.botExists(botId);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -354,9 +371,20 @@ export class GBDeployer implements IGBDeployer {
|
||||||
vectorStore = await HNSWLib.load(min['vectorStorePath'], embedding);
|
vectorStore = await HNSWLib.load(min['vectorStorePath'], embedding);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
GBLogEx.info(min, `Creating new store...`);
|
GBLogEx.info(min, `Creating new store...`);
|
||||||
vectorStore = new HNSWLib(embedding, {
|
vectorStore = await HNSWLib.fromTexts(
|
||||||
space: 'cosine'
|
['This is General Bots.'], // Initial texts (empty)
|
||||||
});
|
{}, // Optional metadata
|
||||||
|
embedding,
|
||||||
|
{
|
||||||
|
'space': 'cosine',
|
||||||
|
} as any
|
||||||
|
);
|
||||||
|
const dir = path.dirname(min['vectorStorePath']);
|
||||||
|
if (!(await GBUtil.exists(dir))) {
|
||||||
|
fs.mkdir(dir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
await vectorStore.save(min['vectorStorePath']);
|
||||||
}
|
}
|
||||||
return vectorStore;
|
return vectorStore;
|
||||||
}
|
}
|
||||||
|
@ -466,7 +494,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
} else {
|
} else {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
1
|
||||||
await asyncPromise.eachSeries(rows, async (line: any) => {
|
await asyncPromise.eachSeries(rows, async (line: any) => {
|
||||||
if (line && line.length > 0) {
|
if (line && line.length > 0) {
|
||||||
const key = line[1];
|
const key = line[1];
|
||||||
|
@ -487,64 +515,106 @@ export class GBDeployer implements IGBDeployer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public async downloadFolder(
|
public async downloadFolder(
|
||||||
min: GBMinInstance,
|
min: GBMinInstance,
|
||||||
localPath: string,
|
localPath: string,
|
||||||
remotePath: string,
|
remotePath: string,
|
||||||
baseUrl: string = null,
|
baseUrl: string = null,
|
||||||
client = null
|
client = null, onlyTextFiles = false
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
GBLogEx.info(min, `downloadFolder: localPath=${localPath}, remotePath=${remotePath}, baseUrl=${baseUrl}`);
|
const storageMode = process.env.GB_MODE;
|
||||||
|
|
||||||
|
if (storageMode === 'gbcluster') {
|
||||||
|
const minioClient = new Client({
|
||||||
|
endPoint: process.env.DRIVE_SERVER || 'localhost',
|
||||||
|
port: parseInt(process.env.DRIVE_PORT || '9000', 10),
|
||||||
|
useSSL: process.env.DRIVE_USE_SSL === 'true',
|
||||||
|
accessKey: process.env.DRIVE_ACCESSKEY,
|
||||||
|
secretKey: process.env.DRIVE_SECRET,
|
||||||
|
});
|
||||||
|
|
||||||
|
const bucketName = (process.env.DRIVE_ORG_PREFIX + min.botId + '.gbai').toLowerCase();
|
||||||
|
|
||||||
|
if (!(await GBUtil.exists(localPath))) {
|
||||||
|
await fs.mkdir(localPath, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const objectsStream = minioClient.listObjects(bucketName, remotePath, true);
|
||||||
|
for await (const obj of objectsStream) {
|
||||||
|
const itemPath = path.join(localPath, obj.name);
|
||||||
|
|
||||||
|
if (obj.name.endsWith('/')) {
|
||||||
|
if (!(await GBUtil.exists(itemPath))) {
|
||||||
|
await fs.mkdir(itemPath, { recursive: true });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let download = true;
|
||||||
|
|
||||||
|
if (await GBUtil.exists(itemPath)) {
|
||||||
|
const stats = await fs.stat(itemPath);
|
||||||
|
if (stats.mtime >= new Date(obj.lastModified)) {
|
||||||
|
download = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only download text files if onlyTextFiles flag is set
|
||||||
|
if (onlyTextFiles) {
|
||||||
|
// Check if file is NOT one of the allowed text file types
|
||||||
|
if (!obj.name.match(/\.(txt|json|csv|xlsx?|xlsm|xlsb|xml|html?|md|docx?|pdf|pptx?)$/i)) {
|
||||||
|
download = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (download) {
|
||||||
|
await minioClient.fGetObject(bucketName, obj.name, itemPath);
|
||||||
|
await fs.utimes(itemPath, new Date(), new Date(obj.lastModified));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (!baseUrl) {
|
if (!baseUrl) {
|
||||||
let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
const { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
||||||
|
|
||||||
remotePath = remotePath.replace(/\\/gi, '/');
|
remotePath = remotePath.replace(/\\/gi, '/');
|
||||||
const parts = remotePath.split('/');
|
const parts = remotePath.split('/');
|
||||||
|
|
||||||
// Creates each subfolder.
|
|
||||||
|
|
||||||
let pathBase = localPath;
|
let pathBase = localPath;
|
||||||
if (!(await GBUtil.exists(pathBase))) {
|
if (!(await GBUtil.exists(pathBase))) {
|
||||||
fs.mkdir(pathBase);
|
await fs.mkdir(pathBase, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(parts, async item => {
|
await CollectionUtil.asyncForEach(parts, async (item) => {
|
||||||
pathBase = path.join(pathBase, item);
|
pathBase = path.join(pathBase, item);
|
||||||
if (!(await GBUtil.exists(pathBase))) {
|
if (!(await GBUtil.exists(pathBase))) {
|
||||||
fs.mkdir(pathBase);
|
await fs.mkdir(pathBase, { recursive: true });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Retrieves all files in remote folder.
|
|
||||||
|
|
||||||
let packagePath = GBUtil.getGBAIPath(min.botId);
|
let packagePath = GBUtil.getGBAIPath(min.botId);
|
||||||
packagePath = urlJoin(packagePath, remotePath);
|
packagePath = urlJoin(packagePath, remotePath);
|
||||||
let url = `${baseUrl}/drive/root:/${packagePath}:/children`;
|
let url = `${baseUrl}/drive/root:/${packagePath}:/children`;
|
||||||
|
|
||||||
GBLogEx.info(min, `Downloading: ${url}`);
|
|
||||||
let documents;
|
let documents;
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await client.api(url).get();
|
const res = await client.api(url).get();
|
||||||
documents = res.value;
|
documents = res.value;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
GBLogEx.info(min, `Error downloading: ${error.toString()}`);
|
GBLogEx.info(min, `Error downloading: ${error.toString()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (documents === undefined || documents.length === 0) {
|
if (documents === undefined || documents.length === 0) {
|
||||||
GBLogEx.info(min, `${remotePath} is an empty folder.`);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Download files or navigate to directory to recurse.
|
await CollectionUtil.asyncForEach(documents, async (item) => {
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(documents, async item => {
|
|
||||||
const itemPath = path.join(localPath, remotePath, item.name);
|
const itemPath = path.join(localPath, remotePath, item.name);
|
||||||
|
|
||||||
if (item.folder) {
|
if (item.folder) {
|
||||||
if (!(await GBUtil.exists(itemPath))) {
|
if (!(await GBUtil.exists(itemPath))) {
|
||||||
fs.mkdir(itemPath);
|
await fs.mkdir(itemPath, { recursive: true });
|
||||||
}
|
}
|
||||||
const nextFolder = urlJoin(remotePath, item.name);
|
const nextFolder = urlJoin(remotePath, item.name);
|
||||||
await this.downloadFolder(min, localPath, nextFolder);
|
await this.downloadFolder(min, localPath, nextFolder);
|
||||||
|
@ -552,28 +622,28 @@ export class GBDeployer implements IGBDeployer {
|
||||||
let download = true;
|
let download = true;
|
||||||
|
|
||||||
if (await GBUtil.exists(itemPath)) {
|
if (await GBUtil.exists(itemPath)) {
|
||||||
const dt = await fs.stat(itemPath);
|
const stats = await fs.stat(itemPath);
|
||||||
if (new Date(dt.mtime) >= new Date(item.lastModifiedDateTime)) {
|
if (new Date(stats.mtime) >= new Date(item.lastModifiedDateTime)) {
|
||||||
download = false;
|
download = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (download) {
|
if (download) {
|
||||||
GBLogEx.info(min, `Downloading: ${itemPath}...`);
|
|
||||||
const url = item['@microsoft.graph.downloadUrl'];
|
const url = item['@microsoft.graph.downloadUrl'];
|
||||||
|
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
await fs.writeFile(itemPath, Buffer.from(await response.arrayBuffer()), { encoding: null });
|
await fs.writeFile(itemPath, new Uint8Array(await response.arrayBuffer()), { encoding: null });
|
||||||
fs.utimes(itemPath, new Date(), new Date(item.lastModifiedDateTime));
|
await fs.utimes(itemPath, new Date(), new Date(item.lastModifiedDateTime));
|
||||||
} else {
|
|
||||||
GBLogEx.info(min, `Local is up to date: ${path.basename(itemPath)}...`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UndDeploys a bot to the storage.
|
* Undeploys a bot to the storage.
|
||||||
*/
|
*/
|
||||||
public async undeployBot(botId: string, packageName: string): Promise<void> {
|
public async undeployBot(botId: string, packageName: string): Promise<void> {
|
||||||
// Deletes Bot registration on cloud.
|
// Deletes Bot registration on cloud.
|
||||||
|
@ -621,13 +691,23 @@ export class GBDeployer implements IGBDeployer {
|
||||||
await this.cleanupPackage(min.instance, packageName);
|
await this.cleanupPackage(min.instance, packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') === 'local') {
|
||||||
const filePath = path.join(GBConfigService.get('STORAGE_LIBRARY'), gbai, packageName);
|
const filePath = path.join(GBConfigService.get('STORAGE_LIBRARY'), gbai, packageName);
|
||||||
await GBUtil.copyIfNewerRecursive(filePath, packageWorkFolder);
|
if (packageType === '.gbdrive' || packageType === '.gbdata') {
|
||||||
|
await GBUtil.copyIfNewerRecursive(filePath, packageWorkFolder, true);
|
||||||
} else {
|
} else {
|
||||||
|
await GBUtil.copyIfNewerRecursive(filePath, packageWorkFolder, false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (packageType === '.gbdrive' || packageType === '.gbdata') {
|
||||||
|
await this.downloadFolder(min, path.join('work', `${gbai}`), packageName, undefined, undefined, true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
await this.downloadFolder(min, path.join('work', `${gbai}`), packageName);
|
await this.downloadFolder(min, path.join('work', `${gbai}`), packageName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Asks for each .gbapp if it will handle the package publishing.
|
// Asks for each .gbapp if it will handle the package publishing.
|
||||||
|
|
||||||
|
@ -661,6 +741,10 @@ export class GBDeployer implements IGBDeployer {
|
||||||
// Deploy platform packages here accordingly to their extension.
|
// Deploy platform packages here accordingly to their extension.
|
||||||
|
|
||||||
switch (packageType) {
|
switch (packageType) {
|
||||||
|
case '.gbdrive':
|
||||||
|
break;
|
||||||
|
case '.gbdata':
|
||||||
|
break;
|
||||||
case '.gbot':
|
case '.gbot':
|
||||||
// Extracts configuration information from .gbot files.
|
// Extracts configuration information from .gbot files.
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -78,7 +78,7 @@ export class GBImporter {
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
instance = <IGBInstance>{};
|
instance = <IGBInstance>{};
|
||||||
instance.state = 'active';
|
instance.state = 'active';
|
||||||
instance.adminPass = GBConfigService.get('ADMIN_PASS');
|
instance.adminPass = await GBUtil.hashPassword( GBConfigService.get('ADMIN_PASS'));
|
||||||
instance.botId = GBConfigService.get('BOT_ID');
|
instance.botId = GBConfigService.get('BOT_ID');
|
||||||
instance.cloudSubscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
|
instance.cloudSubscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
|
||||||
instance.cloudLocation = GBConfigService.get('CLOUD_LOCATION');
|
instance.cloudLocation = GBConfigService.get('CLOUD_LOCATION');
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -37,6 +37,7 @@ import { createRpcServer } from '@push-rpc/core';
|
||||||
import AuthenticationContext from 'adal-node';
|
import AuthenticationContext from 'adal-node';
|
||||||
import arrayBufferToBuffer from 'arraybuffer-to-buffer';
|
import arrayBufferToBuffer from 'arraybuffer-to-buffer';
|
||||||
import { Semaphore } from 'async-mutex';
|
import { Semaphore } from 'async-mutex';
|
||||||
|
import { AccessToken } from 'livekit-server-sdk';
|
||||||
import { Mutex } from 'async-mutex';
|
import { Mutex } from 'async-mutex';
|
||||||
import chokidar from 'chokidar';
|
import chokidar from 'chokidar';
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
|
@ -105,6 +106,7 @@ import { GBConversationalService } from './GBConversationalService.js';
|
||||||
import { GBDeployer } from './GBDeployer.js';
|
import { GBDeployer } from './GBDeployer.js';
|
||||||
import { GBLogEx } from './GBLogEx.js';
|
import { GBLogEx } from './GBLogEx.js';
|
||||||
import { GBSSR } from './GBSSR.js';
|
import { GBSSR } from './GBSSR.js';
|
||||||
|
import Stripe from 'stripe';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minimal service layer for a bot and encapsulation of BOT Framework calls.
|
* Minimal service layer for a bot and encapsulation of BOT Framework calls.
|
||||||
|
@ -160,16 +162,15 @@ export class GBMinService {
|
||||||
// Servers default UI on root address '/' if web enabled.
|
// Servers default UI on root address '/' if web enabled.
|
||||||
|
|
||||||
if (process.env.DISABLE_WEB !== 'true' || process.env.ENABLE_INSTANCE_ON_URL) {
|
if (process.env.DISABLE_WEB !== 'true' || process.env.ENABLE_INSTANCE_ON_URL) {
|
||||||
|
|
||||||
// Servers the bot information object via HTTP so clients can get
|
// Servers the bot information object via HTTP so clients can get
|
||||||
// instance information stored on server.
|
// instance information stored on server.
|
||||||
GBServer.globals.server.use(cors({
|
GBServer.globals.server.use(
|
||||||
origin: 'http://localhost:8081',
|
cors({
|
||||||
|
origin: 'https://gb6.pragmatismo.com.br',
|
||||||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
||||||
allowedHeaders: ['Content-Type', 'Authorization', 'x-requested-with'
|
allowedHeaders: ['Content-Type', 'Authorization', 'x-requested-with', 'x-ms-bot-agent']
|
||||||
, 'x-ms-bot-agent'
|
})
|
||||||
]
|
);
|
||||||
}));
|
|
||||||
GBServer.globals.server.get('/instances/:botId', this.handleGetInstanceForClient.bind(this));
|
GBServer.globals.server.get('/instances/:botId', this.handleGetInstanceForClient.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,14 +212,11 @@ export class GBMinService {
|
||||||
const user = await sec.ensureUser(min, 'testuser', 'testuser', '', 'test', 'testuser', null);
|
const user = await sec.ensureUser(min, 'testuser', 'testuser', '', 'test', 'testuser', null);
|
||||||
const pid = GBVMService.createProcessInfo(user, min, 'api', null);
|
const pid = GBVMService.createProcessInfo(user, min, 'api', null);
|
||||||
|
|
||||||
const response = await client.apis.Conversations.Conversations_StartConversation(
|
const response = await client.apis.Conversations.Conversations_StartConversation({
|
||||||
{
|
|
||||||
userSystemId: user.userSystemId,
|
userSystemId: user.userSystemId,
|
||||||
userName: user.userName,
|
userName: user.userName,
|
||||||
pid: pid
|
pid: pid
|
||||||
}
|
});
|
||||||
|
|
||||||
);
|
|
||||||
const conversationId = response.obj.conversationId;
|
const conversationId = response.obj.conversationId;
|
||||||
GBServer.globals.debugConversationId = conversationId;
|
GBServer.globals.debugConversationId = conversationId;
|
||||||
|
|
||||||
|
@ -237,7 +235,7 @@ export class GBMinService {
|
||||||
name: 'test',
|
name: 'test',
|
||||||
channelIdEx: 'web',
|
channelIdEx: 'web',
|
||||||
pid: pid
|
pid: pid
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -424,7 +422,7 @@ export class GBMinService {
|
||||||
const packageTeams = urlJoin(`work`, GBUtil.getGBAIPath(instance.botId), manifest);
|
const packageTeams = urlJoin(`work`, GBUtil.getGBAIPath(instance.botId), manifest);
|
||||||
if (!(await GBUtil.exists(packageTeams))) {
|
if (!(await GBUtil.exists(packageTeams))) {
|
||||||
const data = await this.deployer.getBotManifest(instance);
|
const data = await this.deployer.getBotManifest(instance);
|
||||||
await fs.writeFile(packageTeams, data);
|
//await fs.writeFile(packageTeams, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serves individual URL for each bot user interface.
|
// Serves individual URL for each bot user interface.
|
||||||
|
@ -459,26 +457,78 @@ export class GBMinService {
|
||||||
|
|
||||||
this.createCheckHealthAddress(GBServer.globals.server, min, min.instance);
|
this.createCheckHealthAddress(GBServer.globals.server, min, min.instance);
|
||||||
|
|
||||||
|
GBServer.globals.server
|
||||||
|
.all(`/${min.instance.botId}/paymentSuccess`, async (req, res) => {
|
||||||
|
try {
|
||||||
|
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
|
||||||
|
GBLogEx.info(min, `Payment success webhook received for bot ${min.instance.botId}`);
|
||||||
|
|
||||||
|
const sessionId = req.query.session_id;
|
||||||
|
if (!sessionId) {
|
||||||
|
GBLogEx.info(min, 'No session_id parameter found in payment success callback');
|
||||||
|
return res.status(400).json({ success: false, error: 'Missing session_id parameter' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const session = await stripe.checkout.sessions.retrieve(sessionId);
|
||||||
|
|
||||||
|
if (session.payment_status === 'paid') {
|
||||||
|
GBLogEx.info(min, `Payment confirmed for session ${sessionId}`);
|
||||||
|
|
||||||
|
// Only for successful payment - send HTML to close window
|
||||||
|
res.send(`
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Payment Successful</title>
|
||||||
|
<script>
|
||||||
|
// Close the window after a short delay
|
||||||
|
setTimeout(() => {
|
||||||
|
window.close();
|
||||||
|
}, 1000);
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body style="text-align: center; padding: 40px; font-family: Arial;">
|
||||||
|
<h1 style="color: #4CAF50;">Payment Successful!</h1>
|
||||||
|
<p>General Bots: Your transaction was completed successfully.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`);
|
||||||
|
} else {
|
||||||
|
GBLogEx.info(min, `Payment not completed for session ${sessionId}`);
|
||||||
|
res.status(402).json({
|
||||||
|
success: false,
|
||||||
|
error: 'Payment not completed',
|
||||||
|
sessionId: sessionId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
GBLogEx.error(min, `Error processing payment success: ${error.message}`);
|
||||||
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
error: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.bind(min);
|
||||||
// Setups official handler for WhatsApp.
|
// Setups official handler for WhatsApp.
|
||||||
|
|
||||||
GBServer.globals.server
|
GBServer.globals.server
|
||||||
.all(`/${min.instance.botId}/whatsapp`, async (req, res) => {
|
.all(`/${min.instance.botId}/whatsapp`, async (req, res) => {
|
||||||
|
const challenge = (min.core['getParam'] as any)(min.instance, `Meta Challenge`, null, true);
|
||||||
|
|
||||||
const status = req.body?.entry?.[0]?.changes?.[0]?.value?.statuses?.[0];
|
const status = req.body?.entry?.[0]?.changes?.[0]?.value?.statuses?.[0];
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
GBLogEx.verbose(min, `WhatsApp: ${status.recipient_id} ${status.status}`);
|
GBLogEx.info(min, `WhatsApp: ${status.recipient_id} ${status.status}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.query['hub.mode'] === 'subscribe') {
|
if (req.query['hub.mode'] === 'subscribe') {
|
||||||
const val = req.query['hub.verify_token'];
|
const val = req.query['hub.verify_token'];
|
||||||
const challenge = (min.core['getParam'] as any)(min.instance, `Meta Challenge`, null, true);
|
|
||||||
|
|
||||||
if (challenge && val === challenge) {
|
if (challenge && val === challenge) {
|
||||||
res.send(req.query['hub.challenge']);
|
res.send(req.query['hub.challenge']);
|
||||||
res.status(200);
|
res.status(200);
|
||||||
GBLogEx.info(min, `Meta callback OK. ${JSON.stringify(req.query)}`);
|
|
||||||
} else {
|
} else {
|
||||||
res.status(401);
|
res.status(401);
|
||||||
}
|
}
|
||||||
|
@ -492,8 +542,13 @@ export class GBMinService {
|
||||||
// Not meta, multiples bots on root bot.
|
// Not meta, multiples bots on root bot.
|
||||||
|
|
||||||
if (!req.body.object) {
|
if (!req.body.object) {
|
||||||
|
if (req.body.To) {
|
||||||
const to = req.body.To.replace(/whatsapp\:\+/gi, '');
|
const to = req.body.To.replace(/whatsapp\:\+/gi, '');
|
||||||
whatsAppDirectLine = WhatsappDirectLine.botsByNumber[to];
|
whatsAppDirectLine = WhatsappDirectLine.botsByNumber[to];
|
||||||
|
} else {
|
||||||
|
const minBoot = GBServer.globals.minBoot as GBMinInstance;
|
||||||
|
whatsAppDirectLine = minBoot.whatsAppDirectLine;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (whatsAppDirectLine) {
|
if (whatsAppDirectLine) {
|
||||||
|
@ -502,6 +557,50 @@ export class GBMinService {
|
||||||
})
|
})
|
||||||
.bind(min);
|
.bind(min);
|
||||||
|
|
||||||
|
GBServer.globals.server.all(`/${min.instance.botId}/meeting-token`, async (req, res) => {
|
||||||
|
try {
|
||||||
|
// Add to your route handler
|
||||||
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||||
|
|
||||||
|
// 1. Validate request
|
||||||
|
const { room, identity, name } = req.query;
|
||||||
|
GBLog.info(`Meeting token asked. ${room} ${identity} ${name}`);
|
||||||
|
if (!room || !identity) {
|
||||||
|
return res.status(400).json({ error: 'Missing required parameters: room, identity' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Get API keys from config (replace with your actual config access)
|
||||||
|
const apiKey = process.env.LIVEKIT_API_KEY;
|
||||||
|
const apiSecret = process.env.LIVEKIT_API_SECRET;
|
||||||
|
if (!apiKey || !apiSecret) {
|
||||||
|
return res.status(500).json({ error: 'Server misconfigured' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Generate token
|
||||||
|
|
||||||
|
const token = new AccessToken(apiKey, apiSecret, {
|
||||||
|
identity: identity.toString(),
|
||||||
|
name: name?.toString() || identity.toString()
|
||||||
|
});
|
||||||
|
|
||||||
|
// 4. Set permissions
|
||||||
|
token.addGrant({
|
||||||
|
roomJoin: true,
|
||||||
|
room: room.toString(),
|
||||||
|
canPublish: true,
|
||||||
|
canSubscribe: true,
|
||||||
|
canPublishData: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// 6. Return JWT
|
||||||
|
const jwt = await token.toJwt();
|
||||||
|
res.json({ token: jwt });
|
||||||
|
} catch (err) {
|
||||||
|
GBLog.error(`Meeting token generation failed: ${err}`);
|
||||||
|
res.status(500).json({ error: 'Token generation failed' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
GBDeployer.mountGBKBAssets(`${botId}.gbkb`, botId, `${botId}.gbkb`);
|
GBDeployer.mountGBKBAssets(`${botId}.gbkb`, botId, `${botId}.gbkb`);
|
||||||
|
|
||||||
return min;
|
return min;
|
||||||
|
@ -529,26 +628,14 @@ export class GBMinService {
|
||||||
private createCheckHealthAddress(server: any, min: GBMinInstance, instance: IGBInstance) {
|
private createCheckHealthAddress(server: any, min: GBMinInstance, instance: IGBInstance) {
|
||||||
server.get(`/${min.instance.botId}/check`, async (req, res) => {
|
server.get(`/${min.instance.botId}/check`, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
// Performs the checking of WhatsApp API if enabled for this instance.
|
|
||||||
|
|
||||||
if (min.whatsAppDirectLine != undefined && instance.whatsappServiceKey !== null) {
|
|
||||||
if (!(await min.whatsAppDirectLine.check(min))) {
|
|
||||||
const error = `WhatsApp API lost connection for: ${min.botId}.`;
|
|
||||||
GBLog.error(error);
|
|
||||||
res.status(500).send(error);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GB is OK, so 200.
|
// GB is OK, so 200.
|
||||||
|
|
||||||
res.status(200).send(`General Bot ${min.botId} is healthly.`);
|
res.status(200).send(`General Bot ${min.botId} is healthly.`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// GB is not OK, 500 and detail the information on response content.
|
// GB is not OK, 500 and detail the information on response content.
|
||||||
|
|
||||||
GBLog.error(error);
|
GBLogEx.error(min, error);
|
||||||
res.status(500).send(error.toString());
|
res.status(500).send('Service with erros. Please, check service log.');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -682,7 +769,8 @@ export class GBMinService {
|
||||||
min.instance.authenticatorTenant,
|
min.instance.authenticatorTenant,
|
||||||
'/oauth2/authorize'
|
'/oauth2/authorize'
|
||||||
);
|
);
|
||||||
authorizationUrl = `${authorizationUrl}?response_type=code&client_id=${min.instance.marketplaceId
|
authorizationUrl = `${authorizationUrl}?response_type=code&client_id=${
|
||||||
|
min.instance.marketplaceId
|
||||||
}&redirect_uri=${urlJoin(process.env.BOT_URL, min.instance.botId, 'token')}`;
|
}&redirect_uri=${urlJoin(process.env.BOT_URL, min.instance.botId, 'token')}`;
|
||||||
GBLogEx.info(min, `HandleOAuthRequests: ${authorizationUrl}.`);
|
GBLogEx.info(min, `HandleOAuthRequests: ${authorizationUrl}.`);
|
||||||
res.redirect(authorizationUrl);
|
res.redirect(authorizationUrl);
|
||||||
|
@ -721,7 +809,7 @@ export class GBMinService {
|
||||||
|
|
||||||
let logo = this.core.getParam(instance, 'Logo', null);
|
let logo = this.core.getParam(instance, 'Logo', null);
|
||||||
|
|
||||||
logo = logo ? urlJoin(instance.botId, 'cache', logo) : 'images/logo-gb.png';
|
logo = logo ? urlJoin(instance.botId, 'cache', logo) : 'https://pragmatismo.com.br/icons/general-bots-text.svg';
|
||||||
|
|
||||||
let config = {
|
let config = {
|
||||||
instanceId: instance.instanceId,
|
instanceId: instance.instanceId,
|
||||||
|
@ -740,8 +828,12 @@ export class GBMinService {
|
||||||
color2: this.core.getParam(instance, 'Color2', null)
|
color2: this.core.getParam(instance, 'Color2', null)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
||||||
config['domain'] = `http://localhost:${GBConfigService.get('PORT')}/directline/${botId}`;
|
const url =
|
||||||
|
process.env.BOT_URL && !process.env.BOT_URL.includes('ngrok')
|
||||||
|
? process.env.BOT_URL
|
||||||
|
: `http://localhost:${GBConfigService.get('PORT')}`;
|
||||||
|
config['domain'] = urlJoin(url, 'directline', botId);
|
||||||
} else {
|
} else {
|
||||||
const webchatTokenContainer = await this.getWebchatToken(instance);
|
const webchatTokenContainer = await this.getWebchatToken(instance);
|
||||||
config['conversationId'] = webchatTokenContainer.conversationId;
|
config['conversationId'] = webchatTokenContainer.conversationId;
|
||||||
|
@ -812,9 +904,11 @@ export class GBMinService {
|
||||||
? instance.marketplacePassword
|
? instance.marketplacePassword
|
||||||
: GBConfigService.get('MARKETPLACE_SECRET')
|
: GBConfigService.get('MARKETPLACE_SECRET')
|
||||||
};
|
};
|
||||||
if (!GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
||||||
|
const url = process.env.BOT_URL || `http://localhost:${GBConfigService.get('PORT')}`;
|
||||||
|
|
||||||
startRouter(GBServer.globals.server, instance.botId);
|
startRouter(GBServer.globals.server, instance.botId);
|
||||||
config['clientOptions'] = { baseUri: `http://localhost:${GBConfigService.get('PORT')}` };
|
config['clientOptions'] = { baseUri: url };
|
||||||
}
|
}
|
||||||
|
|
||||||
const adapter = new BotFrameworkAdapter(config);
|
const adapter = new BotFrameworkAdapter(config);
|
||||||
|
@ -866,8 +960,7 @@ export class GBMinService {
|
||||||
min.sandBoxMap = {};
|
min.sandBoxMap = {};
|
||||||
min['scheduleMap'] = {};
|
min['scheduleMap'] = {};
|
||||||
min['conversationWelcomed'] = {};
|
min['conversationWelcomed'] = {};
|
||||||
if (await min.core.getParam(min.instance, 'Answer Mode', null) &&
|
if ((await min.core.getParam(min.instance, 'Answer Mode', null)) && !min['vectorStore']) {
|
||||||
!min['vectorStore']) {
|
|
||||||
const gbkbPath = GBUtil.getGBAIPath(min.botId, 'gbkb');
|
const gbkbPath = GBUtil.getGBAIPath(min.botId, 'gbkb');
|
||||||
min['vectorStorePath'] = path.join('work', gbkbPath, 'docs-vectorized');
|
min['vectorStorePath'] = path.join('work', gbkbPath, 'docs-vectorized');
|
||||||
min['vectorStore'] = await this.deployer.loadOrCreateEmptyVectorStore(min);
|
min['vectorStore'] = await this.deployer.loadOrCreateEmptyVectorStore(min);
|
||||||
|
@ -941,7 +1034,7 @@ export class GBMinService {
|
||||||
|
|
||||||
await min.whatsAppDirectLine.setup(true);
|
await min.whatsAppDirectLine.setup(true);
|
||||||
} else {
|
} else {
|
||||||
if (min !== minBoot && minBoot.instance.whatsappServiceKey && min.instance.webchatKey) {
|
if (min !== minBoot && minBoot.instance.whatsappServiceKey) {
|
||||||
min.whatsAppDirectLine = new WhatsappDirectLine(
|
min.whatsAppDirectLine = new WhatsappDirectLine(
|
||||||
min,
|
min,
|
||||||
min.botId,
|
min.botId,
|
||||||
|
@ -1040,7 +1133,6 @@ export class GBMinService {
|
||||||
// Default activity processing and handler.
|
// Default activity processing and handler.
|
||||||
|
|
||||||
const handler = async context => {
|
const handler = async context => {
|
||||||
|
|
||||||
// Handle activity text issues.
|
// Handle activity text issues.
|
||||||
|
|
||||||
if (!context.activity.text) {
|
if (!context.activity.text) {
|
||||||
|
@ -1052,21 +1144,58 @@ export class GBMinService {
|
||||||
|
|
||||||
const step = await min.dialogs.createContext(context);
|
const step = await min.dialogs.createContext(context);
|
||||||
step.context.activity.locale = 'pt-BR';
|
step.context.activity.locale = 'pt-BR';
|
||||||
|
|
||||||
|
|
||||||
const sec = new SecService();
|
const sec = new SecService();
|
||||||
let member = context.activity.recipient;
|
let member = context.activity.recipient;
|
||||||
|
|
||||||
if (process.env.STORAGE_NAME || !member) {
|
if (context.activity.type === 'conversationUpdate') {
|
||||||
|
if (
|
||||||
|
context.activity.membersAdded &&
|
||||||
|
context.activity.membersAdded.length > 0 &&
|
||||||
|
context.activity.membersAdded[0].id === context.activity.recipient.id
|
||||||
|
) {
|
||||||
|
GBLogEx.info(min, `Bot added to conversation: ${member.name}`);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.GB_MODE === 'legacy' || !member) {
|
||||||
member = context.activity.from;
|
member = context.activity.from;
|
||||||
}
|
}
|
||||||
let user = await sec.ensureUser(min, member.id, member.name, '', 'web', member.name, null);
|
let user = await sec.ensureUser(min, member.id, member.name, '', 'web', member.name, null);
|
||||||
const userId = user.userId;
|
const userId = user.userId;
|
||||||
const params = user.params ? JSON.parse(user.params) : {};
|
const params = user.params ? JSON.parse(user.params) : {};
|
||||||
|
const t = new SystemKeywords();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const conversationReference = JSON.stringify(TurnContext.getConversationReference(context.activity));
|
const conversationReference = JSON.stringify(TurnContext.getConversationReference(context.activity));
|
||||||
user = await sec.updateConversationReferenceById(user.userId, conversationReference);
|
user = await sec.updateConversationReferenceById(user.userId, conversationReference);
|
||||||
|
let conversationId = step.context.activity.conversation.id;
|
||||||
|
|
||||||
|
let pid = GBMinService.pidsConversation[conversationId];
|
||||||
|
|
||||||
|
if (!pid) {
|
||||||
|
pid = step.context.activity['pid'];
|
||||||
|
if (!pid) {
|
||||||
|
pid = WhatsappDirectLine.pidByNumber[context.activity.from.id];
|
||||||
|
if (!pid) {
|
||||||
|
pid = GBVMService.createProcessInfo(user, min, step.context.activity.channelId, null, step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GBMinService.pidsConversation[conversationId] = pid;
|
||||||
|
step.context.activity['pid'] = pid;
|
||||||
|
|
||||||
|
const auth = min.core.getParam(min.instance, 'Enable Authentication', false);
|
||||||
|
|
||||||
|
if (auth) {
|
||||||
|
const res = await t.find({ pid: pid, handle: 'users.csv', args: [`key={member.id}`] });
|
||||||
|
|
||||||
|
if (!res) {
|
||||||
|
await min.conversationalService.sendText(min, step, 'Sorry, not authorized.');
|
||||||
|
res.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// First time processing.
|
// First time processing.
|
||||||
|
|
||||||
|
@ -1105,34 +1234,18 @@ export class GBMinService {
|
||||||
if (step.context.activity.channelId !== 'msteams') {
|
if (step.context.activity.channelId !== 'msteams') {
|
||||||
const service = new KBService(min.core.sequelize);
|
const service = new KBService(min.core.sequelize);
|
||||||
const data = await service.getFaqBySubjectArray(min.instance.instanceId, 'faq', undefined);
|
const data = await service.getFaqBySubjectArray(min.instance.instanceId, 'faq', undefined);
|
||||||
|
if (data.length > 0) {
|
||||||
await min.conversationalService.sendEvent(min, step, 'play', {
|
await min.conversationalService.sendEvent(min, step, 'play', {
|
||||||
playerType: 'bullet',
|
playerType: 'bullet',
|
||||||
data: data.slice(0, 10)
|
data: data.slice(0, 10)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let conversationId = step.context.activity.conversation.id;
|
|
||||||
|
|
||||||
let pid = GBMinService.pidsConversation[conversationId];
|
|
||||||
|
|
||||||
if (!pid) {
|
|
||||||
|
|
||||||
pid = step.context.activity['pid'];
|
|
||||||
if (!pid) {
|
|
||||||
pid = WhatsappDirectLine.pidByNumber[context.activity.from.id];
|
|
||||||
if (!pid) {
|
|
||||||
pid = GBVMService.createProcessInfo(user, min, step.context.activity.channelId, null, step);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
GBMinService.pidsConversation[conversationId] = pid;
|
|
||||||
step.context.activity['pid'] = pid;
|
|
||||||
|
|
||||||
const notes = min.core.getParam(min.instance, 'Notes', null);
|
const notes = min.core.getParam(min.instance, 'Notes', null);
|
||||||
if (await this.handleUploads(min, step, user, params, notes != null)) {
|
if (await this.handleUploads(min, step, user, params, notes != null)) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Required for MSTEAMS handling of persisted conversations.
|
// Required for MSTEAMS handling of persisted conversations.
|
||||||
|
@ -1146,7 +1259,6 @@ export class GBMinService {
|
||||||
);
|
);
|
||||||
const botToken = await credentials.getToken();
|
const botToken = await credentials.getToken();
|
||||||
const headers = { Authorization: `Bearer ${botToken}` };
|
const headers = { Authorization: `Bearer ${botToken}` };
|
||||||
const t = new SystemKeywords();
|
|
||||||
const data = await t.getByHttp({
|
const data = await t.getByHttp({
|
||||||
pid: 0,
|
pid: 0,
|
||||||
url: file.contentUrl,
|
url: file.contentUrl,
|
||||||
|
@ -1171,6 +1283,8 @@ export class GBMinService {
|
||||||
if (!(await sec.getParam(user, 'welcomed'))) {
|
if (!(await sec.getParam(user, 'welcomed'))) {
|
||||||
const startDialog = min.core.getParam(min.instance, 'Start Dialog', null);
|
const startDialog = min.core.getParam(min.instance, 'Start Dialog', null);
|
||||||
if (startDialog) {
|
if (startDialog) {
|
||||||
|
const t = new SystemKeywords();
|
||||||
|
t.setMemoryContext({ pid: pid, erase: true });
|
||||||
await sec.setParam(userId, 'welcomed', 'true');
|
await sec.setParam(userId, 'welcomed', 'true');
|
||||||
GBLogEx.info(
|
GBLogEx.info(
|
||||||
min,
|
min,
|
||||||
|
@ -1189,14 +1303,7 @@ export class GBMinService {
|
||||||
|
|
||||||
if (context.activity.type === 'installationUpdate') {
|
if (context.activity.type === 'installationUpdate') {
|
||||||
GBLogEx.info(min, `Bot installed on Teams.`);
|
GBLogEx.info(min, `Bot installed on Teams.`);
|
||||||
} else if (context.activity.type === 'conversationUpdate' &&
|
} else if (context.activity.type === 'conversationUpdate') {
|
||||||
context.activity.membersAdded.length > 0) {
|
|
||||||
// Check if a bot or a human participant is being added to the conversation.
|
|
||||||
|
|
||||||
const member = context.activity.membersAdded[0];
|
|
||||||
if (context.activity.membersAdded[0].id === context.activity.recipient.id) {
|
|
||||||
GBLogEx.info(min, `Bot added to conversation, starting chat...`);
|
|
||||||
|
|
||||||
// Calls onNewSession event on each .gbapp package.
|
// Calls onNewSession event on each .gbapp package.
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(appPackages, async e => {
|
await CollectionUtil.asyncForEach(appPackages, async e => {
|
||||||
|
@ -1210,12 +1317,11 @@ export class GBMinService {
|
||||||
|
|
||||||
await step.beginDialog('/');
|
await step.beginDialog('/');
|
||||||
} else {
|
} else {
|
||||||
if (
|
if (!GBMinService.userMobile(step) && !min['conversationWelcomed'][step.context.activity.conversation.id]) {
|
||||||
!GBMinService.userMobile(step) &&
|
|
||||||
!min['conversationWelcomed'][step.context.activity.conversation.id]
|
|
||||||
) {
|
|
||||||
|
|
||||||
const pid = GBVMService.createProcessInfo(user, min, step.context.activity.channelId, null, step);
|
const pid = GBVMService.createProcessInfo(user, min, step.context.activity.channelId, null, step);
|
||||||
|
const t = new SystemKeywords();
|
||||||
|
t.setMemoryContext({ pid: pid, erase: true });
|
||||||
|
|
||||||
step.context.activity['pid'] = pid;
|
step.context.activity['pid'] = pid;
|
||||||
|
|
||||||
min['conversationWelcomed'][step.context.activity.conversation.id] = true;
|
min['conversationWelcomed'][step.context.activity.conversation.id] = true;
|
||||||
|
@ -1227,15 +1333,7 @@ export class GBMinService {
|
||||||
await GBVMService.callVM(startDialog.toLowerCase(), min, step, pid);
|
await GBVMService.callVM(startDialog.toLowerCase(), min, step, pid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
GBLogEx.info(min, `Person added to conversation: ${member.name}`);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (context.activity.type === 'message') {
|
} else if (context.activity.type === 'message') {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Required for F0 handling of persisted conversations.
|
// Required for F0 handling of persisted conversations.
|
||||||
|
|
||||||
GBLogEx.info(
|
GBLogEx.info(
|
||||||
|
@ -1243,7 +1341,6 @@ export class GBMinService {
|
||||||
`Human: pid:${pid} ${context.activity.from.id} ${GBUtil.toYAML(WhatsappDirectLine.pidByNumber)} ${context.activity.text} (type: ${context.activity.type}, name: ${context.activity.name}, channelId: ${context.activity.channelId})`
|
`Human: pid:${pid} ${context.activity.from.id} ${GBUtil.toYAML(WhatsappDirectLine.pidByNumber)} ${context.activity.text} (type: ${context.activity.type}, name: ${context.activity.name}, channelId: ${context.activity.channelId})`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// Processes messages activities.
|
// Processes messages activities.
|
||||||
|
|
||||||
await this.processMessageActivity(context, min, step, pid);
|
await this.processMessageActivity(context, min, step, pid);
|
||||||
|
@ -1266,10 +1363,10 @@ export class GBMinService {
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
||||||
const context = adapter['createContext'](req);
|
const context = adapter['createContext'](req);
|
||||||
context['_activity'] = context.activity.body;
|
context['_activity'] = context.activity.body;
|
||||||
await handler(context);
|
await adapter['processActivity'](req, res, handler);
|
||||||
|
|
||||||
// Return status
|
// Return status
|
||||||
res.status(200);
|
res.status(200);
|
||||||
|
@ -1302,12 +1399,13 @@ export class GBMinService {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (context.activity.name === 'showSubjects') {
|
if (context.activity.name === 'showSubjects') {
|
||||||
await step.replaceDialog('/answer', { query: `Show a list of subjects you can help me in ${contentLocale} language.` });
|
await step.replaceDialog('/answer', {
|
||||||
|
query: `Show a list of subjects you can help me in ${contentLocale} language.`
|
||||||
|
});
|
||||||
} else if (context.activity.name === 'showFAQ') {
|
} else if (context.activity.name === 'showFAQ') {
|
||||||
await step.replaceDialog('/answer', { query: `Show a FAQ for me about how can you help me in a bullet list, in ${contentLocale} language.` });
|
await step.replaceDialog('/answer', {
|
||||||
|
query: `Show a FAQ for me about how can you help me in a bullet list, in ${contentLocale} language.`
|
||||||
|
});
|
||||||
} else if (context.activity.name === 'answerEvent') {
|
} else if (context.activity.name === 'answerEvent') {
|
||||||
await step.beginDialog('/answerEvent', <AskDialogArgs>{
|
await step.beginDialog('/answerEvent', <AskDialogArgs>{
|
||||||
questionId: context.activity.data,
|
questionId: context.activity.data,
|
||||||
|
@ -1393,7 +1491,6 @@ export class GBMinService {
|
||||||
const successfulSaves = await Promise.all(promises);
|
const successfulSaves = await Promise.all(promises);
|
||||||
async function replyForReceivedAttachments(attachmentData) {
|
async function replyForReceivedAttachments(attachmentData) {
|
||||||
if (attachmentData) {
|
if (attachmentData) {
|
||||||
|
|
||||||
// In case of not having HEAR activated before, it is
|
// In case of not having HEAR activated before, it is
|
||||||
// a upload with no Dialog, so run Auto Save to .gbdrive.
|
// a upload with no Dialog, so run Auto Save to .gbdrive.
|
||||||
|
|
||||||
|
@ -1437,16 +1534,16 @@ export class GBMinService {
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const results = await successfulSaves.reduce(async (accum: GBFile[], item) => {
|
const results = (await successfulSaves.reduce(async (accum: GBFile[], item) => {
|
||||||
const result: GBFile = {
|
const result: GBFile = {
|
||||||
data: await fs.readFile(successfulSaves[0]['filename']),
|
data: await fs.readFile(successfulSaves[0]['filename']),
|
||||||
filename: successfulSaves[0]['filename'],
|
filename: successfulSaves[0]['filename'],
|
||||||
name: successfulSaves[0]['name'],
|
name: successfulSaves[0]['name'],
|
||||||
url: successfulSaves[0]['url'],
|
url: successfulSaves[0]['url']
|
||||||
};
|
};
|
||||||
accum.push(result);
|
accum.push(result);
|
||||||
return accum;
|
return accum;
|
||||||
}, []) as GBFile[];
|
}, [])) as GBFile[];
|
||||||
|
|
||||||
if (min.cbMap[user.userId] && min.cbMap[user.userId].promise == '!GBHEAR') {
|
if (min.cbMap[user.userId] && min.cbMap[user.userId].promise == '!GBHEAR') {
|
||||||
if (results.length > 1) {
|
if (results.length > 1) {
|
||||||
|
@ -1554,15 +1651,15 @@ export class GBMinService {
|
||||||
!step.context.activity['group']
|
!step.context.activity['group']
|
||||||
) {
|
) {
|
||||||
await sec.setParam(userId, 'welcomed', 'true');
|
await sec.setParam(userId, 'welcomed', 'true');
|
||||||
|
const t = new SystemKeywords();
|
||||||
|
t.setMemoryContext({ pid: pid, erase: true });
|
||||||
|
|
||||||
min['conversationWelcomed'][step.context.activity.conversation.id] = true;
|
min['conversationWelcomed'][step.context.activity.conversation.id] = true;
|
||||||
GBLogEx.info(
|
GBLogEx.info(
|
||||||
min,
|
min,
|
||||||
`Auto start (4) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`
|
`Auto start (4) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`
|
||||||
);
|
);
|
||||||
await GBVMService.callVM(startDialog.toLowerCase(), min, step, pid);
|
await GBVMService.callVM(startDialog.toLowerCase(), min, step, pid);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1616,7 +1713,7 @@ export class GBMinService {
|
||||||
// Removes unwanted chars in input text.
|
// Removes unwanted chars in input text.
|
||||||
|
|
||||||
step.context.activity['originalText'] = context.activity.text;
|
step.context.activity['originalText'] = context.activity.text;
|
||||||
const text = await GBConversationalService.handleText(min, user, step, context.activity.text);
|
const text = context.activity.text;
|
||||||
step.context.activity['originalText'];
|
step.context.activity['originalText'];
|
||||||
step.context.activity['text'] = text;
|
step.context.activity['text'] = text;
|
||||||
|
|
||||||
|
@ -1662,7 +1759,8 @@ export class GBMinService {
|
||||||
try {
|
try {
|
||||||
await step.continueDialog();
|
await step.continueDialog();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const msg = `ERROR: ${error.message} ${error.stack} ${error.error ? error.error.body : ''} ${error.error ? (error.error.stack ? error.error.stack : '') : ''
|
const msg = `ERROR: ${error.message} ${error.stack} ${error.error ? error.error.body : ''} ${
|
||||||
|
error.error ? (error.error.stack ? error.error.stack : '') : ''
|
||||||
}`;
|
}`;
|
||||||
GBLog.error(msg);
|
GBLog.error(msg);
|
||||||
await min.conversationalService.sendText(
|
await min.conversationalService.sendText(
|
||||||
|
@ -1810,7 +1908,7 @@ export class GBMinService {
|
||||||
private mutex: Mutex = new Mutex();
|
private mutex: Mutex = new Mutex();
|
||||||
|
|
||||||
public async watchPackages(min: GBMinInstance, packageType: string): Promise<void> {
|
public async watchPackages(min: GBMinInstance, packageType: string): Promise<void> {
|
||||||
if (!GBConfigService.get('STORAGE_NAME')) {
|
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
||||||
const packagePath = GBUtil.getGBAIPath(min.botId, packageType);
|
const packagePath = GBUtil.getGBAIPath(min.botId, packageType);
|
||||||
const libraryPath = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath);
|
const libraryPath = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath);
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -99,6 +99,7 @@ export class GBSSR {
|
||||||
'--disable-features=site-per-process',
|
'--disable-features=site-per-process',
|
||||||
'--disable-gpu',
|
'--disable-gpu',
|
||||||
'--no-first-run',
|
'--no-first-run',
|
||||||
|
'--no-sandbox',
|
||||||
'--no-default-browser-check'
|
'--no-default-browser-check'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -117,7 +118,7 @@ export class GBSSR {
|
||||||
return {
|
return {
|
||||||
args: args,
|
args: args,
|
||||||
ignoreHTTPSErrors: true,
|
ignoreHTTPSErrors: true,
|
||||||
headless: false,
|
headless: process.env.CHROME_HEADLESS === 'true',
|
||||||
defaultViewport: null,
|
defaultViewport: null,
|
||||||
executablePath: process.env.CHROME_PATH ? process.env.CHROME_PATH : executablePath(),
|
executablePath: process.env.CHROME_PATH ? process.env.CHROME_PATH : executablePath(),
|
||||||
ignoreDefaultArgs: ['--enable-automation', '--enable-blink-features=IdleDetection']
|
ignoreDefaultArgs: ['--enable-automation', '--enable-blink-features=IdleDetection']
|
||||||
|
@ -335,6 +336,9 @@ export class GBSSR {
|
||||||
if (GBServer.globals.wwwroot && url === '/') {
|
if (GBServer.globals.wwwroot && url === '/') {
|
||||||
packagePath = GBServer.globals.wwwroot + "/index.html"; // TODO.
|
packagePath = GBServer.globals.wwwroot + "/index.html"; // TODO.
|
||||||
}
|
}
|
||||||
|
if (!min && !url.startsWith("/images") && GBServer.globals.wwwroot) {
|
||||||
|
packagePath = path.join(GBServer.globals.wwwroot, url);
|
||||||
|
}
|
||||||
if (!min && !url.startsWith("/static") && GBServer.globals.wwwroot) {
|
if (!min && !url.startsWith("/static") && GBServer.globals.wwwroot) {
|
||||||
packagePath = path.join(GBServer.globals.wwwroot, url);
|
packagePath = path.join(GBServer.globals.wwwroot, url);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -55,6 +55,18 @@ export class QualityDialog extends IGBDialog {
|
||||||
public static setup(bot: BotAdapter, min: GBMinInstance) {
|
public static setup(bot: BotAdapter, min: GBMinInstance) {
|
||||||
const service = new CSService();
|
const service = new CSService();
|
||||||
|
|
||||||
|
min.dialogs.add(
|
||||||
|
new WaterfallDialog('/report', [
|
||||||
|
async step => {
|
||||||
|
const locale = step.context.activity.locale;
|
||||||
|
await min.conversationalService.sendText(min, step, await min.whatsAppDirectLine.getLatestCampaignReport());
|
||||||
|
return await step.replaceDialog('/ask', { isReturning: true });
|
||||||
|
}
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
min.dialogs.add(
|
min.dialogs.add(
|
||||||
new WaterfallDialog('/check', [
|
new WaterfallDialog('/check', [
|
||||||
async step => {
|
async step => {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
File diff suppressed because it is too large
Load diff
BIN
packages/default.gbui/public/images/generalbots-transparent.png
Normal file
BIN
packages/default.gbui/public/images/generalbots-transparent.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
BIN
packages/default.gbui/public/images/logo-gb.png
Normal file
BIN
packages/default.gbui/public/images/logo-gb.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3 KiB |
|
@ -6,7 +6,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
|
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||||
<link rel="stylesheet" type="text/css" href="/themes/{theme}/css/colors.css" />
|
<link rel="stylesheet" type="text/css" href="/themes/{theme}/css/colors.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="/themes/{theme}/css/default.css" />
|
<link rel="stylesheet" type="text/css" href="/themes/{theme}/css/default.css" />
|
||||||
<script src="./js/webchat.js"></script>
|
|
||||||
<title>{title} | General Bots</title>
|
<title>{title} | General Bots</title>
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -347,7 +347,7 @@ class GBUIApp extends React.Component {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (this.state.instanceClient) {
|
if (this.state.instanceClient) {
|
||||||
let color1 = this.state.instanceClient.color1;
|
|
||||||
gbCss = <GBCss instance={this.state.instanceClient} />;
|
gbCss = <GBCss instance={this.state.instanceClient} />;
|
||||||
seo = <SEO instance={this.state.instanceClient} />;
|
seo = <SEO instance={this.state.instanceClient} />;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
@ -35,7 +35,7 @@ const footer = () => (
|
||||||
<div className="footer-container">
|
<div className="footer-container">
|
||||||
General Bots Community Edition
|
General Bots Community Edition
|
||||||
<br/>
|
<br/>
|
||||||
<a href="http://pragmatismo.cloud">pragmatismo.cloud</a>
|
<a href="http://pragmatismo.com.br">pragmatismo.com.br</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
export default footer
|
export default footer
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,23 +21,22 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
| |
|
| |
|
||||||
\*****************************************************************************/
|
\*****************************************************************************/
|
||||||
|
|
||||||
import React from "react";
|
import React from 'react';
|
||||||
|
|
||||||
class SideBarMenu extends React.Component {
|
class SideBarMenu extends React.Component {
|
||||||
send(command) {
|
send(command) {
|
||||||
window.botConnection
|
window.botConnection.postActivity({
|
||||||
.postActivity({
|
type: 'event',
|
||||||
type: "event",
|
|
||||||
name: command,
|
name: command,
|
||||||
locale: "en-us",
|
locale: 'en-us',
|
||||||
textFormat: "plain",
|
textFormat: 'plain',
|
||||||
timestamp: new Date().toISOString()
|
timestamp: new Date().toISOString()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -46,41 +45,34 @@ class SideBarMenu extends React.Component {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="titleSideBarMenu">
|
<div className="titleSideBarMenu">
|
||||||
<img
|
<img className="pragmatismoLogo" width="64px" src={this.props.instance.logo} alt="General Bots Logo" />
|
||||||
className="pragmatismoLogo"
|
|
||||||
src={this.props.instance.logo}
|
|
||||||
alt="General Bots Logo" />
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div className="SidebarMenu">
|
<div className="SidebarMenu">
|
||||||
<div className="IconsMenu">
|
<div className="IconsMenu">
|
||||||
<div className="iconMenu">
|
<div className="iconMenu">
|
||||||
<span className="iconText" onClick={() => this.send("showFAQ")}>
|
<span className="iconText" onClick={() => this.send('showFAQ')}>
|
||||||
FAQ
|
FAQ
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="iconMenu">
|
<div className="iconMenu">
|
||||||
<span className="iconText"
|
<span
|
||||||
onClick={() => window.open(`https://pragmatismo.sharepoint.com/sites/bots/Online/${this.props.instance.botId}.gbai`)}
|
className="iconText"
|
||||||
|
onClick={() =>
|
||||||
|
window.open(`https://drive.pragmatismo.com.br/browser/${this.props.instance.botId}.gbai`)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
Drive
|
Drive
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="iconMenu">
|
<div className="iconMenu">
|
||||||
<span
|
<span className="iconText" onClick={() => this.send('showSubjects')}>
|
||||||
className="iconText"
|
|
||||||
onClick={() => this.send("showSubjects")}>
|
|
||||||
Subjects
|
Subjects
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="iconMenu">
|
<div className="iconMenu">
|
||||||
<span
|
<span className="iconText" onClick={() => window.open('mailto:talk@pragmatismo.com.br')}>
|
||||||
className="iconText"
|
|
||||||
onClick={() => window.open('mailto:talk@pragmatismo.cloud')}
|
|
||||||
>
|
|
||||||
Suggestions
|
Suggestions
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||||
| |
|
| |
|
||||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||||
| Licensed under the AGPL-3.0. |
|
| Licensed under the AGPL-3.0. |
|
||||||
| |
|
| |
|
||||||
| According to our dual licensing model, this program can be used either |
|
| According to our dual licensing model, this program can be used either |
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
| GNU Affero General Public License for more details. |
|
| GNU Affero General Public License for more details. |
|
||||||
| |
|
| |
|
||||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||||
| The licensing of the program under the AGPLv3 does not imply a |
|
| The licensing of the program under the AGPLv3 does not imply a |
|
||||||
| trademark license. Therefore any rights, title and interest in |
|
| trademark license. Therefore any rights, title and interest in |
|
||||||
| our trademarks remain entirely with us. |
|
| our trademarks remain entirely with us. |
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue