Compare commits
No commits in common. "main" and "rodrigorodriguez-patch-4" have entirely different histories.
main
...
rodrigorod
163 changed files with 4751 additions and 51903 deletions
2
.deployment
Normal file
2
.deployment
Normal file
|
@ -0,0 +1,2 @@
|
|||
[config]
|
||||
command = bash ./deploy.sh
|
|
@ -1,46 +0,0 @@
|
|||
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
Normal file
9
.github/ISSUE_TEMPLATE.md
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
<!-- 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
Normal file
35
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
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
Normal file
7
.github/ISSUE_TEMPLATE/custom.md
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
name: Custom issue template
|
||||
about: Describe this issue template's purpose here.
|
||||
|
||||
---
|
||||
|
||||
|
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
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
Normal file
2
.github/ISSUE_TEMPLATE/requirement
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
**Description**
|
||||
A clear and concise description of what the requirement is.
|
16
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
16
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
### 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
Normal file
3
.github/invite-contributors.yml
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
isOutside: true
|
||||
# Team Name
|
||||
team: contributors
|
44
.github/settings.yml
vendored
Normal file
44
.github/settings.yml
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
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,10 +25,9 @@ GB.log
|
|||
gb.log
|
||||
GB.log.json
|
||||
yarn-error.log
|
||||
package-lock.json
|
||||
yarn-lock.json
|
||||
logo.svg
|
||||
screenshot.png
|
||||
data.db
|
||||
.wwebjs_cache
|
||||
*doula*
|
||||
*botpoc*
|
33
.travis.yml
Normal file
33
.travis.yml
Normal file
|
@ -0,0 +1,33 @@
|
|||
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
Normal file
30
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"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
Normal file
4
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"git.ignoreLimitWarning": true,
|
||||
"cmake.ignoreCMakeListsMissing": true
|
||||
}
|
30
.vscode/tasks.json
vendored
Normal file
30
.vscode/tasks.json
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
// 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
|
||||
|
||||
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.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.
|
||||
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.
|
||||
|
||||
## Contributing features
|
||||
|
||||
|
@ -40,7 +40,7 @@ Please open an issue with the `Schema` label to get a discussion started.
|
|||
|
||||
## Legal
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
## Housekeeping
|
||||
|
||||
|
|
8
FEATURES.md
Normal file
8
FEATURES.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
# 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
|
||||
edition of General bots you have installed, please ask info@pragmatismo.com.br
|
||||
edition of General bots you have installed, please ask info@pragmatismo.cloud
|
||||
informing your Customer ID.
|
||||
|
||||
If you modify this Program, or any covered work, by combining it
|
||||
|
|
7
LOCALIZATION.md
Normal file
7
LOCALIZATION.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
# Localization in General Bots
|
||||
|
||||
## .gbapp
|
||||
|
||||
The localization is done by adding a strings.ts file to the root of the .gbapp package.
|
||||
|
115
README.md
115
README.md
|
@ -1,19 +1,16 @@
|
|||
### Key Facts
|
||||
- LLM Orchestrator AGPL licensed (to use as custom-label SaaS, contributing back)
|
||||
- AGPL License (to use as custom-label SaaS)
|
||||
- True community governance
|
||||
- No single corporate control
|
||||
- 5+ years of stability
|
||||
- Never changed license
|
||||
- Enterprise-grad
|
||||
- Hosted locally or Multicloud
|
||||
|
||||
## Contributors
|
||||
|
||||
|
||||
<a href="https://github.com/generalbots/botserver/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=generalbots/botserver" />
|
||||
</a>
|
||||
|
||||
## Overview
|
||||
|
||||
| Area | Status |
|
||||
|------------------------------|----------------------------------------------------------------------------------------------------|
|
||||
|
@ -21,16 +18,17 @@
|
|||
| Community | [](https://stackoverflow.com/questions/tagged/generalbots) [](https://badges.frapsoft.com) [](http://makeapullrequest.com) [](https://github.com/GeneralBots/BotServer/blob/master/LICENSE.txt)|
|
||||
| Management | [](https://gitHub.com/GeneralBots/BotServer/graphs/commit-activity) |
|
||||
| Security | [](https://snyk.io/test/github/GeneralBots/BotServer) |
|
||||
| Building & Quality | [](https://coveralls.io/github/GeneralBots/BotServer) [](https://github.com/prettier/prettier) |
|
||||
| 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)
|
||||
| [Docker Image](https://github.com/lpicanco/docker-botserver)  <br/> *Provided by [@lpicanco](https://github.com/lpicanco/docker-botserver)* |
|
||||
| Building & Quality | [](https://app.travis-ci.com/github/GeneralBots/BotServer) [](https://coveralls.io/github/GeneralBots/BotServer) [](https://github.com/prettier/prettier) |
|
||||
| Packaging | [](https://badge.fury.io) [](https://github.com/GeneralBots/BotServer/releases/latest) [](https://david-dm.org) [](http://commitizen.github.io/cz-cli/) |
|
||||
| Samples | [VBA](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)* |
|
||||
|
||||
# General Bots
|
||||
General Bots
|
||||
------------------
|
||||
|
||||
)
|
||||

|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
## What is a Bot Server?
|
||||
|
||||
|
@ -44,78 +42,9 @@ 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
|
||||
favorite tools from Office (or any text editor) or Photoshop (or any image
|
||||
editor). LLM and BASIC can be mixed used to build custom dialogs so Bot can be extended just like VBA for Excel.
|
||||
editor). BASIC can be used to build custom dialogs so Bot can be extended just like VBA for Excel (currently in alpha).
|
||||
|
||||
## 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
|
||||
|
||||
|
@ -147,12 +76,18 @@ SEND FILE img
|
|||
|
||||
## Guide
|
||||
|
||||
[Read the General Bots BotBook Guide](https://docs.pragmatismo.com.br)
|
||||
[Read the General Bots BotBook Guide](https://github.com/GeneralBots/BotBook/tree/master/book).
|
||||
|
||||
# Videos
|
||||
|
||||
7 AI General Bots LLM Templates for Goodness
|
||||
[https://www.youtube.com/watch?v=KJgvUPXi3Fw](https://www.youtube.com/watch?v=KJgvUPXi3Fw)
|
||||
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.
|
||||
|
||||
[](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
|
||||
|
||||
|
@ -161,14 +96,14 @@ See our [Contribution Guidelines](https://github.com/pragmatismo-io/BotServer/bl
|
|||
|
||||
# Reporting Security Issues
|
||||
|
||||
Security issues and bugs should be reported privately, via email, to the pragmatismo.com.br Security
|
||||
team at [security@pragmatismo.com.br](mailto:security@pragmatismo.com.br). You should
|
||||
Security issues and bugs should be reported privately, via email, to the pragmatismo.cloud Security
|
||||
team at [security@pragmatismo.cloud](mailto:security@pragmatismo.cloud). You should
|
||||
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.
|
||||
|
||||
# License & Warranty
|
||||
|
||||
General Bot Copyright (c) pragmatismo.com.br. All rights reserved.
|
||||
General Bot Copyright (c) pragmatismo.cloud. All rights reserved.
|
||||
Licensed under the AGPL-3.0.
|
||||
|
||||
According to our dual licensing model, this program can be used either
|
||||
|
@ -184,7 +119,7 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
"General Bot" is a registered trademark of pragmatismo.com.br.
|
||||
"General Bot" is a registered trademark of pragmatismo.cloud.
|
||||
The licensing of the program under the AGPLv3 does not imply a
|
||||
trademark license. Therefore any rights, title and interest in
|
||||
our trademarks remain entirely with us.
|
||||
|
|
6
ROADMAP.md
Normal file
6
ROADMAP.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
# 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 | - |
|
7
SAMPLES.md
Normal file
7
SAMPLES.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
# 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.
|
||||
In the meantime, if you have any questions, suggestions
|
||||
or feedback, please contact security@pragmatismo.com.br
|
||||
or feedback, please contact security@pragmatismo.cloud
|
||||
|
||||
|
||||
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
|
||||
|
||||
You can expect to get an update on a reported vulnerability in a day or two.
|
||||
security@pragmatismo.com.br
|
||||
security@pragmatismo.cloud
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://generalbots.online/api",
|
||||
"url": "https://gb.pragmatismo.cloud/api",
|
||||
"description": "General Bots Online"
|
||||
}
|
||||
]
|
||||
|
|
2
boot.mjs
2
boot.mjs
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
process.stdout.write(`General Bots 5 VM: node@${process.version.replace('v', '')}, ${process.platform} ${process.arch} `);
|
||||
process.stdout.write(`General Bots VM: node@${process.version.replace('v', '')}, ${process.platform} ${process.arch} `);
|
||||
|
||||
import fs from 'fs/promises';
|
||||
import os from 'node:os';
|
||||
|
|
10
greenkeeper.json
Normal file
10
greenkeeper.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"groups": {
|
||||
"default": {
|
||||
"packages": [
|
||||
"package.json",
|
||||
"packages/default.gbui/package.json"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
BIN
logo.png
BIN
logo.png
Binary file not shown.
Before Width: | Height: | Size: 25 KiB |
48942
package-lock.json
generated
48942
package-lock.json
generated
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",
|
||||
"@sendgrid/mail": "8.1.3",
|
||||
"@sequelize/core": "7.0.0-alpha.37",
|
||||
"@sequelize/postgres": "^7.0.0-alpha.43",
|
||||
"@types/node": "22.5.2",
|
||||
"@types/validator": "13.12.1",
|
||||
"adm-zip": "0.5.16",
|
||||
"ai2html": "^0.121.1",
|
||||
|
@ -113,7 +113,6 @@
|
|||
"async-promises": "0.2.3",
|
||||
"async-retry": "1.3.3",
|
||||
"basic-auth": "2.0.1",
|
||||
"bcrypt": "^5.1.1",
|
||||
"billboard.js": "3.13.0",
|
||||
"bluebird": "3.7.2",
|
||||
"body-parser": "1.20.2",
|
||||
|
@ -170,13 +169,11 @@
|
|||
"langchain": "0.2.17",
|
||||
"language-tags": "1.0.9",
|
||||
"line-replace": "2.0.1",
|
||||
"livekit-server-sdk": "^2.12.0",
|
||||
"lodash": "4.17.21",
|
||||
"luxon": "3.5.0",
|
||||
"mammoth": "1.8.0",
|
||||
"mariadb": "3.3.1",
|
||||
"mime-types": "2.1.35",
|
||||
"minio": "^8.0.4",
|
||||
"moment": "2.30.1",
|
||||
"ms-rest-azure": "3.0.2",
|
||||
"mysql": "^2.18.1",
|
||||
|
@ -186,7 +183,6 @@
|
|||
"node-html-parser": "6.1.13",
|
||||
"node-nlp": "4.27.0",
|
||||
"node-tesseract-ocr": "2.2.1",
|
||||
"nodemailer": "6.10.1",
|
||||
"nodemon": "^3.1.7",
|
||||
"npm": "10.8.3",
|
||||
"open": "10.1.0",
|
||||
|
@ -196,7 +192,7 @@
|
|||
"pdf-parse": "1.1.1",
|
||||
"pdf-to-png-converter": "3.3.0",
|
||||
"pdfjs-dist": "4.6.82",
|
||||
"pg": "^8.13.1",
|
||||
"pdfkit": "0.15.0",
|
||||
"phone": "3.1.50",
|
||||
"pizzip": "3.1.7",
|
||||
"pptxtemplater": "1.0.5",
|
||||
|
@ -225,9 +221,6 @@
|
|||
"sqlite3": "5.1.7",
|
||||
"ssr-for-bots": "1.0.1-c",
|
||||
"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",
|
||||
"swagger-client": "3.29.2",
|
||||
"swagger-ui-dist": "5.17.14",
|
||||
|
@ -255,9 +248,6 @@
|
|||
"zod-to-json-schema": "3.23.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lodash": "^4.17.20",
|
||||
"@types/node": "^24.1.0",
|
||||
"@types/node-fetch": "^2.6.12",
|
||||
"@types/qrcode": "1.5.5",
|
||||
"@types/url-join": "4.0.3",
|
||||
"@typescript-eslint/eslint-plugin": "8.4.0",
|
||||
|
@ -271,6 +261,8 @@
|
|||
"prettier-standard": "16.4.1",
|
||||
"semantic-release": "24.1.0",
|
||||
"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",
|
||||
"tslint": "6.1.3",
|
||||
"tsx": "^4.19.1",
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -47,7 +47,6 @@ import { SecService } from '../../security.gbapp/services/SecService.js';
|
|||
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
|
||||
import { GBServer } from '../../../src/app.js';
|
||||
import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
|
||||
import { GBUtil } from '../../../src/util.js';
|
||||
|
||||
|
||||
class AdminDialog extends IGBDialog {
|
||||
|
@ -87,7 +86,7 @@ class AdminDialog extends IGBDialog {
|
|||
const locale = step.context.activity.locale;
|
||||
const sensitive = step.context.activity['originalText'];
|
||||
|
||||
if (await GBUtil.comparePassword( sensitive, min.instance.adminPass)) {
|
||||
if (sensitive === min.instance.adminPass) {
|
||||
await min.conversationalService.sendText(min, step, Messages[locale].welcome);
|
||||
|
||||
return await step.endDialog(true);
|
||||
|
@ -121,7 +120,7 @@ class AdminDialog extends IGBDialog {
|
|||
const locale = step.context.activity.locale;
|
||||
const sensitive = step.context.activity['originalText'];
|
||||
|
||||
if (await GBUtil.comparePassword( sensitive, min.instance.adminPass)) {
|
||||
if (sensitive === min.instance.adminPass) {
|
||||
await min.conversationalService.sendText(min, step, Messages[locale].welcome);
|
||||
|
||||
return await min.conversationalService.prompt(min, step, Messages[locale].which_task);
|
||||
|
@ -293,8 +292,6 @@ class AdminDialog extends IGBDialog {
|
|||
await min.conversationalService.sendText(min, step, `Starting publishing for ${botId} packages...`);
|
||||
packages.push(`${botId}.gbot`);
|
||||
packages.push(`${botId}.gbtheme`);
|
||||
packages.push(`${botId}.gbdrive`);
|
||||
packages.push(`${botId}.gbdata`);
|
||||
packages.push(`${botId}.gbkb`);
|
||||
packages.push(`${botId}.gbdialog`);
|
||||
skipError = true;
|
||||
|
@ -307,8 +304,6 @@ class AdminDialog extends IGBDialog {
|
|||
|
||||
if (
|
||||
packageName.toLowerCase() === 'gbdialog' ||
|
||||
packageName.toLowerCase() === 'gbdrive' ||
|
||||
packageName.toLowerCase() === 'gbdata' ||
|
||||
packageName.toLowerCase() === 'gbkb' ||
|
||||
packageName.toLowerCase() === 'gbot' ||
|
||||
packageName.toLowerCase() === 'gbtheme'
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -168,7 +168,7 @@ export class GBAdminService implements IGBAdminService {
|
|||
) {
|
||||
const packageName = text.split(' ')[1];
|
||||
|
||||
const folderName = text.substring(text.indexOf(packageName) + packageName.length + 1);
|
||||
const folderName = text.split(' ')[2];
|
||||
const packageType = path.extname(folderName).substr(1);
|
||||
const gbaiPath = GBUtil.getGBAIPath(min.instance.botId, packageType, null);
|
||||
const localFolder = path.join('work', gbaiPath);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
export const Messages = {
|
||||
'en-US': {
|
||||
authenticate: 'Please, authenticate:',
|
||||
welcome: 'Welcome to pragmatismo.com.br GeneralBots Administration.',
|
||||
welcome: 'Welcome to pragmatismo.cloud GeneralBots Administration.',
|
||||
which_task: 'Which task do you wanna run now?',
|
||||
working: command => `I'm working on ${command}...`,
|
||||
finished_working: 'Done.',
|
||||
|
@ -26,7 +26,7 @@ export const Messages = {
|
|||
},
|
||||
'pt-BR': {
|
||||
authenticate: 'Please, authenticate:',
|
||||
welcome: 'Welcome to pragmatismo.com.br GeneralBots Administration.',
|
||||
welcome: 'Welcome to pragmatismo.cloud GeneralBots Administration.',
|
||||
which_task: 'Which task do you wanna run now?',
|
||||
working: command => `I'm working on ${command}...`,
|
||||
finished_working: 'Done.',
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -111,7 +111,7 @@ export class StartDialog {
|
|||
instance.cloudLocation = location;
|
||||
instance.marketplaceId = appId;
|
||||
instance.marketplacePassword = appPassword;
|
||||
instance.adminPass = await GBUtil.hashPassword(GBAdminService.getRndPassword());
|
||||
instance.adminPass = GBAdminService.getRndPassword();
|
||||
|
||||
return { instance, credentials, subscriptionId , installationDeployer};
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -518,7 +518,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
instance.nlpAuthoringKey = authoringKey;
|
||||
instance.marketplaceId = appId;
|
||||
instance.marketplacePassword = appPassword;
|
||||
instance.adminPass = await GBUtil.hashPassword(GBAdminService.getRndPassword());
|
||||
instance.adminPass = GBAdminService.getRndPassword();
|
||||
|
||||
const credentials = await GBAdminService.getADALCredentialsFromUsername(username, password);
|
||||
// tslint:disable-next-line:no-http-string
|
||||
|
@ -986,6 +986,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
appSettings: [
|
||||
{ name: 'WEBSITES_CONTAINER_START_TIME_LIMIT', value: `${WebSiteResponseTimeout}` },
|
||||
{ name: 'WEBSITE_NODE_DEFAULT_VERSION', value: await GBAdminService.getNodeVersion() },
|
||||
{ name: 'ADMIN_PASS', value: `${instance.adminPass}` },
|
||||
{ name: 'BOT_ID', value: `${instance.botId}` },
|
||||
{ name: 'CLOUD_SUBSCRIPTIONID', value: `${instance.cloudSubscriptionId}` },
|
||||
{ name: 'CLOUD_LOCATION', value: `${instance.cloudLocation}` },
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -30,6 +30,7 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
import sgMail from '@sendgrid/mail';
|
||||
import { ActivityTypes } from 'botbuilder';
|
||||
import { GBLog, GBMinInstance } from 'botlib';
|
||||
import * as df from 'date-diff';
|
||||
|
@ -42,7 +43,7 @@ import mime from 'mime-types';
|
|||
import tesseract from 'node-tesseract-ocr';
|
||||
import path from 'path';
|
||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||
import puppeteer, { executablePath } from 'puppeteer';
|
||||
import puppeteer from 'puppeteer';
|
||||
import qrcode from 'qrcode';
|
||||
import urlJoin from 'url-join';
|
||||
import pkg from 'whatsapp-web.js';
|
||||
|
@ -60,8 +61,6 @@ import { ChartServices } from './ChartServices.js';
|
|||
import { GBVMService } from './GBVMService.js';
|
||||
import { SystemKeywords } from './SystemKeywords.js';
|
||||
import { WebAutomationServices } from './WebAutomationServices.js';
|
||||
import { Client } from 'minio';
|
||||
import nodemailer from 'nodemailer';
|
||||
const { List, Buttons } = pkg;
|
||||
|
||||
|
||||
|
@ -94,11 +93,7 @@ export class DialogKeywords {
|
|||
|
||||
// Launch Puppeteer to render the chart
|
||||
|
||||
const browser = await puppeteer.launch({
|
||||
headless: process.env.CHROME_HEADLESS === 'true',
|
||||
executablePath: process.env.CHROME_PATH ? process.env.CHROME_PATH : executablePath(),
|
||||
}
|
||||
);
|
||||
const browser = await puppeteer.launch();
|
||||
const page = await browser.newPage();
|
||||
|
||||
// Load Billboard.js styles and scripts
|
||||
|
@ -578,6 +573,7 @@ export class DialogKeywords {
|
|||
// tslint:disable-next-line:no-console
|
||||
|
||||
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.
|
||||
|
||||
|
@ -586,36 +582,24 @@ export class DialogKeywords {
|
|||
body = result.value;
|
||||
}
|
||||
|
||||
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
||||
|
||||
const transporter = nodemailer.createTransport({
|
||||
host: process.env.EMAIL_SERVER || 'localhost',
|
||||
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,
|
||||
to: to,
|
||||
subject: subject,
|
||||
text: body,
|
||||
html: body,
|
||||
// headers: {
|
||||
// 'List-Unsubscribe': `<mailto:${config.unsubscribeEmail}?subject=Unsubscribe>`,
|
||||
// 'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click'
|
||||
// }
|
||||
if (emailToken) {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
sgMail.setApiKey(emailToken);
|
||||
const msg = {
|
||||
to: to,
|
||||
from: process.env.EMAIL_FROM,
|
||||
subject: subject,
|
||||
text: body,
|
||||
html: body
|
||||
};
|
||||
|
||||
await transporter.sendMail(mailOptions);
|
||||
GBLogEx.info(min, `E-mail ${to} (${subject}) sent via NodeMailer.`);
|
||||
|
||||
sgMail.send(msg, false, (err, res) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(res);
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
let { client } = await GBDeployer.internalGetDriveClient(min);
|
||||
|
||||
|
@ -725,9 +709,8 @@ export class DialogKeywords {
|
|||
proc.roles = role;
|
||||
|
||||
// Checks access.
|
||||
|
||||
const file = process.env.GB_MODE === 'legacy' ? 'People.xlsx' : 'people.csv';
|
||||
const filters = [file, `${role}=x`, `id=${user.userSystemId}`];
|
||||
|
||||
const filters = ['People.xlsx', `${role}=x`, `id=${user.userSystemId}`];
|
||||
const people = await sys.find({ pid, handle: null, args: filters });
|
||||
|
||||
if (!people) {
|
||||
|
@ -1104,7 +1087,7 @@ export class DialogKeywords {
|
|||
// In case of unmatch, asks the person to try again.
|
||||
|
||||
if (result === null) {
|
||||
await this.talk({ pid, text: `Digite por favor um dos itens sugeridos ou uma parte do texto.` });
|
||||
await this.talk({ pid, text: `Escolha por favor um dos itens sugeridos.` });
|
||||
return await this.hear({ pid, kind, args });
|
||||
}
|
||||
} else if (kind === 'file') {
|
||||
|
@ -1409,7 +1392,7 @@ export class DialogKeywords {
|
|||
const client = await GBUtil.getDirectLineClient(min);
|
||||
conversation.client = client;
|
||||
const response = await client.apis.Conversations.Conversations_StartConversation(
|
||||
|
||||
|
||||
);
|
||||
conversation.conversationId = response.obj.conversationId;
|
||||
|
||||
|
@ -1512,7 +1495,7 @@ export class DialogKeywords {
|
|||
else {
|
||||
|
||||
|
||||
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||
if (GBConfigService.get('STORAGE_NAME')) {
|
||||
|
||||
const ext = path.extname(filename);
|
||||
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
||||
|
@ -1537,52 +1520,17 @@ export class DialogKeywords {
|
|||
'cache',
|
||||
`${fileOnly.replace(/\s/gi, '')}-${GBAdminService.getNumberIdentifier()}.${ext}`
|
||||
);
|
||||
await fs.writeFile(localName, new Uint8Array(buf), { encoding: null });
|
||||
await fs.writeFile(localName, buf, { encoding: null });
|
||||
|
||||
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 {
|
||||
const gbdriveName = GBUtil.getGBAIPath(min.botId, 'gbdrive');
|
||||
localName = path.join(GBConfigService.get('STORAGE_LIBRARY'), gbdriveName, filename);
|
||||
}
|
||||
|
||||
if (localName.endsWith('.image.pdf')) {
|
||||
GBLogEx.info(min, `Converting PDF to images...`);
|
||||
if (localName.endsWith('.pdf')) {
|
||||
|
||||
const pngs = await GBUtil.pdfPageAsImage(min, localName, undefined);
|
||||
|
||||
await CollectionUtil.asyncForEach(pngs, async png => {
|
||||
|
@ -1600,11 +1548,8 @@ export class DialogKeywords {
|
|||
contentUrl: url
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
if (!isNaN(mobile)) {
|
||||
await min.whatsAppDirectLine.sendFileToDevice(mobile, url, filename, caption, undefined, true, true);
|
||||
await min.whatsAppDirectLine.sendFileToDevice(mobile, url, filename, caption, undefined, true);
|
||||
} else {
|
||||
await min.conversationalService['sendOnConversation'](min, user, reply);
|
||||
}
|
||||
|
@ -1623,10 +1568,8 @@ export class DialogKeywords {
|
|||
const buf = await fs.readFile(filename);
|
||||
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
||||
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));
|
||||
|
||||
|
||||
await fs.writeFile(localName, new Uint8Array(buf), { encoding: null });
|
||||
}
|
||||
|
||||
const contentType = mime.lookup(url);
|
||||
|
@ -1638,8 +1581,8 @@ export class DialogKeywords {
|
|||
contentUrl: url
|
||||
});
|
||||
|
||||
if (!isNaN(mobile)) {
|
||||
await min.whatsAppDirectLine.sendFileToDevice(mobile, url, filename, caption, undefined, false);
|
||||
if (channel === 'omnichannel' || !user) {
|
||||
await min.conversationalService.sendFile(min, null, mobile, url, caption);
|
||||
} else {
|
||||
await min.conversationalService['sendOnConversation'](min, user, reply);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -39,7 +39,6 @@ import { CollectionUtil } from 'pragmatismo-io-framework';
|
|||
import { ScheduleServices } from './ScheduleServices.js';
|
||||
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
|
||||
import urlJoin from 'url-join';
|
||||
import { PostgresDialect } from '@sequelize/postgres';
|
||||
import { NodeVM, VMScript } from 'vm2';
|
||||
import { createVm2Pool } from './vm2-process/index.js';
|
||||
import { watch } from 'fs';
|
||||
|
@ -150,7 +149,7 @@ export class GBVMService extends GBService {
|
|||
let mainName = GBVMService.getMethodNameFromVBSFilename(filename);
|
||||
min.scriptMap[filename] = mainName;
|
||||
|
||||
if (writeVBS && GBConfigService.get('GB_MODE') === 'legacy') {
|
||||
if (writeVBS && GBConfigService.get('STORAGE_NAME')) {
|
||||
let text = await this.getTextFromWord(folder, wordFile);
|
||||
|
||||
// Write VBS file without pragma keywords.
|
||||
|
@ -205,7 +204,7 @@ export class GBVMService extends GBService {
|
|||
"author": "${min.botId} owner.",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
|
||||
"yaml": "2.4.2",
|
||||
"encoding": "0.1.13",
|
||||
"isomorphic-fetch": "3.0.0",
|
||||
"punycode": "2.1.1",
|
||||
|
@ -245,133 +244,42 @@ export class GBVMService extends GBService {
|
|||
const logging: boolean | Function =
|
||||
GBConfigService.get('STORAGE_LOGGING') === 'true'
|
||||
? (str: string): void => {
|
||||
GBLogEx.info(min, str);
|
||||
}
|
||||
GBLogEx.info(min, str);
|
||||
}
|
||||
: false;
|
||||
|
||||
const encrypt: boolean = GBConfigService.get('STORAGE_ENCRYPT') === 'true';
|
||||
const acquire = parseInt(GBConfigService.get('STORAGE_ACQUIRE_TIMEOUT'));
|
||||
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: {
|
||||
charset: 'utf8',
|
||||
collate: 'utf8_general_ci',
|
||||
freezeTableName: true,
|
||||
timestamps: false
|
||||
},
|
||||
host: host,
|
||||
port: port,
|
||||
logging: logging as boolean,
|
||||
dialect: dialect,
|
||||
quoteIdentifiers: false, // set case-insensitive
|
||||
dialectOptions: {
|
||||
options: {
|
||||
trustServerCertificate: true,
|
||||
encrypt: encrypt,
|
||||
requestTimeout: 120 * 1000
|
||||
}
|
||||
},
|
||||
pool: {
|
||||
max: 1,
|
||||
min: 0,
|
||||
idle: 10000,
|
||||
evict: 10000,
|
||||
acquire: acquire
|
||||
const sequelizeOptions = {
|
||||
define: {
|
||||
charset: 'utf8',
|
||||
collate: 'utf8_general_ci',
|
||||
freezeTableName: true,
|
||||
timestamps: false
|
||||
},
|
||||
host: host,
|
||||
port: port,
|
||||
logging: logging as boolean,
|
||||
dialect: dialect,
|
||||
quoteIdentifiers: false, // set case-insensitive
|
||||
dialectOptions: {
|
||||
options: {
|
||||
trustServerCertificate: true,
|
||||
encrypt: encrypt,
|
||||
requestTimeout: 120 * 1000
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
pool: {
|
||||
max: 5,
|
||||
min: 0,
|
||||
idle: 10000,
|
||||
evict: 10000,
|
||||
acquire: acquire
|
||||
}
|
||||
};
|
||||
|
||||
if (!min[connectionName]) {
|
||||
GBLogEx.info(min, `Loading data connection ${connectionName} (${dialect})...`);
|
||||
GBLogEx.info(min, `Loading data connection ${connectionName}...`);
|
||||
min[connectionName] = new Sequelize(storageName, username, password, sequelizeOptions);
|
||||
min[connectionName]['gbconnection'] = con;
|
||||
}
|
||||
|
@ -507,10 +415,10 @@ export class GBVMService extends GBService {
|
|||
});
|
||||
|
||||
sync = sync ? sync : !found;
|
||||
|
||||
|
||||
// Do not erase tables in case of an error in collection retrieval.
|
||||
|
||||
if (tables.length === 0) {
|
||||
if (tables.length === 0){
|
||||
sync = false;
|
||||
}
|
||||
|
||||
|
@ -604,13 +512,13 @@ export class GBVMService extends GBService {
|
|||
const jsfile: string = `${filename}.js`;
|
||||
|
||||
const template = (await fs.readFile('./vm-inject.js')).toString();
|
||||
code = template.replace('//##INJECTED_CODE_HERE', code);
|
||||
code = code.replace('//##INJECTED_HEADER', `port=${GBVMService.API_PORT}; botId='${min.botId}';`);
|
||||
code = template.replace('//##INJECTED_CODE_HERE', code );
|
||||
code = code.replace('//##INJECTED_HEADER', `port=${GBVMService.API_PORT}; botId='${min.botId}';` );
|
||||
|
||||
code = ji.default(code, ' ');
|
||||
|
||||
await fs.writeFile(jsfile, code);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private async executeTasks(min, tasks) {
|
||||
|
@ -809,13 +717,7 @@ export class GBVMService extends GBService {
|
|||
|
||||
if (!table && !talk && !systemPrompt) {
|
||||
for (let j = 0; j < keywords.length; j++) {
|
||||
const oldLine = line;
|
||||
line = line.replace(keywords[j][0], keywords[j][1]);
|
||||
|
||||
if(line != oldLine){
|
||||
break;
|
||||
}
|
||||
|
||||
line = line.replace(keywords[j][0], keywords[j][1]); // TODO: Investigate delay here.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -975,7 +877,7 @@ export class GBVMService extends GBService {
|
|||
|
||||
// Auto-NLP generates BASIC variables related to entities.
|
||||
|
||||
if (step?.context?.activity.originalText && min['nerEngine']) {
|
||||
if (step?.context?.activity.originalText && min['nerEngine']) {
|
||||
const result = await min['nerEngine'].process(step.context.activity.originalText);
|
||||
|
||||
for (let i = 0; i < result.entities.length; i++) {
|
||||
|
@ -1034,12 +936,12 @@ export class GBVMService extends GBService {
|
|||
let result;
|
||||
|
||||
try {
|
||||
if (GBConfigService.get('GBVM') !== false) {
|
||||
if (!GBConfigService.get('GBVM')) {
|
||||
return await (async () => {
|
||||
return await new Promise((resolve) => {
|
||||
sandbox['resolve'] = resolve;
|
||||
// TODO: #411 sandbox['reject'] = reject;
|
||||
sandbox['reject'] = () => { };
|
||||
sandbox['reject'] = () => {};
|
||||
|
||||
const vm1 = new NodeVM({
|
||||
allowAsync: true,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -113,7 +113,7 @@ export class ImageProcessingServices {
|
|||
const azureOpenAIEndpoint = await min.core.getParam(min.instance, 'Azure Open AI Endpoint', null, true);
|
||||
const azureOpenAIVersion = await (min.core as any)['getParam'](min.instance, 'Azure Open AI Version', null, true);
|
||||
const azureOpenAIImageModel = await (min.core as any)['getParam'](min.instance, 'Azure Open AI Image Model', null, true);
|
||||
|
||||
|
||||
|
||||
if (azureOpenAIKey) {
|
||||
// Initialize the Azure OpenAI client
|
||||
|
@ -124,17 +124,16 @@ export class ImageProcessingServices {
|
|||
apiVersion: azureOpenAIVersion,
|
||||
apiKey: azureOpenAIKey
|
||||
});
|
||||
|
||||
|
||||
// Make a request to the image generation endpoint
|
||||
|
||||
|
||||
const response = await client.images.generate({
|
||||
|
||||
model: '',
|
||||
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
|
||||
n: 1,
|
||||
size: '1024x1024'
|
||||
});
|
||||
|
||||
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
||||
const localName = path.join('work', gbaiName, 'cache', `DALL-E${GBAdminService.getRndReadableIdentifier()}.png`);
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -522,14 +522,6 @@ 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++] = [
|
||||
/^\s*(.*)\=\s*(DIR)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3, $4) => {
|
||||
|
@ -580,14 +572,6 @@ 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++] = [
|
||||
/^\s*hear (\w+\$*) as\s*integer/gim,
|
||||
($0, $1) => {
|
||||
|
@ -922,15 +906,6 @@ 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++] = [
|
||||
/^\s*((?:[a-z]+.?)(?:(?:\w+).)(?:\w+)*)\s*=\s*(datediff)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3, $4) => {
|
||||
|
@ -1312,7 +1287,7 @@ export class KeywordsExpressions {
|
|||
keywords[i++] = [
|
||||
/^\s*((?:[a-z]+.?)(?:(?:\w+).)(?:\w+)*)\s*=\s*(.*)\s*as\s*pdf/gim,
|
||||
($0, $1, $2) => {
|
||||
return `${$1} = await sys.asPdf({pid: pid, data: ${$2}})`;
|
||||
return `${$1} = await sys.asPdf({pid: pid, data: ${$2})`;
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -1324,13 +1299,13 @@ export class KeywordsExpressions {
|
|||
];
|
||||
|
||||
keywords[i++] = [
|
||||
/^\s*(save)(\s*)(.*\.(xlsx|csv))(.*)/gim,
|
||||
($0, $1, $2, $3, $4, $5) => {
|
||||
/^\s*(save)(\s*)(.*\.xlsx)(.*)/gim,
|
||||
($0, $1, $2, $3, $4) => {
|
||||
$3 = $3.replace(/\'/g, '');
|
||||
$3 = $3.replace(/\"/g, '');
|
||||
$3 = $3.replace(/\`/g, '');
|
||||
$5 = $5.substr(2);
|
||||
return `await sys.save({pid: pid, file: "${$3}", args: [${$5}]})`;
|
||||
$4 = $4.substr(2);
|
||||
return `await sys.save({pid: pid, file: "${$3}", args: [${$4}]})`;
|
||||
}
|
||||
];
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -29,53 +29,49 @@
|
|||
\*****************************************************************************/
|
||||
'use strict';
|
||||
|
||||
import ComputerVisionClient from '@azure/cognitiveservices-computervision';
|
||||
import ApiKeyCredentials from '@azure/ms-rest-js';
|
||||
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 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 { 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 { GBConversationalService } from '../../core.gbapp/services/GBConversationalService.js';
|
||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.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 { GBServer } from '../../../src/app.js';
|
||||
import { GBVMService } from './GBVMService.js';
|
||||
import { KeywordsExpressions } from './KeywordsExpressions.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 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 { exec } from 'child_process';
|
||||
import util from 'util';
|
||||
|
||||
// Promisify the exec function for async/await usage
|
||||
const execPromise = util.promisify(exec);
|
||||
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 { Page } from 'facebook-nodejs-business-sdk';
|
||||
|
||||
import { md5 } from 'js-md5';
|
||||
import { Client } from 'minio';
|
||||
import { GBUtil } from '../../../src/util.js';
|
||||
|
||||
/**
|
||||
|
@ -177,22 +173,22 @@ export class SystemKeywords {
|
|||
if (date) {
|
||||
return array
|
||||
? array.sort((a, b) => {
|
||||
const c = new Date(a[memberName]);
|
||||
const d = new Date(b[memberName]);
|
||||
return c.getTime() - d.getTime();
|
||||
})
|
||||
const c = new Date(a[memberName]);
|
||||
const d = new Date(b[memberName]);
|
||||
return c.getTime() - d.getTime();
|
||||
})
|
||||
: null;
|
||||
} else {
|
||||
return array
|
||||
? array.sort((a, b) => {
|
||||
if (a[memberName] < b[memberName]) {
|
||||
return -1;
|
||||
}
|
||||
if (a[memberName] > b[memberName]) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
})
|
||||
if (a[memberName] < b[memberName]) {
|
||||
return -1;
|
||||
}
|
||||
if (a[memberName] > b[memberName]) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
})
|
||||
: array;
|
||||
}
|
||||
}
|
||||
|
@ -366,42 +362,8 @@ export class SystemKeywords {
|
|||
);
|
||||
}
|
||||
|
||||
private async convertWithLibreOffice(pid, inputPath) {
|
||||
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);
|
||||
}
|
||||
|
||||
public async asPDF({ pid, data }) {
|
||||
let file = await this.renderTable(pid, data, true, false);
|
||||
return file;
|
||||
}
|
||||
|
||||
|
@ -429,7 +391,7 @@ export class SystemKeywords {
|
|||
return new Promise((resolve, reject) => {
|
||||
stream.on('data', chunk => chunks.push(chunk));
|
||||
stream.on('error', reject);
|
||||
stream.on('end', () => resolve(Buffer.concat(chunks.map(chunk => new Uint8Array(chunk)))));
|
||||
stream.on('end', () => resolve(Buffer.concat(chunks)));
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -453,7 +415,7 @@ export class SystemKeywords {
|
|||
const buffer = pngPages[0].content;
|
||||
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
||||
|
||||
await fs.writeFile(localName, new Uint8Array(buffer), { encoding: null });
|
||||
await fs.writeFile(localName, buffer, { encoding: null });
|
||||
|
||||
return { localName: localName, url: url, data: buffer };
|
||||
}
|
||||
|
@ -746,7 +708,7 @@ export class SystemKeywords {
|
|||
// Writes it to disk and calculate hash.
|
||||
|
||||
const data = await response.arrayBuffer();
|
||||
await fs.writeFile(localName, new Uint8Array(Buffer.from(data)), { encoding: null });
|
||||
await fs.writeFile(localName, Buffer.from(data), { encoding: null });
|
||||
const hash = new Uint8Array(md5.array(data));
|
||||
|
||||
// Performs uploading passing local hash.
|
||||
|
@ -823,7 +785,7 @@ export class SystemKeywords {
|
|||
const minRef = min;
|
||||
|
||||
await retry(
|
||||
async bail => {
|
||||
async (bail) => {
|
||||
const t = this.getTableFromName(tableName, minRef);
|
||||
try {
|
||||
await t.bulkCreate(rowsDest);
|
||||
|
@ -875,13 +837,7 @@ export class SystemKeywords {
|
|||
/**
|
||||
* Saves the content of several variables to a new row in a tabular file.
|
||||
*
|
||||
* @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
|
||||
* @example SAVE "customers.xlsx", name, email, phone, address, city, state, country
|
||||
*
|
||||
*/
|
||||
public async save({ pid, file, args }): Promise<any> {
|
||||
|
@ -891,89 +847,6 @@ export class SystemKeywords {
|
|||
|
||||
const { min } = await DialogKeywords.getProcessInfo(pid);
|
||||
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);
|
||||
const botId = min.instance.botId;
|
||||
const packagePath = GBUtil.getGBAIPath(botId, 'gbdata');
|
||||
|
@ -986,11 +859,13 @@ export class SystemKeywords {
|
|||
} catch (e) {
|
||||
if (e.cause === 404) {
|
||||
// Creates the file.
|
||||
|
||||
const blank = path.join(process.env.PWD, 'blank.xlsx');
|
||||
const data = await fs.readFile(blank);
|
||||
await client.api(`${baseUrl}/drive/root:/${packagePath}/${file}:/content`).put(data);
|
||||
|
||||
// Tries to open again.
|
||||
|
||||
document = await this.internalGetDocument(client, baseUrl, packagePath, file);
|
||||
sheets = await client.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets`).get();
|
||||
} else {
|
||||
|
@ -1001,44 +876,51 @@ export class SystemKeywords {
|
|||
let address;
|
||||
let body = { values: [[]] };
|
||||
|
||||
// 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();
|
||||
// Processes FILTER option to ensure parallel SET calls.
|
||||
|
||||
// const hasIdColumn = firstCell.text.toLowerCase() === 'id';
|
||||
const filter = await DialogKeywords.getOption({ pid, name: 'filter' });
|
||||
if (filter) {
|
||||
// Creates id row.
|
||||
|
||||
// // 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]) {
|
||||
// const allRows = await client
|
||||
// .api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/usedRange`)
|
||||
// .get();
|
||||
body.values[0][0] = 'id';
|
||||
const addressId = 'A1:A1';
|
||||
await client
|
||||
.api(
|
||||
`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='${addressId}')`
|
||||
)
|
||||
.patch(body);
|
||||
body.values[0][0] = undefined;
|
||||
|
||||
// for (let i = 1; i < allRows.values.length; i++) {
|
||||
// if (allRows.values[i][0] === args[0]) {
|
||||
// // Update existing row
|
||||
// address = `A${i + 1}:${this.numberToLetters(args.length - 1)}${i + 1}`;
|
||||
// for (let j = 0; j < args.length; j++) {
|
||||
// body.values[0][j] = args[j];
|
||||
// }
|
||||
// rowUpdated = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
const rowUpdated = false;
|
||||
// If no row was updated, add a new row
|
||||
if (!rowUpdated) {
|
||||
// FINDs the filtered row to be updated.
|
||||
|
||||
const row = await this.find({ pid, handle: null, args: [file, filter] });
|
||||
if (row) {
|
||||
address = `A${row['line']}:${this.numberToLetters(args.length)}${row['line']}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Editing or saving detection.
|
||||
|
||||
if (!address) {
|
||||
await client
|
||||
.api(
|
||||
`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A2:DX2')/insert`
|
||||
)
|
||||
.post({});
|
||||
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(
|
||||
|
@ -1064,30 +946,6 @@ 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.
|
||||
*
|
||||
|
@ -1270,7 +1128,7 @@ export class SystemKeywords {
|
|||
const localName = path.join('work', gbaiName, 'cache', `csv${GBAdminService.getRndReadableIdentifier()}.csv`);
|
||||
const url = file['@microsoft.graph.downloadUrl'];
|
||||
const response = await fetch(url);
|
||||
await fs.writeFile(localName, new Uint8Array(Buffer.from(await response.arrayBuffer())), { encoding: null });
|
||||
await fs.writeFile(localName, Buffer.from(await response.arrayBuffer()), { encoding: null });
|
||||
|
||||
var workbook = new Excel.Workbook();
|
||||
let worksheet = await workbook.csv.readFile(localName);
|
||||
|
@ -1317,47 +1175,11 @@ export class SystemKeywords {
|
|||
} else if (file.indexOf('.csv') !== -1) {
|
||||
let res;
|
||||
let packagePath = GBUtil.getGBAIPath(min.botId, `gbdata`);
|
||||
|
||||
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 csvFile = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath, file);
|
||||
const data = await fs.readFile(csvFile, 'utf8');
|
||||
|
||||
const firstLine = data.split('\n')[0];
|
||||
const headers = firstLine.split(',');
|
||||
const db = await csvdb(csvFile, headers, ',');
|
||||
|
||||
GBLogEx.info(min, `READ .csv: ${csvFile}.`);
|
||||
|
||||
if (args[0]) {
|
||||
const systemFilter = await SystemKeywords.getFilter(args[0]);
|
||||
let filter = {};
|
||||
|
@ -1367,8 +1189,6 @@ export class SystemKeywords {
|
|||
res = await db.get();
|
||||
}
|
||||
|
||||
GBLogEx.info(min, `ROWS: ${res.length}.`);
|
||||
|
||||
return res.length > 1 ? res : res[0];
|
||||
} else {
|
||||
const t = this.getTableFromName(file, min);
|
||||
|
@ -1878,9 +1698,13 @@ export class SystemKeywords {
|
|||
const srcPath = urlJoin(root, src);
|
||||
const dstPath = urlJoin(packagePath, dest);
|
||||
|
||||
|
||||
if (path.extname(srcPath) === 'ai') {
|
||||
|
||||
// TODO: To be done.
|
||||
|
||||
} else {
|
||||
|
||||
// Checks if the destination contains subfolders that
|
||||
// need to be created.
|
||||
|
||||
|
@ -2161,98 +1985,35 @@ export class SystemKeywords {
|
|||
*
|
||||
* Fills a .docx or .pptx with template data.
|
||||
*
|
||||
* doc = FILL "templates/template.docx" WITH data
|
||||
* doc = FILL "templates/template.docx", data
|
||||
*
|
||||
*/
|
||||
private async getTemplateBuffer(min: any, gbaiName: string, templateName: string): Promise<Buffer> {
|
||||
public async fill({ pid, templateName, data }) {
|
||||
const { min, user } = await DialogKeywords.getProcessInfo(pid);
|
||||
const botId = min.instance.botId;
|
||||
const gbaiName = GBUtil.getGBAIPath(botId, 'gbdata');
|
||||
let localName;
|
||||
|
||||
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||
// Legacy mode - using Microsoft Graph API
|
||||
const { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
||||
const packagePath = '/' + urlJoin(gbaiName, `${botId}.gbdrive`);
|
||||
const template = await this.internalGetDocument(client, baseUrl, packagePath, templateName);
|
||||
const url = template['@microsoft.graph.downloadUrl'];
|
||||
const res = await fetch(url);
|
||||
return Buffer.from(await res.arrayBuffer());
|
||||
} else if (GBConfigService.get('GB_MODE') === 'gbcluster') {
|
||||
// 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);
|
||||
// Downloads template from .gbdrive.
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
||||
let packagePath = '/' + urlJoin(gbaiName, `${botId}.gbdrive`);
|
||||
let template = await this.internalGetDocument(client, baseUrl, packagePath, templateName);
|
||||
let url = template['@microsoft.graph.downloadUrl'];
|
||||
const res = await fetch(url);
|
||||
let buf: any = Buffer.from(await res.arrayBuffer());
|
||||
localName = path.join('work', gbaiName, 'cache', `tmp${GBAdminService.getRndReadableIdentifier()}.docx`);
|
||||
await fs.writeFile(localName, buf, { encoding: null });
|
||||
|
||||
private async getImageBuffer(min: any, gbaiName: string, imagePath: string): Promise<Buffer> {
|
||||
const botId = min.instance.botId;
|
||||
// Replace image path on all elements of data.
|
||||
|
||||
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 = [];
|
||||
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: any) => {
|
||||
for (const i in o) {
|
||||
const traverseDataToInjectImageUrl = async o => {
|
||||
for (var i in o) {
|
||||
let value = o[i];
|
||||
|
||||
if (value && value.gbarray) {
|
||||
|
@ -2261,84 +2022,112 @@ export class SystemKeywords {
|
|||
}
|
||||
|
||||
for (const kind of ['png', 'jpg', 'jpeg']) {
|
||||
if (value?.endsWith?.(`.${kind}`)) {
|
||||
const imageBuffer = await this.getImageBuffer(min, gbaiName, value);
|
||||
if (value.endsWith && value.endsWith(`.${kind}`)) {
|
||||
const { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
||||
|
||||
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(
|
||||
'work',
|
||||
gbaiName,
|
||||
'cache',
|
||||
`tmp${GBAdminService.getRndReadableIdentifier()}-${path.basename(value)}.png`
|
||||
`tmp${GBAdminService.getRndReadableIdentifier()}-${value}.png`
|
||||
);
|
||||
await fs.writeFile(imageName, new Uint8Array(imageBuffer), { encoding: null });
|
||||
const response = await fetch(url);
|
||||
const buf = Buffer.from(await response.arrayBuffer());
|
||||
await fs.writeFile(imageName, buf, { encoding: null });
|
||||
|
||||
const getNormalSize = ({ width, height, orientation }: any) => {
|
||||
const getNormalSize = ({ width, height, orientation }) => {
|
||||
return (orientation || 0) >= 5 ? [height, width] : [width, height];
|
||||
};
|
||||
|
||||
// TODO: sharp. const metadata = await sharp(buf).metadata();
|
||||
const size = getNormalSize({
|
||||
width: 400,
|
||||
height: 400,
|
||||
orientation: '0'
|
||||
});
|
||||
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(imageName));
|
||||
images[index++] = { url, size, buf: imageBuffer };
|
||||
url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(imageName));
|
||||
images[index++] = { url: url, size: size, buf: buf };
|
||||
}
|
||||
}
|
||||
|
||||
if (o[i] !== null && typeof o[i] === 'object') {
|
||||
if (o[i] !== null && typeof o[i] == 'object') {
|
||||
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;
|
||||
const opts = {
|
||||
var opts = {
|
||||
fileType: 'docx',
|
||||
centered: false,
|
||||
getImage: () => images[indexImage].buf,
|
||||
getSize: () => images[indexImage++].size
|
||||
getImage: (tagValue, tagName) => {
|
||||
return images[indexImage].buf;
|
||||
},
|
||||
getSize: (img, tagValue, tagName) => {
|
||||
return images[indexImage++].size;
|
||||
}
|
||||
};
|
||||
|
||||
// Process the template
|
||||
const zip = new PizZip(templateBuffer);
|
||||
const doc = new Docxtemplater();
|
||||
// Loads the file as binary content.
|
||||
|
||||
let zip = new PizZip(buf);
|
||||
let doc = new Docxtemplater();
|
||||
doc.setOptions({ paragraphLoop: true, linebreaks: true });
|
||||
doc.loadZip(zip);
|
||||
|
||||
if (localName.endsWith('.pptx')) {
|
||||
doc.attachModule(pptxTemplaterModule);
|
||||
}
|
||||
|
||||
doc.attachModule(new ImageModule(opts));
|
||||
doc.render(data);
|
||||
|
||||
const outputBuffer = doc.getZip().generate({ type: 'nodebuffer', compression: 'DEFLATE' });
|
||||
await fs.writeFile(localName, new Uint8Array(outputBuffer), { encoding: null });
|
||||
await traverseDataToInjectImageUrl(data);
|
||||
doc.setData(data).render();
|
||||
|
||||
return { localName, url, data: outputBuffer };
|
||||
buf = doc.getZip().generate({ type: 'nodebuffer', compression: 'DEFLATE' });
|
||||
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) {
|
||||
let letters = '';
|
||||
|
@ -2689,11 +2478,12 @@ export class SystemKeywords {
|
|||
GBLogEx.info(min, `BlueSky Automation: ${text}.`);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
public async answer({ pid, text }) {
|
||||
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}`);
|
||||
return answer.answer;
|
||||
}
|
||||
|
@ -2705,9 +2495,9 @@ export class SystemKeywords {
|
|||
*/
|
||||
public async rewrite({ pid, text }) {
|
||||
const { min, user } = await DialogKeywords.getProcessInfo(pid);
|
||||
const prompt = `${text}`;
|
||||
const prompt = `Rewrite this sentence in a better way: ${text}`;
|
||||
const answer = await ChatServices.invokeLLM(min, prompt);
|
||||
GBLogEx.info(min, `REWRITE ${text} TO ${answer.text}`);
|
||||
GBLogEx.info(min, `REWRITE ${text} TO ${answer}`);
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
@ -2768,7 +2558,7 @@ export class SystemKeywords {
|
|||
|
||||
const buf = Buffer.from(data.Payment.QrCodeBase64Image, 'base64');
|
||||
const localName = path.join('work', gbaiName, 'cache', `qr${GBAdminService.getRndReadableIdentifier()}.png`);
|
||||
await fs.writeFile(localName, new Uint8Array(buf), { encoding: null });
|
||||
await fs.writeFile(localName, buf, { encoding: null });
|
||||
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
||||
|
||||
GBLogEx.info(min, `GBPay: ${data.MerchantOrderId} OK: ${url}.`);
|
||||
|
@ -2857,6 +2647,7 @@ export class SystemKeywords {
|
|||
}
|
||||
|
||||
public async getExtensionInfo(ext: any): Promise<any> {
|
||||
|
||||
// TODO: Load exts.
|
||||
|
||||
let array = []; // exts.filter((v, i, a) => a[i]['extension'] === ext);
|
||||
|
@ -2935,7 +2726,7 @@ export class SystemKeywords {
|
|||
try {
|
||||
let data;
|
||||
|
||||
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||
if (GBConfigService.get('STORAGE_NAME')) {
|
||||
let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
||||
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
||||
let packagePath = '/' + urlJoin(gbaiName, `${min.botId}.gbdrive`);
|
||||
|
@ -3000,7 +2791,7 @@ export class SystemKeywords {
|
|||
|
||||
// Criação de um arquivo temporário para enviar
|
||||
const tempFilePath = path.resolve('temp_image.jpg');
|
||||
await fs.writeFile(tempFilePath, new Uint8Array(imageBuffer));
|
||||
await fs.writeFile(tempFilePath, imageBuffer);
|
||||
|
||||
// Publicação da imagem
|
||||
const page = new Page(pageId);
|
||||
|
@ -3117,16 +2908,17 @@ export class SystemKeywords {
|
|||
}
|
||||
|
||||
public async convertAI2HTML(aiFilePath) {
|
||||
|
||||
// Convert the AI file to HTML and assets
|
||||
const result = await ai2html.convertFile(aiFilePath, {
|
||||
outputFormat: 'html',
|
||||
outputWriteMethod: 'write-file',
|
||||
outputPath: path.dirname(aiFilePath),
|
||||
useDocumentSettings: true
|
||||
useDocumentSettings: true,
|
||||
});
|
||||
|
||||
// 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
|
||||
const htmlContent = await fs.readFile(htmlFilePath, 'utf8');
|
||||
|
@ -3138,8 +2930,10 @@ export class SystemKeywords {
|
|||
await fs.writeFile(cacheFilePath, htmlContent);
|
||||
|
||||
return cacheFilePath;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public async refreshDataSourceCache({ pid, connectionName }) {
|
||||
const { min, user, params, step } = await DialogKeywords.getProcessInfo(pid);
|
||||
|
||||
|
@ -3165,25 +2959,25 @@ export class SystemKeywords {
|
|||
const tables = await GBUtil.listTables(dialect, con);
|
||||
|
||||
// Function to map source database datatypes to SQLite-compatible datatypes
|
||||
const mapToSQLiteType = columnType => {
|
||||
const mapToSQLiteType = (columnType) => {
|
||||
const typeMapping = {
|
||||
VARCHAR: DataTypes.STRING,
|
||||
CHAR: DataTypes.STRING,
|
||||
TEXT: DataTypes.TEXT,
|
||||
TINYINT: DataTypes.INTEGER,
|
||||
SMALLINT: DataTypes.INTEGER,
|
||||
MEDIUMINT: DataTypes.INTEGER,
|
||||
INT: DataTypes.INTEGER,
|
||||
INTEGER: DataTypes.INTEGER,
|
||||
BIGINT: DataTypes.BIGINT,
|
||||
FLOAT: DataTypes.FLOAT,
|
||||
DOUBLE: DataTypes.DOUBLE,
|
||||
DECIMAL: DataTypes.DECIMAL,
|
||||
DATE: DataTypes.DATE,
|
||||
DATETIME: DataTypes.DATE,
|
||||
TIMESTAMP: DataTypes.DATE,
|
||||
BLOB: DataTypes.BLOB,
|
||||
BOOLEAN: DataTypes.BOOLEAN
|
||||
'VARCHAR': DataTypes.STRING,
|
||||
'CHAR': DataTypes.STRING,
|
||||
'TEXT': DataTypes.TEXT,
|
||||
'TINYINT': DataTypes.INTEGER,
|
||||
'SMALLINT': DataTypes.INTEGER,
|
||||
'MEDIUMINT': DataTypes.INTEGER,
|
||||
'INT': DataTypes.INTEGER,
|
||||
'INTEGER': DataTypes.INTEGER,
|
||||
'BIGINT': DataTypes.BIGINT,
|
||||
'FLOAT': DataTypes.FLOAT,
|
||||
'DOUBLE': DataTypes.DOUBLE,
|
||||
'DECIMAL': DataTypes.DECIMAL,
|
||||
'DATE': DataTypes.DATE,
|
||||
'DATETIME': DataTypes.DATE,
|
||||
'TIMESTAMP': DataTypes.DATE,
|
||||
'BLOB': DataTypes.BLOB,
|
||||
'BOOLEAN': DataTypes.BOOLEAN,
|
||||
// Add more mappings as needed
|
||||
};
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"title": "Default General Bot",
|
||||
"description": "Default General Bot",
|
||||
"whoAmIVideo": "TODO.mp4",
|
||||
"author": "pragmatismo.com.br",
|
||||
"author": "pragmatismo.cloud",
|
||||
"license": "AGPL",
|
||||
"engineName": "guaribas-1.0.0"
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -65,7 +65,8 @@ export class WelcomeDialog extends IGBDialog {
|
|||
async step => {
|
||||
if (
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -86,7 +86,7 @@ export class GBConfigService {
|
|||
value = this.getServerPort();
|
||||
break;
|
||||
case 'GBVM':
|
||||
value = true;
|
||||
value = false;
|
||||
break;
|
||||
case 'STORAGE_NAME':
|
||||
value = null;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -43,7 +43,6 @@ import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js';
|
|||
import { SecService } from '../../security.gbapp/services/SecService.js';
|
||||
import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService.js';
|
||||
import { MicrosoftAppCredentials } from 'botframework-connector';
|
||||
import { DocxLoader } from '@langchain/community/document_loaders/fs/docx';
|
||||
import { GBConfigService } from './GBConfigService.js';
|
||||
import { CollectionUtil, AzureText } from 'pragmatismo-io-framework';
|
||||
import { GuaribasUser } from '../../security.gbapp/models/index.js';
|
||||
|
@ -53,7 +52,7 @@ import { createWriteStream, createReadStream } from 'fs';
|
|||
import fs from 'fs/promises';
|
||||
import twilio from 'twilio';
|
||||
import Nexmo from 'nexmo';
|
||||
import path, { join } from 'path';
|
||||
import { join } from 'path';
|
||||
import shell from 'any-shell-escape';
|
||||
import { exec } from 'child_process';
|
||||
import prism from 'prism-media';
|
||||
|
@ -474,7 +473,7 @@ export class GBConversationalService {
|
|||
return new Promise<string>(async (resolve, reject) => {
|
||||
try {
|
||||
const oggFile = new Readable();
|
||||
oggFile._read = () => { }; // _read is required but you can noop it
|
||||
oggFile._read = () => {}; // _read is required but you can noop it
|
||||
oggFile.push(buffer);
|
||||
oggFile.push(null);
|
||||
|
||||
|
@ -647,15 +646,6 @@ export class GBConversationalService {
|
|||
text.toLowerCase().endsWith('.png') ||
|
||||
text.toLowerCase().endsWith('.mp4') ||
|
||||
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 mediaType = mediaFile.toLowerCase().endsWith('.mp4') || text.toLowerCase().endsWith('.mov') ? 'video' : 'image';
|
||||
|
||||
|
@ -1211,8 +1201,8 @@ export class GBConversationalService {
|
|||
|
||||
public async sendTextWithOptions(min: GBMinInstance, step, text, translate, keepTextList, user) {
|
||||
let sec = new SecService();
|
||||
|
||||
if (!user) {
|
||||
|
||||
if (!user){
|
||||
user = await sec.getUserFromSystemId(step.context.activity.from.id);
|
||||
}
|
||||
await this['sendTextWithOptionsAndUser'](min, user, step, text, true, null);
|
||||
|
@ -1262,11 +1252,11 @@ export class GBConversationalService {
|
|||
analytics.createMessage(min.instance.instanceId, conversation, null, text);
|
||||
}
|
||||
|
||||
if (!isNaN(user.userSystemId)) {
|
||||
if (!isNaN(user.userSystemId)){
|
||||
|
||||
await min.whatsAppDirectLine.sendToDevice(user.userSystemId, text);
|
||||
await min.whatsAppDirectLine.sendToDevice(user.userSystemId, text);
|
||||
}
|
||||
else {
|
||||
else{
|
||||
await step.context.sendActivity(text);
|
||||
|
||||
}
|
||||
|
@ -1290,24 +1280,24 @@ export class GBConversationalService {
|
|||
* Sends a message in a user with an already started conversation (got ConversationReference set)
|
||||
*/
|
||||
public async sendOnConversation(min: GBMinInstance, user: GuaribasUser, message: any) {
|
||||
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||
const ref = JSON.parse(user.conversationReference);
|
||||
MicrosoftAppCredentials.trustServiceUrl(ref.serviceUrl);
|
||||
await min.bot['continueConversation'](ref, async t1 => {
|
||||
const ref2 = TurnContext.getConversationReference(t1.activity);
|
||||
await min.bot.continueConversation(ref2, async t2 => {
|
||||
await t2.sendActivity(message);
|
||||
if (GBConfigService.get('STORAGE_NAME')) {
|
||||
const ref = JSON.parse(user.conversationReference);
|
||||
MicrosoftAppCredentials.trustServiceUrl(ref.serviceUrl);
|
||||
await min.bot['continueConversation'](ref, async t1 => {
|
||||
const ref2 = TurnContext.getConversationReference(t1.activity);
|
||||
await min.bot.continueConversation(ref2, async t2 => {
|
||||
await t2.sendActivity(message);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
const ref = JSON.parse(user.conversationReference);
|
||||
await min.bot['continueConversation'](ref, async (t1) => {
|
||||
const ref2 = TurnContext.getConversationReference(t1.activity);
|
||||
await min.bot.continueConversation(ref2, async (t2) => {
|
||||
await t2.sendActivity(message);
|
||||
});
|
||||
const ref2 = TurnContext.getConversationReference(t1.activity);
|
||||
await min.bot.continueConversation(ref2, async (t2) => {
|
||||
await t2.sendActivity(message);
|
||||
});
|
||||
});
|
||||
|
||||
if (message['buttons'] || message['sections']) {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -67,7 +67,6 @@ import { GBDeployer } from './GBDeployer.js';
|
|||
import { SystemKeywords } from '../../basic.gblib/services/SystemKeywords.js';
|
||||
import csvdb from 'csv-database';
|
||||
import { SaaSPackage } from '../../saas.gbapp/index.js';
|
||||
import { Client } from 'minio';
|
||||
|
||||
/**
|
||||
* GBCoreService contains main logic for handling storage services related
|
||||
|
@ -113,7 +112,7 @@ export class GBCoreService implements IGBCoreService {
|
|||
constructor() {
|
||||
this.adminService = new GBAdminService(this);
|
||||
}
|
||||
public async ensureInstances(instances: IGBInstance[], bootInstance: any, core: IGBCoreService) { }
|
||||
public async ensureInstances(instances: IGBInstance[], bootInstance: any, core: IGBCoreService) {}
|
||||
|
||||
/**
|
||||
* Gets database config and connect to storage. Currently two databases
|
||||
|
@ -122,86 +121,62 @@ export class GBCoreService implements IGBCoreService {
|
|||
public async initStorage(): Promise<any> {
|
||||
this.dialect = GBConfigService.get('STORAGE_DIALECT');
|
||||
|
||||
let port: number | undefined;
|
||||
let host: string | undefined;
|
||||
let database: string | undefined;
|
||||
let username: string | undefined;
|
||||
let password: string | undefined;
|
||||
let storage: string | undefined;
|
||||
|
||||
|
||||
if (!['mssql', 'postgres', 'sqlite'].includes(this.dialect)) {
|
||||
throw new Error(`Unknown or unsupported dialect: ${this.dialect}.`);
|
||||
}
|
||||
|
||||
|
||||
if (this.dialect === 'mssql' || this.dialect === 'postgres') {
|
||||
if (this.dialect === 'mssql') {
|
||||
host = GBConfigService.get('STORAGE_SERVER');
|
||||
database = GBConfigService.get('STORAGE_NAME');
|
||||
username = GBConfigService.get('STORAGE_USERNAME');
|
||||
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') {
|
||||
storage = GBConfigService.get('STORAGE_FILE');
|
||||
|
||||
if (!storage) {
|
||||
throw new Error('STORAGE_FILE is required for SQLite.');
|
||||
}
|
||||
|
||||
if (!(await GBUtil.exists(storage))) {
|
||||
process.env.STORAGE_SYNC = 'true';
|
||||
}
|
||||
} else {
|
||||
throw new Error(`Unknown dialect: ${this.dialect}.`);
|
||||
}
|
||||
|
||||
|
||||
const logging: boolean | Function =
|
||||
GBConfigService.get('STORAGE_LOGGING') === 'true'
|
||||
? (str: string): void => {
|
||||
GBLogEx.info(0, str);
|
||||
}
|
||||
GBLogEx.info(0, str);
|
||||
}
|
||||
: false;
|
||||
|
||||
|
||||
const encrypt: boolean = GBConfigService.get('STORAGE_ENCRYPT') === 'true';
|
||||
|
||||
|
||||
const acquireStr = GBConfigService.get('STORAGE_ACQUIRE_TIMEOUT');
|
||||
const acquire = acquireStr ? parseInt(acquireStr, 10) : 10000; // Valor padrão de 10 segundos
|
||||
|
||||
|
||||
const acquire = parseInt(GBConfigService.get('STORAGE_ACQUIRE_TIMEOUT'));
|
||||
const sequelizeOptions: SequelizeOptions = {
|
||||
define: {
|
||||
freezeTableName: true,
|
||||
timestamps: false,
|
||||
timestamps: false
|
||||
},
|
||||
host: host,
|
||||
port: port,
|
||||
logging: logging as boolean,
|
||||
dialect: this.dialect as Dialect,
|
||||
storage: storage,
|
||||
quoteIdentifiers: this.dialect === 'postgres',
|
||||
dialectOptions: this.dialect === 'mssql' ? {
|
||||
quoteIdentifiers: false, // set case-insensitive
|
||||
dialectOptions: {
|
||||
options: {
|
||||
trustServerCertificate: true,
|
||||
encrypt: encrypt,
|
||||
},
|
||||
} : {},
|
||||
encrypt: encrypt
|
||||
}
|
||||
},
|
||||
pool: {
|
||||
max: 5,
|
||||
min: 0,
|
||||
idle: 10000,
|
||||
evict: 10000,
|
||||
acquire: acquire,
|
||||
},
|
||||
acquire: acquire
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
this.sequelize = new Sequelize(database, username, password, sequelizeOptions);
|
||||
}
|
||||
|
||||
|
@ -277,15 +252,12 @@ export class GBCoreService implements IGBCoreService {
|
|||
const options = {
|
||||
where: {
|
||||
[Op.or]: and
|
||||
},
|
||||
order: [['instanceId', 'ASC']]
|
||||
}
|
||||
};
|
||||
return await GuaribasInstance.findAll(options as any);
|
||||
return await GuaribasInstance.findAll(options);
|
||||
} else {
|
||||
const options = { where: { state: 'active' } ,
|
||||
|
||||
order: [['instanceId', 'ASC']]};
|
||||
return await GuaribasInstance.findAll(options as any);
|
||||
const options = { where: { state: 'active' } };
|
||||
return await GuaribasInstance.findAll(options);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -323,6 +295,7 @@ export class GBCoreService implements IGBCoreService {
|
|||
public async writeEnv(instance: IGBInstance) {
|
||||
const env = `
|
||||
ADDITIONAL_DEPLOY_PATH=
|
||||
ADMIN_PASS=${instance.adminPass}
|
||||
BOT_ID=${instance.botId}
|
||||
CLOUD_SUBSCRIPTIONID=${instance.cloudSubscriptionId}
|
||||
CLOUD_LOCATION=${instance.cloudLocation}
|
||||
|
@ -340,7 +313,7 @@ STORAGE_SYNC_ALTER=true
|
|||
ENDPOINT_UPDATE=true
|
||||
`;
|
||||
|
||||
await fs.writeFile('.env', env);
|
||||
await fs.writeFile('.env', env);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -550,7 +523,7 @@ ENDPOINT_UPDATE=true
|
|||
* Verifies that an complex global password has been specified
|
||||
* before starting the server.
|
||||
*/
|
||||
public ensureAdminIsSecured() { }
|
||||
public ensureAdminIsSecured() {}
|
||||
|
||||
public async createBootInstance(
|
||||
core: GBCoreService,
|
||||
|
@ -702,30 +675,30 @@ ENDPOINT_UPDATE=true
|
|||
}
|
||||
|
||||
public async setConfig(min, name: string, value: any): Promise<any> {
|
||||
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||
if (GBConfigService.get('STORAGE_NAME')) {
|
||||
// Handles calls for BASIC persistence on sheet files.
|
||||
GBLog.info(`Defining Config.xlsx variable ${name}= '${value}'...`);
|
||||
|
||||
|
||||
let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
||||
const maxLines = 512;
|
||||
const file = 'Config.xlsx';
|
||||
const packagePath = GBUtil.getGBAIPath(min.botId, `gbot`);
|
||||
|
||||
|
||||
let document = await new SystemKeywords().internalGetDocument(client, baseUrl, packagePath, file);
|
||||
|
||||
|
||||
// Creates book session that will be discarded.
|
||||
let sheets = await client.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets`).get();
|
||||
|
||||
|
||||
// Get the current rows in column A
|
||||
let results = await client
|
||||
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A1:A${maxLines}')`)
|
||||
.get();
|
||||
|
||||
|
||||
const rows = results.values;
|
||||
let address = '';
|
||||
let lastEmptyRow = -1;
|
||||
let isEdit = false;
|
||||
|
||||
|
||||
// Loop through column A to find the row where name matches, or find the next empty row
|
||||
for (let i = 7; i <= rows.length; i++) {
|
||||
let result = rows[i - 1][0];
|
||||
|
@ -734,27 +707,27 @@ ENDPOINT_UPDATE=true
|
|||
isEdit = true; // We are in editing mode
|
||||
break;
|
||||
} else if (!result && lastEmptyRow === -1) {
|
||||
lastEmptyRow = i; // Store the first empty row if no match is found
|
||||
lastEmptyRow = i ; // Store the first empty row if no match is found
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If no match was found and there's an empty row, add a new entry
|
||||
if (!isEdit && lastEmptyRow !== -1) {
|
||||
address = `A${lastEmptyRow}:B${lastEmptyRow}`; // Add new entry in columns A and B
|
||||
}
|
||||
|
||||
|
||||
// Prepare the request body based on whether it's an edit or add operation
|
||||
let body = { values: isEdit ? [[value]] : [[name, value]] };
|
||||
|
||||
|
||||
// Update or add the new value in the found address
|
||||
await client
|
||||
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='${address}')`)
|
||||
.patch(body);
|
||||
}
|
||||
else if (GBConfigService.get('GB_MODE') === 'local') {
|
||||
let packagePath = GBUtil.getGBAIPath(min.botId, `gbot`);
|
||||
|
||||
} else {
|
||||
let packagePath = GBUtil.getGBAIPath(min.botId, `gbot`);
|
||||
const config = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath, 'config.csv');
|
||||
|
||||
|
||||
const db = await csvdb(config, ['name', 'value'], ',');
|
||||
if (await db.get({ name: name })) {
|
||||
await db.edit({ name: name }, { name, value });
|
||||
|
@ -763,7 +736,7 @@ ENDPOINT_UPDATE=true
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a dynamic param from instance. Dynamic params are defined in Config.xlsx
|
||||
* and loaded into the work folder from comida command.
|
||||
|
@ -863,72 +836,75 @@ ENDPOINT_UPDATE=true
|
|||
}
|
||||
|
||||
public async ensureFolders(instances, deployer: GBDeployer) {
|
||||
const storageMode = process.env.GB_MODE;
|
||||
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))) {
|
||||
mkdirp.sync(libraryPath);
|
||||
}
|
||||
|
||||
await this.syncBotStorage(instances, 'default', deployer, libraryPath);
|
||||
|
||||
const files = await fs.readdir(libraryPath);
|
||||
await CollectionUtil.asyncForEach(files, async (file) => {
|
||||
if (file.trim().toLowerCase() !== 'default.gbai' && file.charAt(0) !== '_') {
|
||||
let botId = file.replace(/\.gbai/, '');
|
||||
await this.syncBotStorage(instances, botId, deployer, libraryPath);
|
||||
|
||||
}
|
||||
});
|
||||
if (!(await GBUtil.exists(libraryPath))) {
|
||||
mkdirp.sync(libraryPath);
|
||||
}
|
||||
|
||||
await this.syncBotStorage(instances, 'default', deployer, libraryPath);
|
||||
|
||||
const files = await fs.readdir(libraryPath);
|
||||
await CollectionUtil.asyncForEach(files, async file => {
|
||||
if (file.trim().toLowerCase() !== 'default.gbai' && file.charAt(0) !== '_') {
|
||||
let botId = file.replace(/\.gbai/, '');
|
||||
|
||||
await this.syncBotStorage(instances, botId, deployer, libraryPath);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async syncBotStorage(instances: any, botId: any, deployer: GBDeployer, libraryPath: string) {
|
||||
|
||||
|
||||
let instance = instances.find(p => p.botId.toLowerCase().trim() === botId.toLowerCase().trim());
|
||||
|
||||
if (process.env.GB_MODE === 'local') {
|
||||
if (!instance) {
|
||||
GBLog.info(`Importing package ${botId}.gbai...`);
|
||||
if (!instance) {
|
||||
GBLog.info(`Importing package ${botId}...`);
|
||||
|
||||
// Creates a bot.
|
||||
// Creates a bot.
|
||||
|
||||
let mobile = null,
|
||||
email = null;
|
||||
let mobile = null,
|
||||
email = null;
|
||||
|
||||
instance = await deployer.deployBlankBot(botId, mobile, email);
|
||||
instances.push(instance);
|
||||
const gbaiPath = path.join(libraryPath, `${botId}.gbai`);
|
||||
instance = await deployer.deployBlankBot(botId, mobile, email);
|
||||
const gbaiPath = path.join(libraryPath, `${botId}.gbai`);
|
||||
|
||||
if (!(await GBUtil.exists(gbaiPath))) {
|
||||
fs.mkdir(gbaiPath, { recursive: true });
|
||||
}
|
||||
if (!(await GBUtil.exists(gbaiPath))) {
|
||||
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[]) {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -39,8 +39,6 @@ import express from 'express';
|
|||
import child_process from 'child_process';
|
||||
import { rimraf } from 'rimraf';
|
||||
import urlJoin from 'url-join';
|
||||
import { Client } from 'minio';
|
||||
|
||||
import fs from 'fs/promises';
|
||||
import { GBError, GBLog, GBMinInstance, IGBCoreService, IGBDeployer, IGBInstance, IGBPackage } from 'botlib';
|
||||
import { AzureSearch } from 'pragmatismo-io-framework';
|
||||
|
@ -49,7 +47,7 @@ import { GBServer } from '../../../src/app.js';
|
|||
import { GBVMService } from '../../basic.gblib/services/GBVMService.js';
|
||||
import Excel from 'exceljs';
|
||||
import asyncPromise from 'async-promises';
|
||||
import { GuaribasInstance, GuaribasPackage } from '../models/GBModel.js';
|
||||
import { GuaribasPackage } from '../models/GBModel.js';
|
||||
import { GBAdminService } from './../../admin.gbapp/services/GBAdminService.js';
|
||||
import { AzureDeployerService } from './../../azuredeployer.gbapp/services/AzureDeployerService.js';
|
||||
import { KBService } from './../../kb.gbapp/services/KBService.js';
|
||||
|
@ -222,7 +220,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
const instance = await this.importer.createBotInstance(botId);
|
||||
const bootInstance = GBServer.globals.bootInstance;
|
||||
|
||||
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||
if (GBConfigService.get('STORAGE_NAME')) {
|
||||
// Gets the access token to perform service operations.
|
||||
|
||||
const accessToken = await (GBServer.globals.minBoot.adminService as any)['acquireElevatedToken'](
|
||||
|
@ -234,14 +232,13 @@ export class GBDeployer implements IGBDeployer {
|
|||
|
||||
const service = await AzureDeployerService.createInstance(this);
|
||||
const application = await service.createApplication(accessToken, botId);
|
||||
|
||||
// Fills new instance base information and get App secret.
|
||||
|
||||
instance.marketplaceId = (application as any).appId;
|
||||
instance.marketplacePassword = await service.createApplicationSecret(accessToken, (application as any).id);
|
||||
}
|
||||
|
||||
instance.adminPass = await GBUtil.hashPassword(GBAdminService.getRndPassword());
|
||||
instance.adminPass = GBAdminService.getRndPassword();
|
||||
instance.title = botId;
|
||||
instance.activationCode = instance.botId.substring(0, 15);
|
||||
instance.state = 'active';
|
||||
|
@ -252,14 +249,13 @@ export class GBDeployer implements IGBDeployer {
|
|||
// Saves bot information to the store.
|
||||
|
||||
await this.core.saveInstance(instance);
|
||||
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||
if (GBConfigService.get('STORAGE_NAME')) {
|
||||
await this.deployBotOnAzure(instance, GBServer.globals.publicAddress);
|
||||
}
|
||||
|
||||
// Makes available bot to the channels and .gbui interfaces.
|
||||
|
||||
const min = await GBServer.globals.minService.mountBot(instance);
|
||||
GBServer.globals.minInstances.push(min);
|
||||
await GBServer.globals.minService.mountBot(instance);
|
||||
|
||||
// Creates remaining objects on the cloud and updates instance information.
|
||||
|
||||
|
@ -270,22 +266,9 @@ export class GBDeployer implements IGBDeployer {
|
|||
* Verifies if bot exists on bot catalog.
|
||||
*/
|
||||
public async botExists(botId: string): Promise<boolean> {
|
||||
const service = await AzureDeployerService.createInstance(this);
|
||||
|
||||
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
||||
const where = { botId: botId };
|
||||
|
||||
return await GuaribasInstance.findOne({
|
||||
where: where
|
||||
}) !== null;
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
const service = await AzureDeployerService.createInstance(this);
|
||||
|
||||
return await service.botExists(botId);
|
||||
|
||||
}
|
||||
return await service.botExists(botId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -371,20 +354,9 @@ export class GBDeployer implements IGBDeployer {
|
|||
vectorStore = await HNSWLib.load(min['vectorStorePath'], embedding);
|
||||
} catch (e) {
|
||||
GBLogEx.info(min, `Creating new store...`);
|
||||
vectorStore = await HNSWLib.fromTexts(
|
||||
['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']);
|
||||
vectorStore = new HNSWLib(embedding, {
|
||||
space: 'cosine'
|
||||
});
|
||||
}
|
||||
return vectorStore;
|
||||
}
|
||||
|
@ -494,13 +466,13 @@ export class GBDeployer implements IGBDeployer {
|
|||
} else {
|
||||
return [];
|
||||
}
|
||||
1
|
||||
|
||||
await asyncPromise.eachSeries(rows, async (line: any) => {
|
||||
if (line && line.length > 0) {
|
||||
const key = line[1];
|
||||
let value = line[2];
|
||||
|
||||
|
||||
|
||||
if (key && value) {
|
||||
if (value.text) { value = value.text };
|
||||
obj[key] = value;
|
||||
|
@ -515,135 +487,93 @@ export class GBDeployer implements IGBDeployer {
|
|||
|
||||
/**
|
||||
*/
|
||||
|
||||
public async downloadFolder(
|
||||
min: GBMinInstance,
|
||||
localPath: string,
|
||||
remotePath: string,
|
||||
baseUrl: string = null,
|
||||
client = null, onlyTextFiles = false
|
||||
client = null
|
||||
): Promise<any> {
|
||||
const storageMode = process.env.GB_MODE;
|
||||
GBLogEx.info(min, `downloadFolder: localPath=${localPath}, remotePath=${remotePath}, baseUrl=${baseUrl}`);
|
||||
|
||||
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,
|
||||
});
|
||||
if (!baseUrl) {
|
||||
let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
||||
|
||||
const bucketName = (process.env.DRIVE_ORG_PREFIX + min.botId + '.gbai').toLowerCase();
|
||||
remotePath = remotePath.replace(/\\/gi, '/');
|
||||
const parts = remotePath.split('/');
|
||||
|
||||
if (!(await GBUtil.exists(localPath))) {
|
||||
await fs.mkdir(localPath, { recursive: true });
|
||||
// Creates each subfolder.
|
||||
|
||||
let pathBase = localPath;
|
||||
if (!(await GBUtil.exists(pathBase))) {
|
||||
fs.mkdir(pathBase);
|
||||
}
|
||||
|
||||
const objectsStream = minioClient.listObjects(bucketName, remotePath, true);
|
||||
for await (const obj of objectsStream) {
|
||||
const itemPath = path.join(localPath, obj.name);
|
||||
await CollectionUtil.asyncForEach(parts, async item => {
|
||||
pathBase = path.join(pathBase, item);
|
||||
if (!(await GBUtil.exists(pathBase))) {
|
||||
fs.mkdir(pathBase);
|
||||
}
|
||||
});
|
||||
|
||||
if (obj.name.endsWith('/')) {
|
||||
// Retrieves all files in remote folder.
|
||||
|
||||
let packagePath = GBUtil.getGBAIPath(min.botId);
|
||||
packagePath = urlJoin(packagePath, remotePath);
|
||||
let url = `${baseUrl}/drive/root:/${packagePath}:/children`;
|
||||
|
||||
GBLogEx.info(min, `Downloading: ${url}`);
|
||||
let documents;
|
||||
|
||||
|
||||
try {
|
||||
const res = await client.api(url).get();
|
||||
documents = res.value;
|
||||
} catch (error) {
|
||||
GBLogEx.info(min, `Error downloading: ${error.toString()}`);
|
||||
}
|
||||
if (documents === undefined || documents.length === 0) {
|
||||
GBLogEx.info(min, `${remotePath} is an empty folder.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Download files or navigate to directory to recurse.
|
||||
|
||||
await CollectionUtil.asyncForEach(documents, async item => {
|
||||
const itemPath = path.join(localPath, remotePath, item.name);
|
||||
|
||||
if (item.folder) {
|
||||
if (!(await GBUtil.exists(itemPath))) {
|
||||
await fs.mkdir(itemPath, { recursive: true });
|
||||
fs.mkdir(itemPath);
|
||||
}
|
||||
const nextFolder = urlJoin(remotePath, item.name);
|
||||
await this.downloadFolder(min, localPath, nextFolder);
|
||||
} else {
|
||||
let download = true;
|
||||
|
||||
if (await GBUtil.exists(itemPath)) {
|
||||
const stats = await fs.stat(itemPath);
|
||||
if (stats.mtime >= new Date(obj.lastModified)) {
|
||||
const dt = await fs.stat(itemPath);
|
||||
if (new Date(dt.mtime) >= new Date(item.lastModifiedDateTime)) {
|
||||
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) {
|
||||
const { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
||||
GBLogEx.info(min, `Downloading: ${itemPath}...`);
|
||||
const url = item['@microsoft.graph.downloadUrl'];
|
||||
|
||||
remotePath = remotePath.replace(/\\/gi, '/');
|
||||
const parts = remotePath.split('/');
|
||||
|
||||
let pathBase = localPath;
|
||||
if (!(await GBUtil.exists(pathBase))) {
|
||||
await fs.mkdir(pathBase, { recursive: true });
|
||||
}
|
||||
|
||||
await CollectionUtil.asyncForEach(parts, async (item) => {
|
||||
pathBase = path.join(pathBase, item);
|
||||
if (!(await GBUtil.exists(pathBase))) {
|
||||
await fs.mkdir(pathBase, { recursive: true });
|
||||
}
|
||||
});
|
||||
|
||||
let packagePath = GBUtil.getGBAIPath(min.botId);
|
||||
packagePath = urlJoin(packagePath, remotePath);
|
||||
let url = `${baseUrl}/drive/root:/${packagePath}:/children`;
|
||||
|
||||
let documents;
|
||||
|
||||
try {
|
||||
const res = await client.api(url).get();
|
||||
documents = res.value;
|
||||
} catch (error) {
|
||||
GBLogEx.info(min, `Error downloading: ${error.toString()}`);
|
||||
}
|
||||
|
||||
if (documents === undefined || documents.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
await CollectionUtil.asyncForEach(documents, async (item) => {
|
||||
const itemPath = path.join(localPath, remotePath, item.name);
|
||||
|
||||
if (item.folder) {
|
||||
if (!(await GBUtil.exists(itemPath))) {
|
||||
await fs.mkdir(itemPath, { recursive: true });
|
||||
}
|
||||
const nextFolder = urlJoin(remotePath, item.name);
|
||||
await this.downloadFolder(min, localPath, nextFolder);
|
||||
const response = await fetch(url);
|
||||
await fs.writeFile(itemPath, Buffer.from(await response.arrayBuffer()), { encoding: null });
|
||||
fs.utimes(itemPath, new Date(), new Date(item.lastModifiedDateTime));
|
||||
} else {
|
||||
let download = true;
|
||||
|
||||
if (await GBUtil.exists(itemPath)) {
|
||||
const stats = await fs.stat(itemPath);
|
||||
if (new Date(stats.mtime) >= new Date(item.lastModifiedDateTime)) {
|
||||
download = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (download) {
|
||||
const url = item['@microsoft.graph.downloadUrl'];
|
||||
|
||||
const response = await fetch(url);
|
||||
await fs.writeFile(itemPath, new Uint8Array(await response.arrayBuffer()), { encoding: null });
|
||||
await fs.utimes(itemPath, new Date(), new Date(item.lastModifiedDateTime));
|
||||
}
|
||||
GBLogEx.info(min, `Local is up to date: ${path.basename(itemPath)}...`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Undeploys a bot to the storage.
|
||||
* UndDeploys a bot to the storage.
|
||||
*/
|
||||
public async undeployBot(botId: string, packageName: string): Promise<void> {
|
||||
// Deletes Bot registration on cloud.
|
||||
|
@ -691,21 +621,11 @@ export class GBDeployer implements IGBDeployer {
|
|||
await this.cleanupPackage(min.instance, packageName);
|
||||
}
|
||||
|
||||
if (GBConfigService.get('GB_MODE') === 'local') {
|
||||
if (!GBConfigService.get('STORAGE_NAME')) {
|
||||
const filePath = path.join(GBConfigService.get('STORAGE_LIBRARY'), gbai, packageName);
|
||||
if (packageType === '.gbdrive' || packageType === '.gbdata') {
|
||||
await GBUtil.copyIfNewerRecursive(filePath, packageWorkFolder, true);
|
||||
} else {
|
||||
await GBUtil.copyIfNewerRecursive(filePath, packageWorkFolder, false);
|
||||
}
|
||||
await GBUtil.copyIfNewerRecursive(filePath, packageWorkFolder);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -741,10 +661,6 @@ export class GBDeployer implements IGBDeployer {
|
|||
// Deploy platform packages here accordingly to their extension.
|
||||
|
||||
switch (packageType) {
|
||||
case '.gbdrive':
|
||||
break;
|
||||
case '.gbdata':
|
||||
break;
|
||||
case '.gbot':
|
||||
// Extracts configuration information from .gbot files.
|
||||
|
||||
|
@ -762,7 +678,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
con['storageDriver'] = min.core.getParam<string>(min.instance, `${connectionName} Driver`, null);
|
||||
con['storageTables'] = min.core.getParam<string>(min.instance, `${connectionName} Tables`, null);
|
||||
const storageName = min.core.getParam<string>(min.instance, `${connectionName} Name`, null);
|
||||
|
||||
|
||||
let file = min.core.getParam<string>(min.instance, `${connectionName} File`, null);
|
||||
|
||||
if (storageName) {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -78,7 +78,7 @@ export class GBImporter {
|
|||
if (!instance) {
|
||||
instance = <IGBInstance>{};
|
||||
instance.state = 'active';
|
||||
instance.adminPass = await GBUtil.hashPassword( GBConfigService.get('ADMIN_PASS'));
|
||||
instance.adminPass = GBConfigService.get('ADMIN_PASS');
|
||||
instance.botId = GBConfigService.get('BOT_ID');
|
||||
instance.cloudSubscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
|
||||
instance.cloudLocation = GBConfigService.get('CLOUD_LOCATION');
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -37,7 +37,6 @@ import { createRpcServer } from '@push-rpc/core';
|
|||
import AuthenticationContext from 'adal-node';
|
||||
import arrayBufferToBuffer from 'arraybuffer-to-buffer';
|
||||
import { Semaphore } from 'async-mutex';
|
||||
import { AccessToken } from 'livekit-server-sdk';
|
||||
import { Mutex } from 'async-mutex';
|
||||
import chokidar from 'chokidar';
|
||||
import cors from 'cors';
|
||||
|
@ -106,7 +105,6 @@ import { GBConversationalService } from './GBConversationalService.js';
|
|||
import { GBDeployer } from './GBDeployer.js';
|
||||
import { GBLogEx } from './GBLogEx.js';
|
||||
import { GBSSR } from './GBSSR.js';
|
||||
import Stripe from 'stripe';
|
||||
|
||||
/**
|
||||
* Minimal service layer for a bot and encapsulation of BOT Framework calls.
|
||||
|
@ -162,15 +160,16 @@ export class GBMinService {
|
|||
// Servers default UI on root address '/' if web enabled.
|
||||
|
||||
if (process.env.DISABLE_WEB !== 'true' || process.env.ENABLE_INSTANCE_ON_URL) {
|
||||
|
||||
// Servers the bot information object via HTTP so clients can get
|
||||
// instance information stored on server.
|
||||
GBServer.globals.server.use(
|
||||
cors({
|
||||
origin: 'https://gb6.pragmatismo.com.br',
|
||||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
||||
allowedHeaders: ['Content-Type', 'Authorization', 'x-requested-with', 'x-ms-bot-agent']
|
||||
})
|
||||
);
|
||||
GBServer.globals.server.use(cors({
|
||||
origin: 'http://localhost:8081',
|
||||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
||||
allowedHeaders: ['Content-Type', 'Authorization', 'x-requested-with'
|
||||
, 'x-ms-bot-agent'
|
||||
]
|
||||
}));
|
||||
GBServer.globals.server.get('/instances/:botId', this.handleGetInstanceForClient.bind(this));
|
||||
}
|
||||
|
||||
|
@ -212,11 +211,14 @@ export class GBMinService {
|
|||
const user = await sec.ensureUser(min, 'testuser', 'testuser', '', 'test', 'testuser', null);
|
||||
const pid = GBVMService.createProcessInfo(user, min, 'api', null);
|
||||
|
||||
const response = await client.apis.Conversations.Conversations_StartConversation({
|
||||
userSystemId: user.userSystemId,
|
||||
userName: user.userName,
|
||||
pid: pid
|
||||
});
|
||||
const response = await client.apis.Conversations.Conversations_StartConversation(
|
||||
{
|
||||
userSystemId: user.userSystemId,
|
||||
userName: user.userName,
|
||||
pid: pid
|
||||
}
|
||||
|
||||
);
|
||||
const conversationId = response.obj.conversationId;
|
||||
GBServer.globals.debugConversationId = conversationId;
|
||||
|
||||
|
@ -235,7 +237,7 @@ export class GBMinService {
|
|||
name: 'test',
|
||||
channelIdEx: 'web',
|
||||
pid: pid
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -282,7 +284,7 @@ export class GBMinService {
|
|||
/**
|
||||
* Unmounts the bot web site (default.gbui) secure domain, if any.
|
||||
*/
|
||||
public async unloadDomain(instance: IGBInstance) {}
|
||||
public async unloadDomain(instance: IGBInstance) { }
|
||||
|
||||
/**
|
||||
* Mount the instance by creating an BOT Framework bot object,
|
||||
|
@ -422,7 +424,7 @@ export class GBMinService {
|
|||
const packageTeams = urlJoin(`work`, GBUtil.getGBAIPath(instance.botId), manifest);
|
||||
if (!(await GBUtil.exists(packageTeams))) {
|
||||
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.
|
||||
|
@ -457,78 +459,26 @@ export class GBMinService {
|
|||
|
||||
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.
|
||||
|
||||
GBServer.globals.server
|
||||
.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];
|
||||
|
||||
if (status) {
|
||||
GBLogEx.info(min, `WhatsApp: ${status.recipient_id} ${status.status}`);
|
||||
GBLogEx.verbose(min, `WhatsApp: ${status.recipient_id} ${status.status}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.query['hub.mode'] === 'subscribe') {
|
||||
const val = req.query['hub.verify_token'];
|
||||
const challenge = (min.core['getParam'] as any)(min.instance, `Meta Challenge`, null, true);
|
||||
|
||||
if (challenge && val === challenge) {
|
||||
res.send(req.query['hub.challenge']);
|
||||
res.status(200);
|
||||
GBLogEx.info(min, `Meta callback OK. ${JSON.stringify(req.query)}`);
|
||||
} else {
|
||||
res.status(401);
|
||||
}
|
||||
|
@ -542,13 +492,8 @@ export class GBMinService {
|
|||
// Not meta, multiples bots on root bot.
|
||||
|
||||
if (!req.body.object) {
|
||||
if (req.body.To) {
|
||||
const to = req.body.To.replace(/whatsapp\:\+/gi, '');
|
||||
whatsAppDirectLine = WhatsappDirectLine.botsByNumber[to];
|
||||
} else {
|
||||
const minBoot = GBServer.globals.minBoot as GBMinInstance;
|
||||
whatsAppDirectLine = minBoot.whatsAppDirectLine;
|
||||
}
|
||||
const to = req.body.To.replace(/whatsapp\:\+/gi, '');
|
||||
whatsAppDirectLine = WhatsappDirectLine.botsByNumber[to];
|
||||
}
|
||||
|
||||
if (whatsAppDirectLine) {
|
||||
|
@ -557,50 +502,6 @@ export class GBMinService {
|
|||
})
|
||||
.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`);
|
||||
|
||||
return min;
|
||||
|
@ -628,14 +529,26 @@ export class GBMinService {
|
|||
private createCheckHealthAddress(server: any, min: GBMinInstance, instance: IGBInstance) {
|
||||
server.get(`/${min.instance.botId}/check`, async (req, res) => {
|
||||
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.
|
||||
|
||||
res.status(200).send(`General Bot ${min.botId} is healthly.`);
|
||||
} catch (error) {
|
||||
// GB is not OK, 500 and detail the information on response content.
|
||||
|
||||
GBLogEx.error(min, error);
|
||||
res.status(500).send('Service with erros. Please, check service log.');
|
||||
GBLog.error(error);
|
||||
res.status(500).send(error.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -769,9 +682,8 @@ export class GBMinService {
|
|||
min.instance.authenticatorTenant,
|
||||
'/oauth2/authorize'
|
||||
);
|
||||
authorizationUrl = `${authorizationUrl}?response_type=code&client_id=${
|
||||
min.instance.marketplaceId
|
||||
}&redirect_uri=${urlJoin(process.env.BOT_URL, min.instance.botId, 'token')}`;
|
||||
authorizationUrl = `${authorizationUrl}?response_type=code&client_id=${min.instance.marketplaceId
|
||||
}&redirect_uri=${urlJoin(process.env.BOT_URL, min.instance.botId, 'token')}`;
|
||||
GBLogEx.info(min, `HandleOAuthRequests: ${authorizationUrl}.`);
|
||||
res.redirect(authorizationUrl);
|
||||
});
|
||||
|
@ -809,7 +721,7 @@ export class GBMinService {
|
|||
|
||||
let logo = this.core.getParam(instance, 'Logo', null);
|
||||
|
||||
logo = logo ? urlJoin(instance.botId, 'cache', logo) : 'https://pragmatismo.com.br/icons/general-bots-text.svg';
|
||||
logo = logo ? urlJoin(instance.botId, 'cache', logo) : 'images/logo-gb.png';
|
||||
|
||||
let config = {
|
||||
instanceId: instance.instanceId,
|
||||
|
@ -828,12 +740,8 @@ export class GBMinService {
|
|||
color2: this.core.getParam(instance, 'Color2', null)
|
||||
};
|
||||
|
||||
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
||||
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);
|
||||
if (!GBConfigService.get('STORAGE_NAME')) {
|
||||
config['domain'] = `http://localhost:${GBConfigService.get('PORT')}/directline/${botId}`;
|
||||
} else {
|
||||
const webchatTokenContainer = await this.getWebchatToken(instance);
|
||||
config['conversationId'] = webchatTokenContainer.conversationId;
|
||||
|
@ -904,11 +812,9 @@ export class GBMinService {
|
|||
? instance.marketplacePassword
|
||||
: GBConfigService.get('MARKETPLACE_SECRET')
|
||||
};
|
||||
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
||||
const url = process.env.BOT_URL || `http://localhost:${GBConfigService.get('PORT')}`;
|
||||
|
||||
if (!GBConfigService.get('STORAGE_NAME')) {
|
||||
startRouter(GBServer.globals.server, instance.botId);
|
||||
config['clientOptions'] = { baseUri: url };
|
||||
config['clientOptions'] = { baseUri: `http://localhost:${GBConfigService.get('PORT')}` };
|
||||
}
|
||||
|
||||
const adapter = new BotFrameworkAdapter(config);
|
||||
|
@ -923,8 +829,8 @@ export class GBMinService {
|
|||
|
||||
// The minimal bot is built here.
|
||||
|
||||
const min = new GBMinInstance();
|
||||
|
||||
const min = new GBMinInstance();
|
||||
|
||||
// Setups default BOT Framework dialogs.
|
||||
|
||||
min.userProfile = conversationState.createProperty('userProfile');
|
||||
|
@ -960,7 +866,8 @@ export class GBMinService {
|
|||
min.sandBoxMap = {};
|
||||
min['scheduleMap'] = {};
|
||||
min['conversationWelcomed'] = {};
|
||||
if ((await min.core.getParam(min.instance, 'Answer Mode', null)) && !min['vectorStore']) {
|
||||
if (await min.core.getParam(min.instance, 'Answer Mode', null) &&
|
||||
!min['vectorStore']) {
|
||||
const gbkbPath = GBUtil.getGBAIPath(min.botId, 'gbkb');
|
||||
min['vectorStorePath'] = path.join('work', gbkbPath, 'docs-vectorized');
|
||||
min['vectorStore'] = await this.deployer.loadOrCreateEmptyVectorStore(min);
|
||||
|
@ -1034,7 +941,7 @@ export class GBMinService {
|
|||
|
||||
await min.whatsAppDirectLine.setup(true);
|
||||
} else {
|
||||
if (min !== minBoot && minBoot.instance.whatsappServiceKey) {
|
||||
if (min !== minBoot && minBoot.instance.whatsappServiceKey && min.instance.webchatKey) {
|
||||
min.whatsAppDirectLine = new WhatsappDirectLine(
|
||||
min,
|
||||
min.botId,
|
||||
|
@ -1133,6 +1040,7 @@ export class GBMinService {
|
|||
// Default activity processing and handler.
|
||||
|
||||
const handler = async context => {
|
||||
|
||||
// Handle activity text issues.
|
||||
|
||||
if (!context.activity.text) {
|
||||
|
@ -1144,58 +1052,21 @@ export class GBMinService {
|
|||
|
||||
const step = await min.dialogs.createContext(context);
|
||||
step.context.activity.locale = 'pt-BR';
|
||||
|
||||
|
||||
const sec = new SecService();
|
||||
let member = context.activity.recipient;
|
||||
|
||||
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) {
|
||||
if (process.env.STORAGE_NAME || !member) {
|
||||
member = context.activity.from;
|
||||
}
|
||||
let user = await sec.ensureUser(min, member.id, member.name, '', 'web', member.name, null);
|
||||
const userId = user.userId;
|
||||
const params = user.params ? JSON.parse(user.params) : {};
|
||||
const t = new SystemKeywords();
|
||||
|
||||
try {
|
||||
const conversationReference = JSON.stringify(TurnContext.getConversationReference(context.activity));
|
||||
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.
|
||||
|
||||
|
@ -1234,18 +1105,34 @@ export class GBMinService {
|
|||
if (step.context.activity.channelId !== 'msteams') {
|
||||
const service = new KBService(min.core.sequelize);
|
||||
const data = await service.getFaqBySubjectArray(min.instance.instanceId, 'faq', undefined);
|
||||
if (data.length > 0) {
|
||||
await min.conversationalService.sendEvent(min, step, 'play', {
|
||||
playerType: 'bullet',
|
||||
data: data.slice(0, 10)
|
||||
});
|
||||
await min.conversationalService.sendEvent(min, step, 'play', {
|
||||
playerType: 'bullet',
|
||||
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);
|
||||
if (await this.handleUploads(min, step, user, params, notes != null)) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Required for MSTEAMS handling of persisted conversations.
|
||||
|
@ -1259,6 +1146,7 @@ export class GBMinService {
|
|||
);
|
||||
const botToken = await credentials.getToken();
|
||||
const headers = { Authorization: `Bearer ${botToken}` };
|
||||
const t = new SystemKeywords();
|
||||
const data = await t.getByHttp({
|
||||
pid: 0,
|
||||
url: file.contentUrl,
|
||||
|
@ -1283,8 +1171,6 @@ export class GBMinService {
|
|||
if (!(await sec.getParam(user, 'welcomed'))) {
|
||||
const startDialog = min.core.getParam(min.instance, 'Start Dialog', null);
|
||||
if (startDialog) {
|
||||
const t = new SystemKeywords();
|
||||
t.setMemoryContext({ pid: pid, erase: true });
|
||||
await sec.setParam(userId, 'welcomed', 'true');
|
||||
GBLogEx.info(
|
||||
min,
|
||||
|
@ -1303,37 +1189,53 @@ export class GBMinService {
|
|||
|
||||
if (context.activity.type === 'installationUpdate') {
|
||||
GBLogEx.info(min, `Bot installed on Teams.`);
|
||||
} else if (context.activity.type === 'conversationUpdate') {
|
||||
// Calls onNewSession event on each .gbapp package.
|
||||
} 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.
|
||||
|
||||
await CollectionUtil.asyncForEach(appPackages, async e => {
|
||||
await e.onNewSession(min, step);
|
||||
});
|
||||
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...`);
|
||||
|
||||
// Auto starts dialogs if any is specified.
|
||||
// Calls onNewSession event on each .gbapp package.
|
||||
|
||||
if (!startDialog && !(await sec.getParam(user, 'welcomed'))) {
|
||||
// Otherwise, calls / (root) to default welcome users.
|
||||
await CollectionUtil.asyncForEach(appPackages, async e => {
|
||||
await e.onNewSession(min, step);
|
||||
});
|
||||
|
||||
await step.beginDialog('/');
|
||||
} else {
|
||||
if (!GBMinService.userMobile(step) && !min['conversationWelcomed'][step.context.activity.conversation.id]) {
|
||||
const pid = GBVMService.createProcessInfo(user, min, step.context.activity.channelId, null, step);
|
||||
const t = new SystemKeywords();
|
||||
t.setMemoryContext({ pid: pid, erase: true });
|
||||
// Auto starts dialogs if any is specified.
|
||||
|
||||
step.context.activity['pid'] = pid;
|
||||
if (!startDialog && !(await sec.getParam(user, 'welcomed'))) {
|
||||
// Otherwise, calls / (root) to default welcome users.
|
||||
|
||||
min['conversationWelcomed'][step.context.activity.conversation.id] = true;
|
||||
await step.beginDialog('/');
|
||||
} else {
|
||||
if (
|
||||
!GBMinService.userMobile(step) &&
|
||||
!min['conversationWelcomed'][step.context.activity.conversation.id]
|
||||
) {
|
||||
|
||||
GBLogEx.info(
|
||||
min,
|
||||
`Auto start (web 1) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`
|
||||
);
|
||||
await GBVMService.callVM(startDialog.toLowerCase(), min, step, pid);
|
||||
const pid = GBVMService.createProcessInfo(user, min, step.context.activity.channelId, null, step);
|
||||
step.context.activity['pid'] = pid;
|
||||
|
||||
min['conversationWelcomed'][step.context.activity.conversation.id] = true;
|
||||
|
||||
GBLogEx.info(
|
||||
min,
|
||||
`Auto start (web 1) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`
|
||||
);
|
||||
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') {
|
||||
|
||||
|
||||
|
||||
// Required for F0 handling of persisted conversations.
|
||||
|
||||
GBLogEx.info(
|
||||
|
@ -1341,6 +1243,7 @@ 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})`
|
||||
);
|
||||
|
||||
|
||||
// Processes messages activities.
|
||||
|
||||
await this.processMessageActivity(context, min, step, pid);
|
||||
|
@ -1363,10 +1266,10 @@ export class GBMinService {
|
|||
};
|
||||
|
||||
try {
|
||||
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
||||
if (!GBConfigService.get('STORAGE_NAME')) {
|
||||
const context = adapter['createContext'](req);
|
||||
context['_activity'] = context.activity.body;
|
||||
await adapter['processActivity'](req, res, handler);
|
||||
await handler(context);
|
||||
|
||||
// Return status
|
||||
res.status(200);
|
||||
|
@ -1399,13 +1302,12 @@ export class GBMinService {
|
|||
);
|
||||
|
||||
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') {
|
||||
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') {
|
||||
await step.beginDialog('/answerEvent', <AskDialogArgs>{
|
||||
questionId: context.activity.data,
|
||||
|
@ -1491,6 +1393,7 @@ export class GBMinService {
|
|||
const successfulSaves = await Promise.all(promises);
|
||||
async function replyForReceivedAttachments(attachmentData) {
|
||||
if (attachmentData) {
|
||||
|
||||
// In case of not having HEAR activated before, it is
|
||||
// a upload with no Dialog, so run Auto Save to .gbdrive.
|
||||
|
||||
|
@ -1534,16 +1437,16 @@ export class GBMinService {
|
|||
name: string;
|
||||
}
|
||||
|
||||
const results = (await successfulSaves.reduce(async (accum: GBFile[], item) => {
|
||||
const results = await successfulSaves.reduce(async (accum: GBFile[], item) => {
|
||||
const result: GBFile = {
|
||||
data: await fs.readFile(successfulSaves[0]['filename']),
|
||||
filename: successfulSaves[0]['filename'],
|
||||
name: successfulSaves[0]['name'],
|
||||
url: successfulSaves[0]['url']
|
||||
url: successfulSaves[0]['url'],
|
||||
};
|
||||
accum.push(result);
|
||||
return accum;
|
||||
}, [])) as GBFile[];
|
||||
}, []) as GBFile[];
|
||||
|
||||
if (min.cbMap[user.userId] && min.cbMap[user.userId].promise == '!GBHEAR') {
|
||||
if (results.length > 1) {
|
||||
|
@ -1651,15 +1554,15 @@ export class GBMinService {
|
|||
!step.context.activity['group']
|
||||
) {
|
||||
await sec.setParam(userId, 'welcomed', 'true');
|
||||
const t = new SystemKeywords();
|
||||
t.setMemoryContext({ pid: pid, erase: true });
|
||||
|
||||
min['conversationWelcomed'][step.context.activity.conversation.id] = true;
|
||||
GBLogEx.info(
|
||||
min,
|
||||
`Auto start (4) dialog is now being called: ${startDialog} for ${min.instance.instanceId}...`
|
||||
);
|
||||
await GBVMService.callVM(startDialog.toLowerCase(), min, step, pid);
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1713,7 +1616,7 @@ export class GBMinService {
|
|||
// Removes unwanted chars in input text.
|
||||
|
||||
step.context.activity['originalText'] = context.activity.text;
|
||||
const text = context.activity.text;
|
||||
const text = await GBConversationalService.handleText(min, user, step, context.activity.text);
|
||||
step.context.activity['originalText'];
|
||||
step.context.activity['text'] = text;
|
||||
|
||||
|
@ -1759,9 +1662,8 @@ export class GBMinService {
|
|||
try {
|
||||
await step.continueDialog();
|
||||
} 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);
|
||||
await min.conversationalService.sendText(
|
||||
min,
|
||||
|
@ -1884,10 +1786,10 @@ export class GBMinService {
|
|||
pingSendTimeout: null,
|
||||
keepAliveTimeout: null,
|
||||
listeners: {
|
||||
unsubscribed(subscriptions: number): void {},
|
||||
subscribed(subscriptions: number): void {},
|
||||
disconnected(remoteId: string, connections: number): void {},
|
||||
connected(remoteId: string, connections: number): void {},
|
||||
unsubscribed(subscriptions: number): void { },
|
||||
subscribed(subscriptions: number): void { },
|
||||
disconnected(remoteId: string, connections: number): void { },
|
||||
connected(remoteId: string, connections: number): void { },
|
||||
messageIn(...params): void {
|
||||
params.shift();
|
||||
},
|
||||
|
@ -1908,7 +1810,7 @@ export class GBMinService {
|
|||
private mutex: Mutex = new Mutex();
|
||||
|
||||
public async watchPackages(min: GBMinInstance, packageType: string): Promise<void> {
|
||||
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
||||
if (!GBConfigService.get('STORAGE_NAME')) {
|
||||
const packagePath = GBUtil.getGBAIPath(min.botId, packageType);
|
||||
const libraryPath = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath);
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -99,7 +99,6 @@ export class GBSSR {
|
|||
'--disable-features=site-per-process',
|
||||
'--disable-gpu',
|
||||
'--no-first-run',
|
||||
'--no-sandbox',
|
||||
'--no-default-browser-check'
|
||||
];
|
||||
|
||||
|
@ -118,7 +117,7 @@ export class GBSSR {
|
|||
return {
|
||||
args: args,
|
||||
ignoreHTTPSErrors: true,
|
||||
headless: process.env.CHROME_HEADLESS === 'true',
|
||||
headless: false,
|
||||
defaultViewport: null,
|
||||
executablePath: process.env.CHROME_PATH ? process.env.CHROME_PATH : executablePath(),
|
||||
ignoreDefaultArgs: ['--enable-automation', '--enable-blink-features=IdleDetection']
|
||||
|
@ -336,9 +335,6 @@ export class GBSSR {
|
|||
if (GBServer.globals.wwwroot && url === '/') {
|
||||
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) {
|
||||
packagePath = path.join(GBServer.globals.wwwroot, url);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -55,18 +55,6 @@ export class QualityDialog extends IGBDialog {
|
|||
public static setup(bot: BotAdapter, min: GBMinInstance) {
|
||||
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(
|
||||
new WaterfallDialog('/check', [
|
||||
async step => {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
1961
packages/default.gbui/aggregated_code.md
Normal file
1961
packages/default.gbui/aggregated_code.md
Normal file
File diff suppressed because it is too large
Load diff
Binary file not shown.
Before Width: | Height: | Size: 58 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3 KiB |
|
@ -6,7 +6,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -38,7 +38,7 @@
|
|||
<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/default.css" />
|
||||
|
||||
<script src="./js/webchat.js"></script>
|
||||
<title>{title} | General Bots</title>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -347,7 +347,7 @@ class GBUIApp extends React.Component {
|
|||
);
|
||||
|
||||
if (this.state.instanceClient) {
|
||||
|
||||
let color1 = this.state.instanceClient.color1;
|
||||
gbCss = <GBCss instance={this.state.instanceClient} />;
|
||||
seo = <SEO instance={this.state.instanceClient} />;
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
@ -35,7 +35,7 @@ const footer = () => (
|
|||
<div className="footer-container">
|
||||
General Bots Community Edition
|
||||
<br/>
|
||||
<a href="http://pragmatismo.com.br">pragmatismo.com.br</a>
|
||||
<a href="http://pragmatismo.cloud">pragmatismo.cloud</a>
|
||||
</div>
|
||||
);
|
||||
export default footer
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| According to our dual licensing model, this program can be used either |
|
||||
|
@ -21,58 +21,66 @@
|
|||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
| |
|
||||
\*****************************************************************************/
|
||||
|
||||
import React from 'react';
|
||||
import React from "react";
|
||||
|
||||
class SideBarMenu extends React.Component {
|
||||
send(command) {
|
||||
window.botConnection.postActivity({
|
||||
type: 'event',
|
||||
name: command,
|
||||
locale: 'en-us',
|
||||
textFormat: 'plain',
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
window.botConnection
|
||||
.postActivity({
|
||||
type: "event",
|
||||
name: command,
|
||||
locale: "en-us",
|
||||
textFormat: "plain",
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<div className="titleSideBarMenu">
|
||||
<img className="pragmatismoLogo" width="64px" src={this.props.instance.logo} alt="General Bots Logo" />
|
||||
<img
|
||||
className="pragmatismoLogo"
|
||||
src={this.props.instance.logo}
|
||||
alt="General Bots Logo" />
|
||||
|
||||
</div>
|
||||
<div className="SidebarMenu">
|
||||
<div className="IconsMenu">
|
||||
<div className="iconMenu">
|
||||
<span className="iconText" onClick={() => this.send('showFAQ')}>
|
||||
<span className="iconText" onClick={() => this.send("showFAQ")}>
|
||||
FAQ
|
||||
</span>
|
||||
</div>
|
||||
<div className="iconMenu">
|
||||
<span
|
||||
className="iconText"
|
||||
onClick={() =>
|
||||
window.open(`https://drive.pragmatismo.com.br/browser/${this.props.instance.botId}.gbai`)
|
||||
}
|
||||
<span className="iconText"
|
||||
onClick={() => window.open(`https://pragmatismo.sharepoint.com/sites/bots/Online/${this.props.instance.botId}.gbai`)}
|
||||
>
|
||||
Drive
|
||||
</span>
|
||||
</div>
|
||||
<div className="iconMenu">
|
||||
<span className="iconText" onClick={() => this.send('showSubjects')}>
|
||||
<span
|
||||
className="iconText"
|
||||
onClick={() => this.send("showSubjects")}>
|
||||
Subjects
|
||||
</span>
|
||||
</div>
|
||||
<div className="iconMenu">
|
||||
<span className="iconText" onClick={() => window.open('mailto:talk@pragmatismo.com.br')}>
|
||||
<span
|
||||
className="iconText"
|
||||
onClick={() => window.open('mailto:talk@pragmatismo.cloud')}
|
||||
>
|
||||
Suggestions
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
||||
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
||||
| |
|
||||
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
|
||||
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| 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 |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of pragmatismo.com.br. |
|
||||
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| 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