Compare commits

...
Sign in to create a new pull request.

233 commits

Author SHA1 Message Date
Rodrigo Rodriguez (Pragmatismo)
b5bf44fd70 Update SystemKeywords.ts
Some checks failed
GBCI / build (push) Has been cancelled
2025-08-25 19:46:19 -03:00
Rodrigo Rodriguez (Pragmatismo)
864107fca0 Update SystemKeywords.ts
Some checks are pending
GBCI / build (push) Waiting to run
2025-08-25 19:33:51 -03:00
Rodrigo Rodriguez (Pragmatismo)
2695b54460 Refactor code formatting and adjust minor syntax errors
Some checks are pending
GBCI / build (push) Waiting to run
2025-08-25 19:32:31 -03:00
Rodrigo Rodriguez (Pragmatismo)
27dde0f4f0 Merge branch 'main' of https://alm.pragmatismo.com.br/GeneralBots/botserver
Some checks failed
GBCI / build (push) Failing after 18m55s
2025-08-23 21:40:54 -03:00
Rodrigo Rodriguez (Pragmatismo)
e6ec0d2e9e - Logo fix. 2025-08-23 21:39:03 -03:00
300b5dc258 Update templates/edu.gbai/edu.gbdialog/enrollment.bas
Some checks failed
GBCI / build (push) Failing after 24m25s
2025-08-10 20:59:06 +00:00
Rodrigo Rodriguez (Pragmatismo)
9201d7a262 refactor(SystemKeywords): comment out unused ID column logic for clarity
Some checks failed
GBCI / build (push) Failing after 12m30s
2025-08-05 14:17:38 -03:00
Rodrigo Rodriguez (Pragmatismo)
fb24bbd98e refactor(SystemKeywords): comment out unused ID column logic for clarity
Some checks are pending
GBCI / build (push) Waiting to run
2025-08-05 14:03:17 -03:00
Rodrigo Rodriguez (Pragmatismo)
58ebbe880c - TS updates.
Some checks failed
GBCI / build (push) Has been cancelled
2025-07-22 18:04:15 -03:00
Rodrigo Rodriguez (Pragmatismo)
d21b1747d6 refactor(SystemKeywords): comment out unused ID column logic for clarity
Some checks failed
GBCI / build (push) Failing after 11m21s
2025-07-19 22:48:11 -03:00
Rodrigo Rodriguez (Pragmatismo)
26eb714e2c refactor(SystemKeywords): comment out unused ID column logic for clarity
Some checks failed
GBCI / build (push) Failing after 10m30s
2025-07-19 22:27:47 -03:00
Rodrigo Rodriguez (Pragmatismo)
5c3b24dadd refactor(SystemKeywords): comment out unused ID column logic for clarity
Some checks failed
GBCI / build (push) Has been cancelled
2025-07-02 20:38:26 -03:00
Rodrigo Rodriguez (Pragmatismo)
a33ed106f7 refactor(SystemKeywords): comment out unused ID column logic for clarity
Some checks failed
GBCI / build (push) Failing after 8m12s
2025-06-27 15:37:04 -03:00
Rodrigo Rodriguez (Pragmatismo)
afe9e6c7ab refactor(SystemKeywords): comment out unused ID column logic for clarity
Some checks failed
GBCI / build (push) Has been cancelled
2025-06-27 15:31:11 -03:00
Rodrigo Rodriguez (Pragmatismo)
3afdbb1ddb fix(GBSSR): update packagePath logic to handle non-static URLs correctly
Some checks failed
GBCI / build (push) Failing after 8m30s
2025-06-27 13:31:32 -03:00
Rodrigo Rodriguez (Pragmatismo)
f245de43b2 fix: update Puppeteer launch options to use environment variables for headless mode and enhance enrollment confirmation messages
Some checks failed
GBCI / build (push) Failing after 8m24s
2025-06-27 12:46:15 -03:00
Rodrigo Rodriguez (Pragmatismo)
619a0e11b9 fix(WhatsappDirectLine): update sendFileToDevice to default isViewOnce to true and clean up header example
Some checks failed
GBCI / build (push) Failing after 7m41s
2025-06-24 14:54:28 -03:00
Rodrigo Rodriguez (Pragmatismo)
f71c803f2c fix(WhatsappDirectLine): update sendFileToDevice to default isViewOnce to true and clean up header example
Some checks failed
GBCI / build (push) Failing after 8m0s
2025-06-24 11:43:00 -03:00
Rodrigo Rodriguez (Pragmatismo)
3d5c30a3b0 fix(WhatsappDirectLine): update sendFileToDevice to default isViewOnce to true and clean up header example
Some checks failed
GBCI / build (push) Failing after 9m6s
2025-06-24 08:43:17 -03:00
Rodrigo Rodriguez (Pragmatismo)
9d95e4f8c1 fix(WhatsappDirectLine): update sendFileToDevice to default isViewOnce to true and clean up header example
Some checks failed
GBCI / build (push) Has been cancelled
2025-06-15 19:23:39 -03:00
Rodrigo Rodriguez (Pragmatismo)
cbdf3664bb fix(WhatsappDirectLine): update sendFileToDevice to default isViewOnce to true and clean up header example
Some checks are pending
GBCI / build (push) Waiting to run
2025-06-15 19:17:50 -03:00
Rodrigo Rodriguez (Pragmatismo)
0d5a4aee3c fix(WhatsappDirectLine): update sendFileToDevice to default isViewOnce to true and clean up header example
Some checks are pending
GBCI / build (push) Waiting to run
2025-06-15 19:00:45 -03:00
Rodrigo Rodriguez (Pragmatismo)
1d20dd83b0 fix(WhatsappDirectLine): streamline media handling and improve template creation
Some checks failed
GBCI / build (push) Has been cancelled
2025-06-12 11:50:14 -03:00
Rodrigo Rodriguez (Pragmatismo)
2e42c36ecb fix(WhatsappDirectLine): streamline media handling and improve template creation
Some checks are pending
GBCI / build (push) Waiting to run
2025-06-12 11:31:33 -03:00
Rodrigo Rodriguez (Pragmatismo)
2da1e99c0d fix(WhatsappDirectLine): comment out unused header component in message structure
Some checks are pending
GBCI / build (push) Waiting to run
2025-06-12 11:20:00 -03:00
Rodrigo Rodriguez (Pragmatismo)
30fa9ec5db fix(WhatsappDirectLine): comment out unused header component in message structure
Some checks are pending
GBCI / build (push) Waiting to run
2025-06-11 12:05:57 -03:00
Rodrigo Rodriguez (Pragmatismo)
e68eccffd4 fix(WhatsappDirectLine): comment out unused header component in message structure
Some checks are pending
GBCI / build (push) Waiting to run
2025-06-11 11:47:59 -03:00
Rodrigo Rodriguez (Pragmatismo)
910d78765a fix(WhatsappDirectLine): comment out unused header component in message structure
Some checks are pending
GBCI / build (push) Waiting to run
2025-06-11 11:08:15 -03:00
Rodrigo Rodriguez (Pragmatismo)
e17ad407ff fix(WhatsappDirectLine): comment out unused header component in message structure
Some checks are pending
GBCI / build (push) Waiting to run
2025-06-11 11:05:48 -03:00
Rodrigo Rodriguez (Pragmatismo)
75b0e0a9c8 fix(WhatsappDirectLine): add missing closing brace for header object in message structure
Some checks are pending
GBCI / build (push) Waiting to run
2025-06-11 10:28:13 -03:00
Rodrigo Rodriguez (Pragmatismo)
0b748d68fb fix(WhatsappDirectLine): add missing closing brace for header object in message structure
Some checks are pending
GBCI / build (push) Waiting to run
2025-06-11 10:05:39 -03:00
Rodrigo Rodriguez (Pragmatismo)
215bd1b699 fix(WhatsappDirectLine): refactor server status check and improve large file upload process with chunked uploads
Some checks are pending
GBCI / build (push) Waiting to run
2025-06-11 09:53:10 -03:00
Rodrigo Rodriguez (Pragmatismo)
aa606c0d90 fix(GBConversationalService, WhatsappDirectLine): update component structure to include header type and format
Some checks are pending
GBCI / build (push) Waiting to run
2025-06-11 09:40:58 -03:00
Rodrigo Rodriguez (Pragmatismo)
b0517c9c94 fix(WhatsappDirectLine): refactor large file upload process to improve error handling and add public URL registration
Some checks are pending
GBCI / build (push) Waiting to run
2025-06-11 09:33:34 -03:00
Rodrigo Rodriguez (Pragmatismo)
51831d2f24 fix(WhatsappDirectLine): refactor large file upload process to improve error handling and add public URL registration
Some checks are pending
GBCI / build (push) Waiting to run
2025-06-11 09:19:16 -03:00
Rodrigo Rodriguez (Pragmatismo)
25e688aed9 fix(WhatsappDirectLine): improve large file upload handling and error messages
Some checks are pending
GBCI / build (push) Waiting to run
2025-06-10 20:27:02 -03:00
Rodrigo Rodriguez (Pragmatismo)
f232bdbaac fix(KBService): update Puppeteer configuration for headless mode and executable path
Some checks failed
GBCI / build (push) Failing after 8s
fix(node.yaml): correct deployment paths and improve Node.js setup
fix(.gitignore): add 'botpoc' to ignored files
fix(SystemKeywords): enhance PDF conversion and image processing logic
fix(DialogKeywords): adjust Puppeteer launch options for better performance
fix(KeywordsExpressions): fix syntax error in PDF assignment
2025-06-09 19:51:05 -03:00
Rodrigo Rodriguez (Pragmatismo)
43242cb433 fix(KBService): update Puppeteer configuration for headless mode and executable path
fix(node.yaml): correct deployment paths and improve Node.js setup
fix(.gitignore): add 'botpoc' to ignored files
fix(SystemKeywords): enhance PDF conversion and image processing logic
fix(DialogKeywords): adjust Puppeteer launch options for better performance
fix(KeywordsExpressions): fix syntax error in PDF assignment
2025-06-09 19:48:24 -03:00
Rodrigo Rodriguez (Pragmatismo)
2b2ab3a42e fix(KBService): standardize formatting and improve code readability
All checks were successful
GBCI / build (push) Successful in 1m13s
2025-05-22 20:32:30 -03:00
Rodrigo Rodriguez (Pragmatismo)
e2382ccddc fix(KBService): standardize formatting and improve code readability
All checks were successful
GBCI / build (push) Successful in 1m1s
2025-05-22 18:56:30 -03:00
Rodrigo Rodriguez (Pragmatismo)
53710da2a7 fix(KBService): reduce timeout and max documents for crawling logic
All checks were successful
GBCI / build (push) Successful in 41s
2025-05-22 12:16:05 -03:00
Rodrigo Rodriguez (Pragmatismo)
4e6e34e978 fix(KBService): remove unnecessary skip variable in file processing logic
All checks were successful
GBCI / build (push) Successful in 3m22s
2025-05-22 11:14:10 -03:00
Rodrigo Rodriguez (Pragmatismo)
3abbec63a7 fix(KBService): remove unnecessary skip variable in file processing logic
All checks were successful
GBCI / build (push) Successful in 33s
2025-05-22 11:00:16 -03:00
Rodrigo Rodriguez (Pragmatismo)
b6ba7d5a3d fix(KBService): remove unnecessary skip variable in file processing logic
All checks were successful
GBCI / build (push) Successful in 38s
2025-05-22 10:55:32 -03:00
Rodrigo Rodriguez (Pragmatismo)
2f605f101c fix(KBService): remove unnecessary skip variable in file processing logic
All checks were successful
GBCI / build (push) Successful in 49s
2025-05-22 10:46:11 -03:00
Rodrigo Rodriguez (Pragmatismo)
2ee0f0f7ec fix(KBService): remove unnecessary skip variable in file processing logic
All checks were successful
GBCI / build (push) Successful in 1m30s
2025-05-22 10:41:43 -03:00
Rodrigo Rodriguez (Pragmatismo)
8d83dc214a fix(KBService): remove unnecessary skip variable in file processing logic
All checks were successful
GBCI / build (push) Successful in 50s
2025-05-13 23:10:42 -03:00
Rodrigo Rodriguez (Pragmatismo)
4c28404578 fix(KBService): update file processing logic to include additional file types
All checks were successful
GBCI / build (push) Successful in 1m13s
2025-05-13 22:43:47 -03:00
Rodrigo Rodriguez (Pragmatismo)
0f0f8d610e fix(KBService): skip processing of files in gbdata path
All checks were successful
GBCI / build (push) Successful in 47s
2025-05-13 22:33:29 -03:00
Rodrigo Rodriguez (Pragmatismo)
5e492d590e fix(KBService): enable concatenation of files from gbdata path
All checks were successful
GBCI / build (push) Successful in 1m13s
2025-05-13 22:19:18 -03:00
Rodrigo Rodriguez (Pragmatismo)
24d2b10afb feat(ChatServices): specify model as 'gpt-4' for improved performance
All checks were successful
GBCI / build (push) Successful in 1m26s
2025-05-12 09:20:28 -03:00
Rodrigo Rodriguez (Pragmatismo)
bb05685767 feat(ChatServices): specify model as 'gpt-4' for improved performance
All checks were successful
GBCI / build (push) Successful in 56s
2025-05-11 23:19:44 -03:00
Rodrigo Rodriguez (Pragmatismo)
83107fbf91 refactor(workflows): remove unnecessary .env file copy in deployment script
All checks were successful
GBCI / build (push) Successful in 57s
2025-05-11 22:44:30 -03:00
Rodrigo Rodriguez (Pragmatismo)
1ca61954a4 refactor(GBDeployer): simplify file type checks for downloading text files
Some checks failed
GBCI / build (push) Failing after 12s
2025-05-11 22:41:54 -03:00
Rodrigo Rodriguez (Pragmatismo)
c5f522d7d7 refactor(GBDeployer): simplify file type checks for downloading text files
All checks were successful
GBCI / build (push) Successful in 44s
2025-05-11 21:21:25 -03:00
Rodrigo Rodriguez (Pragmatismo)
f078881b0d feat(KeywordsExpressions, DialogKeywords, AdminDialog, GBDeployer, KBService): enhance functionality and improve file handling
All checks were successful
GBCI / build (push) Successful in 1m20s
2025-05-11 10:09:32 -03:00
Rodrigo Rodriguez (Pragmatismo)
1ef6cbb032 feat(KeywordsExpressions): add support for posting to Instagram with parameters
All checks were successful
GBCI / build (push) Successful in 2m2s
refactor(GBAdminService): improve folder name extraction logic
refactor(ImageProcessingServices): clean up whitespace and enhance image generation options
refactor(SystemKeywords): simplify rewrite prompt and logging
fix(ChatServices): correct spacing in model invocation
delete(marketing.gbai): remove outdated marketing poster template
add(marketing.gbai): create new marketing poster template with Instagram posting functionality
2025-05-09 21:19:14 -03:00
Rodrigo Rodriguez (Pragmatismo)
e3992b34af refactor(GBOService): remove unused imports for cleaner code
All checks were successful
GBCI / build (push) Successful in 50s
2025-04-30 14:19:00 -03:00
Rodrigo Rodriguez (Pragmatismo)
525703052d fix(DialogKeywords): comment out unused email headers in mail options
Some checks failed
GBCI / build (push) Has been cancelled
2025-04-30 14:18:32 -03:00
Rodrigo Rodriguez (Pragmatismo)
f34a4f25d0 feat(DialogKeywords): integrate Nodemailer for email sending functionality
All checks were successful
GBCI / build (push) Successful in 5m2s
2025-04-30 13:50:47 -03:00
Rodrigo Rodriguez (Pragmatismo)
7ababd7a80 feat(DialogKeywords): integrate Nodemailer for email sending functionality
Some checks failed
GBCI / build (push) Failing after 1m56s
2025-04-30 13:45:49 -03:00
Rodrigo Rodriguez (Pragmatismo)
320e401cad fix(GBMinService): update CORS origin to use HTTPS for improved security
All checks were successful
GBCI / build (push) Successful in 1m2s
2025-04-27 19:00:54 -03:00
Rodrigo Rodriguez (Pragmatismo)
2a61c07cd1 fix(GBMinService): update CORS origin to specific subdomain
All checks were successful
GBCI / build (push) Successful in 44s
2025-04-27 18:46:43 -03:00
Rodrigo Rodriguez (Pragmatismo)
b5034f9167 fix(GBMinService): add logging for meeting token requests and definition
All checks were successful
GBCI / build (push) Successful in 59s
2025-04-27 18:02:00 -03:00
Rodrigo Rodriguez (Pragmatismo)
c200456e38 fix(GBMinService): add logging for meeting token requests and definition
All checks were successful
GBCI / build (push) Successful in 1m15s
2025-04-26 21:44:02 -03:00
Rodrigo Rodriguez (Pragmatismo)
3ce1d1e152 fix(GBMinService): await token.toJwt() for proper JWT generation
All checks were successful
GBCI / build (push) Successful in 29s
2025-04-26 17:27:29 -03:00
Rodrigo Rodriguez (Pragmatismo)
b7f9c07faf fix(GBMinService): await token.toJwt() for proper JWT generation
All checks were successful
GBCI / build (push) Successful in 31s
2025-04-26 17:17:28 -03:00
Rodrigo Rodriguez (Pragmatismo)
7f7397b192 fix(dependencies): remove duplicate super-strong-password-generator entries in package.json
All checks were successful
GBCI / build (push) Successful in 2m36s
2025-04-26 17:01:02 -03:00
Rodrigo Rodriguez (Pragmatismo)
4db5e10b15 fix(workflow): clean up node_modules before installing production dependencies in BotServer
Some checks failed
GBCI / build (push) Failing after 2m32s
2025-04-26 16:56:38 -03:00
Rodrigo Rodriguez (Pragmatismo)
32183519d2 fix(workflow): enable npm ci command for production build in BotServer
Some checks failed
GBCI / build (push) Failing after 2m39s
2025-04-26 16:47:02 -03:00
Rodrigo Rodriguez (Pragmatismo)
a6e3722a2a fix(workflow): enable npm ci command for production build in BotServer
Some checks failed
GBCI / build (push) Failing after 2m56s
2025-04-26 16:40:42 -03:00
Rodrigo Rodriguez (Pragmatismo)
1b65edc213 feat(GBMinService): update dependencies to include livekit-server-sdk and AccessToken import
Some checks failed
GBCI / build (push) Failing after 37s
2025-04-26 16:14:53 -03:00
Rodrigo Rodriguez (Pragmatismo)
6f6dfca9c2 feat(GBMinService): add CORS header to meeting token endpoint
All checks were successful
GBCI / build (push) Successful in 37s
2025-04-26 15:25:35 -03:00
Rodrigo Rodriguez (Pragmatismo)
7175ab550b feat(GBMinService): add endpoint for generating meeting tokens with LiveKit
All checks were successful
GBCI / build (push) Successful in 1m29s
2025-04-26 15:15:57 -03:00
Rodrigo Rodriguez (Pragmatismo)
30460100d9 chore: remove deprecated files including deployment scripts, localization, and CI configurations
All checks were successful
GBCI / build (push) Successful in 1m4s
2025-04-25 02:24:52 -03:00
Rodrigo Rodriguez (Pragmatismo)
c6ddaa8ec9 chore: remove deprecated files including deployment scripts, localization, and CI configurations 2025-04-25 02:20:32 -03:00
Rodrigo Rodriguez (Pragmatismo)
4d850362d2 chore: remove unused image assets and update API URL in configuration 2025-04-25 01:46:35 -03:00
Rodrigo Rodriguez (Pragmatismo)
0cb49684e6 feat(GBMinService, MainService): integrate Stripe payment success handling and update dialog flow 2025-04-24 20:02:50 -03:00
Rodrigo Rodriguez (Pragmatismo)
feb7939387 feat(GBMinService, MainService): integrate Stripe payment success handling and update dialog flow 2025-04-24 19:52:06 -03:00
Rodrigo Rodriguez (Pragmatismo)
ec8b0d44df feat(GBMinService, MainService): integrate Stripe payment success handling and update dialog flow
All checks were successful
GBCI / build (push) Successful in 1m18s
2025-04-24 01:18:30 -03:00
Rodrigo Rodriguez (Pragmatismo)
e3ac4f58b3 refactor(GBOService, MainModel): clean up code and enhance model structure for better clarity and maintainability
All checks were successful
GBCI / build (push) Successful in 1m30s
2025-04-21 22:29:26 -03:00
Rodrigo Rodriguez (Pragmatismo)
9e08cb5e64 fix(SystemKeywords): enhance save method to support CSV files and improve row update logic
All checks were successful
GBCI / build (push) Successful in 1m5s
2025-04-19 22:34:42 -03:00
Rodrigo Rodriguez (Pragmatismo)
d4ad69c4b0 fix(DialogKeywords): modify file naming convention for improved clarity
All checks were successful
GBCI / build (push) Successful in 30s
2025-04-19 14:44:40 -03:00
Rodrigo Rodriguez (Pragmatismo)
b5369ad15c fix(DialogKeywords): update file writing method and adjust WhatsApp file sending logic
All checks were successful
GBCI / build (push) Successful in 39s
2025-04-19 14:39:21 -03:00
Rodrigo Rodriguez (Pragmatismo)
4f8067108f fix(DialogKeywords): update file writing method and adjust WhatsApp file sending logic
All checks were successful
GBCI / build (push) Successful in 29s
2025-04-19 14:36:48 -03:00
Rodrigo Rodriguez (Pragmatismo)
a003f5297c fix(DialogKeywords): update file writing method and adjust WhatsApp file sending logic
All checks were successful
GBCI / build (push) Successful in 46s
2025-04-19 14:33:58 -03:00
Rodrigo Rodriguez (Pragmatismo)
638534e31f fix(DialogKeywords): update file writing method and adjust WhatsApp file sending logic
All checks were successful
GBCI / build (push) Successful in 37s
2025-04-19 14:27:23 -03:00
Rodrigo Rodriguez (Pragmatismo)
7c05a95054 fix(DialogKeywords): update file writing method and adjust WhatsApp file sending logic
All checks were successful
GBCI / build (push) Successful in 28s
2025-04-19 14:20:15 -03:00
Rodrigo Rodriguez (Pragmatismo)
47e3c7648b fix(DialogKeywords): update file writing method and adjust WhatsApp file sending logic
All checks were successful
GBCI / build (push) Successful in 35s
2025-04-19 14:13:53 -03:00
Rodrigo Rodriguez (Pragmatismo)
d55a16aa80 fix(workflow): add logging for file copying in node.yaml
All checks were successful
GBCI / build (push) Successful in 1m3s
2025-04-19 14:05:43 -03:00
Rodrigo Rodriguez (Pragmatismo)
2feee016ca fix(workflow): add logging for file copying in node.yaml
All checks were successful
GBCI / build (push) Successful in 28s
2025-04-19 13:37:55 -03:00
Rodrigo Rodriguez (Pragmatismo)
9fe9444c69 fix(workflow): comment out Node.js setup and adjust build commands in node.yaml
All checks were successful
GBCI / build (push) Successful in 30s
2025-04-19 13:36:07 -03:00
Rodrigo Rodriguez (Pragmatismo)
84f2b7bd9b fix(ChatServices): update prompt message for clarity on tool results
All checks were successful
GBCI / build (push) Successful in 2m28s
2025-04-19 13:32:53 -03:00
Rodrigo Rodriguez (Pragmatismo)
449774c2d2 fix(ChatServices): update prompt message for clarity on tool results
All checks were successful
GBCI / build (push) Successful in 8m37s
2025-04-19 13:21:41 -03:00
Rodrigo Rodriguez (Pragmatismo)
827b4451a8 fix(ChatServices): enhance logging and clarify response instructions
All checks were successful
GBCI / build (push) Successful in 8m22s
2025-04-19 12:39:25 -03:00
Rodrigo Rodriguez (Pragmatismo)
46176fe2f3 fix(workflow): streamline botserver restart process in node.yaml
All checks were successful
GBCI / build (push) Successful in 8m35s
2025-04-19 12:14:18 -03:00
Rodrigo Rodriguez (Pragmatismo)
c599932c10 fix(workflow): ensure BotServer directory is created before copying files
Some checks failed
GBCI / build (push) Has been cancelled
2025-04-19 11:48:09 -03:00
Rodrigo Rodriguez (Pragmatismo)
b6be0b5418 fix(workflow): ensure BotServer directory is created before copying files
Some checks failed
GBCI / build (push) Has been cancelled
2025-04-19 11:36:07 -03:00
Rodrigo Rodriguez (Pragmatismo)
bc5e18c4f0 fix(workflow): ensure BotServer directory is created before copying files
Some checks failed
GBCI / build (push) Has been cancelled
2025-04-19 11:14:26 -03:00
Rodrigo Rodriguez (Pragmatismo)
380f2ce83a fix(workflow): ensure BotServer directory is created before copying files
All checks were successful
GBCI / build (push) Successful in 6m33s
2025-04-19 01:42:51 -03:00
Rodrigo Rodriguez (Pragmatismo)
8e58038295 fix(workflow): ensure BotServer directory is created before copying files
All checks were successful
GBCI / build (push) Successful in 8m8s
2025-04-19 01:12:54 -03:00
Rodrigo Rodriguez (Pragmatismo)
79ca7e1da0 fix(workflow): update node.yaml to correctly copy .env file to deployment location
Some checks failed
GBCI / build (push) Failing after 18s
2025-04-19 01:09:16 -03:00
Rodrigo Rodriguez (Pragmatismo)
0364526fc6 fix(workflow): update node.yaml to run npm start in the background
Some checks failed
GBCI / build (push) Failing after 1m3s
2025-04-19 00:24:43 -03:00
Rodrigo Rodriguez (Pragmatismo)
ce78abdceb fix(workflow): update node.yaml to run npm start in the background
Some checks failed
GBCI / build (push) Failing after 3m19s
2025-04-18 23:48:26 -03:00
Rodrigo Rodriguez (Pragmatismo)
bc0aa7627e feat: update dependencies and improve file handling in GBVMService
Some checks failed
GBCI / build (push) Failing after 3m57s
2025-04-18 22:20:33 -03:00
Rodrigo Rodriguez (Pragmatismo)
ea224b4937 feat: add bcrypt for password hashing and comparison utilities
Some checks failed
GBCI / build (push) Failing after 3m46s
2025-04-17 21:45:46 -03:00
Rodrigo Rodriguez (Pragmatismo)
31b7d5d59e fix(GBMinService): comment out file writing to prevent overwriting bot manifest
Some checks failed
GBCI / build (push) Failing after 1h26m41s
2025-04-17 16:21:02 -03:00
Rodrigo Rodriguez (Pragmatismo)
87802e4249 fix(SystemKeywords): update file writing to use Uint8Array for buffer consistency
Some checks failed
GBCI / build (push) Has been cancelled
2025-04-17 16:15:27 -03:00
Rodrigo Rodriguez (Pragmatismo)
eb9ddb7ead feat(SystemKeywords): integrate MinIO client for file retrieval in gbcluster mode
Some checks failed
GBCI / build (push) Failing after 4m47s
2025-04-17 15:05:09 -03:00
Rodrigo Rodriguez (Pragmatismo)
d2851aabd6 feat(DialogKeywords): integrate MinIO client for file handling in gbcluster mode
Some checks failed
GBCI / build (push) Failing after 3h14m23s
2025-04-15 13:56:56 -03:00
Rodrigo Rodriguez (Pragmatismo)
7035c6799f feat(DialogKeywords): integrate MinIO client for file handling in gbcluster mode
Some checks failed
GBCI / build (push) Failing after 4m4s
2025-04-15 13:46:02 -03:00
Rodrigo Rodriguez (Pragmatismo)
0a69ff1d8b feat(DialogKeywords): integrate MinIO client for file handling in gbcluster mode
Some checks failed
GBCI / build (push) Has been cancelled
2025-04-15 13:30:42 -03:00
Rodrigo Rodriguez (Pragmatismo)
ffdea65c59 feat(DialogKeywords): integrate MinIO client for file handling in gbcluster mode
Some checks failed
GBCI / build (push) Failing after 4m16s
2025-04-15 13:19:51 -03:00
Rodrigo Rodriguez (Pragmatismo)
6d75b4997b fix: update URLs and email addresses to reflect new domain 2025-04-15 12:49:05 -03:00
Rodrigo Rodriguez (Pragmatismo)
6e141e25a7 fix(app): comment out boot instance creation and saving in legacy mode
Some checks failed
GBCI / build (push) Failing after 2h8m50s
2025-04-04 19:11:12 -03:00
Rodrigo Rodriguez (Pragmatismo)
70c2d7c0d5 fix(app): comment out boot instance creation and saving in legacy mode
Some checks failed
GBCI / build (push) Has been cancelled
2025-04-04 18:34:57 -03:00
Rodrigo Rodriguez (Pragmatismo)
8ffc62ed67 fix(app): comment out boot instance creation and saving in legacy mode
Some checks failed
GBCI / build (push) Has been cancelled
2025-04-04 18:27:39 -03:00
Rodrigo Rodriguez (Pragmatismo)
97862e54a5 fix(app): comment out boot instance creation and saving in legacy mode
All checks were successful
GBCI / build (push) Successful in 6m44s
2025-04-04 16:14:08 -03:00
Rodrigo Rodriguez (Pragmatismo)
7594cea1e0 fix(services): add ordering to GuaribasInstance query in GBCoreService
Some checks failed
GBCI / build (push) Failing after 3h10m7s
2025-04-03 14:53:05 -03:00
Rodrigo Rodriguez (Pragmatismo)
56504beea3 fix(services): add ordering to GuaribasInstance query in GBCoreService
Some checks failed
GBCI / build (push) Failing after 7m1s
2025-04-03 14:20:08 -03:00
Rodrigo Rodriguez (Pragmatismo)
081cd8a8b6 fix(services): add ordering to GuaribasInstance query in GBCoreService
Some checks failed
GBCI / build (push) Failing after 1h49m6s
2025-03-30 00:20:44 -03:00
Rodrigo Rodriguez (Pragmatismo)
e300fcda60 fix(services): change script file extension from .docx to .vbs in KBService
Some checks failed
GBCI / build (push) Failing after 8m50s
2025-03-30 00:07:05 -03:00
Rodrigo Rodriguez (Pragmatismo)
2617409867 fix(services): add ordering to GuaribasInstance query in GBCoreService
Some checks failed
GBCI / build (push) Has been cancelled
2025-03-29 23:12:53 -03:00
Rodrigo Rodriguez (Pragmatismo)
905dc5642e fix(services): add ordering to GuaribasInstance query in GBCoreService
Some checks failed
GBCI / build (push) Has been cancelled
2025-03-29 22:11:57 -03:00
Rodrigo Rodriguez (Pragmatismo)
0d89750a57 fix(services): update condition in GBMinService to simplify WhatsApp Direct Line setup
Some checks failed
GBCI / build (push) Has been cancelled
2025-03-29 20:38:55 -03:00
Rodrigo Rodriguez (Pragmatismo)
ba750a289f fix(services): refactor GBOService instantiation and update template listing logic
Some checks failed
GBCI / build (push) Has been cancelled
2025-03-29 20:27:22 -03:00
Rodrigo Rodriguez (Pragmatismo)
0e74502cc1 fix(services): refactor GBOService instantiation and update template listing logic 2025-03-29 11:03:46 -03:00
Rodrigo Rodriguez (Pragmatismo)
61d8cfe93c fix(workflows): clean up node.yaml by removing unnecessary commented-out commands
Some checks failed
GBCI / build (push) Failing after 3h13m32s
2025-03-28 10:24:41 -03:00
Rodrigo Rodriguez (Pragmatismo)
dbc1611b74 fix(workflows): clean up node.yaml by removing unnecessary commented-out commands
Some checks failed
GBCI / build (push) Has been cancelled
2025-03-28 09:27:15 -03:00
Rodrigo Rodriguez (Pragmatismo)
e7241cde67 fix(workflows): clean up node.yaml by removing unnecessary commented-out commands
All checks were successful
GBCI / build (push) Successful in 0s
2025-03-28 09:20:12 -03:00
Rodrigo Rodriguez (Pragmatismo)
a8f4643d9c fix(workflows): clean up node.yaml by removing unnecessary commented-out commands
Some checks failed
GBCI / build (push) Failing after 0s
2025-03-28 09:19:10 -03:00
Rodrigo Rodriguez (Pragmatismo)
d3c62ba406 fix(workflows): clean up node.yaml by removing unnecessary commented-out commands
Some checks failed
GBCI / build (push) Failing after 0s
2025-03-28 09:18:37 -03:00
Rodrigo Rodriguez (Pragmatismo)
dd14d83f98 fix(workflows): clean up node.yaml by removing unnecessary commented-out commands
Some checks failed
GBCI / build (push) Failing after 0s
2025-03-28 09:18:08 -03:00
Rodrigo Rodriguez (Pragmatismo)
3ab6b9c8e7 fix(workflows): clean up node.yaml by removing unnecessary commented-out commands
All checks were successful
GBCI / build (push) Successful in 5s
2025-03-28 09:17:08 -03:00
Rodrigo Rodriguez (Pragmatismo)
5f2472ced2 fix(workflows): clean up node.yaml by removing unnecessary commented-out commands
Some checks failed
GBCI / build (push) Failing after 19s
2025-03-28 09:16:14 -03:00
Rodrigo Rodriguez (Pragmatismo)
c07fd1cbd8 fix(workflows): clean up node.yaml by removing unnecessary commented-out commands
All checks were successful
GBCI / build (push) Successful in 0s
2025-03-28 09:15:50 -03:00
Rodrigo Rodriguez (Pragmatismo)
672d8b905f fix(workflows): clean up node.yaml by removing unnecessary commented-out commands
All checks were successful
GBCI / build (push) Successful in 0s
2025-03-28 09:14:55 -03:00
Rodrigo Rodriguez (Pragmatismo)
277ce61619 fix(workflows): clean up node.yaml by removing unnecessary commented-out commands
All checks were successful
GBCI / build (push) Successful in 0s
2025-03-28 09:13:15 -03:00
Rodrigo Rodriguez (Pragmatismo)
337848b241 fix(workflows): clean up node.yaml by removing unnecessary commented-out commands
All checks were successful
GBCI / build (push) Successful in 4s
2025-03-28 09:11:28 -03:00
Rodrigo Rodriguez (Pragmatismo)
00ed68281e fix(workflows): clean up node.yaml by removing unnecessary commented-out commands
All checks were successful
GBCI / build (push) Successful in 0s
2025-03-28 09:09:08 -03:00
Rodrigo Rodriguez (Pragmatismo)
9d44b7f3f5 fix(workflows): clean up node.yaml by removing unnecessary commented-out commands
All checks were successful
GBCI / build (push) Successful in 0s
2025-03-28 09:08:37 -03:00
Rodrigo Rodriguez (Pragmatismo)
7835a8ede8 fix(workflows): clean up node.yaml by removing unnecessary commented-out commands
All checks were successful
GBCI / build (push) Successful in 1s
2025-03-28 09:01:06 -03:00
Rodrigo Rodriguez (Pragmatismo)
8742c736a4 fix(workflows): clean up node.yaml by removing unnecessary commented-out commands
All checks were successful
GBCI / build (push) Successful in 0s
2025-03-28 08:59:25 -03:00
Rodrigo Rodriguez (Pragmatismo)
935503400d fix(workflows): clean up node.yaml by removing unnecessary commented-out commands
All checks were successful
GBCI / build (push) Successful in 1s
2025-03-28 08:57:41 -03:00
Rodrigo Rodriguez (Pragmatismo)
d30ec7e85b fix(workflows): clean up node.yaml by removing unnecessary commented-out commands
All checks were successful
GBCI / build (push) Successful in 0s
2025-03-28 08:49:06 -03:00
Rodrigo Rodriguez (Pragmatismo)
83bd0f5b13 fix(workflows): clean up node.yaml by removing unnecessary commented-out commands
All checks were successful
GBCI / build (push) Successful in 0s
2025-03-28 08:45:50 -03:00
Rodrigo Rodriguez (Pragmatismo)
60d4028cf5 fix(workflows): clean up node.yaml by removing unnecessary commented-out commands
Some checks failed
GBCI / build (push) Failing after 2m29s
2025-03-28 08:42:24 -03:00
Rodrigo Rodriguez (Pragmatismo)
a533e1fbd9 fix(services): remove unnecessary comments and improve URL configuration in GBCoreService and GBMinService
Some checks failed
GBCI / build (push) Failing after 0s
2025-03-28 08:40:46 -03:00
Rodrigo Rodriguez (Pragmatismo)
42b718a4b3 fix(services): remove unnecessary comments and improve URL configuration in GBCoreService and GBMinService
All checks were successful
GBCI / build (push) Successful in 0s
2025-03-28 08:39:06 -03:00
Rodrigo Rodriguez (Pragmatismo)
759caba765 fix(services): remove unnecessary comments and improve URL configuration in GBCoreService and GBMinService
All checks were successful
GBCI / build (push) Successful in 6m13s
2025-03-28 08:03:30 -03:00
Rodrigo Rodriguez (Pragmatismo)
1b6dcb061b fix(services): remove unnecessary comments and improve URL configuration in GBCoreService and GBMinService
All checks were successful
GBCI / build (push) Successful in 5m13s
2025-03-28 07:48:50 -03:00
Rodrigo Rodriguez (Pragmatismo)
98e6badbb2 fix(workflows): clean up node.yaml by removing unnecessary whitespace
All checks were successful
GBCI / build (push) Successful in 5m56s
2025-03-28 07:35:45 -03:00
Rodrigo Rodriguez (Pragmatismo)
8584e43cc7 fix(workflows): clean up node.yaml by removing unnecessary whitespace
All checks were successful
GBCI / build (push) Successful in 6m4s
2025-03-28 07:14:35 -03:00
Rodrigo Rodriguez (Pragmatismo)
49203c3abb fix(workflows): clean up node.yaml by removing unnecessary whitespace
All checks were successful
GBCI / build (push) Successful in 4m53s
2025-03-26 23:39:06 -03:00
Rodrigo Rodriguez (Pragmatismo)
1421600cc5 fix(workflows): clean up node.yaml by removing unnecessary whitespace
Some checks failed
GBCI / build (push) Failing after 4m14s
2025-03-26 23:33:23 -03:00
Rodrigo Rodriguez (Pragmatismo)
294efd42f1 fix(workflows): clean up node.yaml by removing unnecessary whitespace
Some checks failed
GBCI / build (push) Failing after 3m41s
2025-03-26 23:24:58 -03:00
Rodrigo Rodriguez (Pragmatismo)
d921be4435 fix(workflows): clean up node.yaml by removing unnecessary whitespace
Some checks failed
GBCI / build (push) Failing after 7m32s
2025-03-26 22:56:02 -03:00
Rodrigo Rodriguez (Pragmatismo)
195ac0e411 fix(workflows): clean up node.yaml by removing unnecessary whitespace
Some checks failed
GBCI / build (push) Failing after 9s
2025-03-26 22:41:47 -03:00
Rodrigo Rodriguez (Pragmatismo)
296365ea3f fix(workflows): clean up node.yaml by removing unnecessary whitespace
Some checks failed
GBCI / build (push) Failing after 17s
2025-03-26 22:36:40 -03:00
Rodrigo Rodriguez (Pragmatismo)
3a1af21e6f fix(workflows): clean up node.yaml by removing unnecessary whitespace
Some checks failed
GBCI / build (push) Failing after 27s
2025-03-26 21:43:49 -03:00
Rodrigo Rodriguez (Pragmatismo)
7326727540 fix(workflows): clean up node.yaml by removing unnecessary whitespace
Some checks failed
GBCI / build (push) Failing after 31s
2025-03-26 21:36:37 -03:00
Rodrigo Rodriguez (Pragmatismo)
f2bf5bc047 fix(workflows): clean up node.yaml by removing unnecessary whitespace
Some checks failed
GBCI / build (push) Failing after 38s
2025-03-26 21:29:00 -03:00
Rodrigo Rodriguez (Pragmatismo)
b7c34446da fix(workflows): clean up node.yaml by removing unnecessary whitespace 2025-03-26 20:56:10 -03:00
Rodrigo Rodriguez (Pragmatismo)
337f93848f fix(workflows): change build runner from CI to gbo 2025-03-26 20:35:27 -03:00
Rodrigo Rodriguez (Pragmatismo)
c3ea648279 fix(workflows): change build runner from CI to gbo 2025-03-26 20:34:11 -03:00
Rodrigo Rodriguez (Pragmatismo)
d83bb86af3 fix(workflows): change build runner from CI to gbo 2025-03-26 20:29:33 -03:00
Rodrigo Rodriguez (Pragmatismo)
47debcf2e7 fix(workflows): change build runner from CI to gbo
Some checks failed
GBCI / build (push) Failing after 1m26s
2025-03-26 19:50:42 -03:00
Rodrigo Rodriguez (Pragmatismo)
dbdb75c4d6 delete: Remove issue and pull request templates
Some checks are pending
GBCI / build (push) Waiting to run
2025-03-26 19:49:41 -03:00
Rodrigo Rodriguez (Pragmatismo)
c80eabb066 delete: Remove issue and pull request templates
Some checks are pending
GBCI / build (push) Waiting to run
2025-03-26 19:46:19 -03:00
Rodrigo Rodriguez (Pragmatismo)
5fe45a04f7 new(all): Removal of OneDrive dependencies. 2025-03-05 22:09:05 -03:00
Rodrigo Rodriguez
e557eaa24f new(whatsapp.gblib): FB Analytics. 2025-02-16 21:47:03 -03:00
Rodrigo Rodriguez
8cdc814199 new(whatsapp.gblib): FB Analytics. 2025-02-16 21:41:38 -03:00
Rodrigo Rodriguez
beffc53463 new(whatsapp.gblib): FB Analytics. 2025-02-16 21:01:10 -03:00
Rodrigo Rodriguez
4521f6c342 new(whatsapp.gblib): FB Analytics. 2025-02-16 20:56:01 -03:00
Rodrigo Rodriguez
bb3a6a7a84 new(whatsapp.gblib): FB Analytics. 2025-02-16 20:53:04 -03:00
Rodrigo Rodriguez
592c25492d new(whatsapp.gblib): FB Analytics. 2025-02-16 20:47:16 -03:00
Rodrigo Rodriguez
23ed6f8932 new(whatsapp.gblib): FB Analytics. 2025-02-16 20:34:54 -03:00
Rodrigo Rodriguez
0f2f369a2b new(whatsapp.gblib): FB Analytics. 2025-02-16 20:26:09 -03:00
Rodrigo Rodriguez
d5d0f235a7 new(whatsapp.gblib): FB Analytics. 2025-02-16 19:29:53 -03:00
Rodrigo Rodriguez
091c9825bf new(whatsapp.gblib): FB Analytics. 2025-02-16 19:27:57 -03:00
Rodrigo Rodriguez
5183a2bdca new(whatsapp.gblib): FB Analytics. 2025-02-16 19:23:18 -03:00
Rodrigo Rodriguez
be3ba92429 new(whatsapp.gblib): FB Analytics. 2025-02-16 19:21:09 -03:00
Rodrigo Rodriguez
fe1f5d5150 new(whatsapp.gblib): FB Analytics. 2025-02-16 19:13:10 -03:00
Rodrigo Rodriguez
760cb807cc new(whatsapp.gblib): FB Analytics. 2025-02-16 19:08:26 -03:00
Rodrigo Rodriguez
b9db5840c9 new(whatsapp.gblib): FB Analytics. 2025-02-16 19:04:10 -03:00
Rodrigo Rodriguez
b8a9740792 new(whatsapp.gblib): FB Analytics. 2025-02-16 18:56:07 -03:00
Rodrigo Rodriguez
8a8884da64 new(whatsapp.gblib): FB Analytics. 2025-02-16 18:42:16 -03:00
Rodrigo Rodriguez
9978e35f33 new(whatsapp.gblib): FB Analytics. 2025-02-16 18:28:09 -03:00
Rodrigo Rodriguez
ffd7b52ade new(whatsapp.gblib): FB Analytics. 2025-02-16 18:24:08 -03:00
Rodrigo Rodriguez
a693265cb1 new(whatsapp.gblib): FB Analytics. 2025-02-16 18:22:14 -03:00
Rodrigo Rodriguez
614539a0b4 new(whatsapp.gblib): FB Analytics. 2025-02-16 18:16:14 -03:00
Rodrigo Rodriguez
292d396eeb new(whatsapp.gblib): FB Analytics. 2025-02-16 18:09:46 -03:00
Rodrigo Rodriguez
36667b5c4b new(whatsapp.gblib): FB Analytics. 2025-02-16 18:05:06 -03:00
Rodrigo Rodriguez
61e72cd186 new(whatsapp.gblib): FB Analytics. 2025-02-16 17:57:01 -03:00
Rodrigo Rodriguez
52dbc5a109 new(whatsapp.gblib): FB Analytics. 2025-02-16 10:54:42 -03:00
Rodrigo Rodriguez
4010fca0cf fix(whatsapp.gblib): Fixed audio with IBM Watson. 2025-02-02 18:42:45 -03:00
Rodrigo Rodriguez
f5a383dd1a fix(whatsapp.gblib): Fixed audio with IBM Watson. 2025-02-02 18:29:58 -03:00
Rodrigo Rodriguez
a6d3ec38b3 fix(whatsapp.gblib): Fixed audio with IBM Watson. 2025-02-02 17:44:25 -03:00
Rodrigo Rodriguez
54b2b6a56e fix(whatsapp.gblib): Fixed audio with IBM Watson. 2025-02-02 17:06:43 -03:00
Rodrigo Rodriguez
a654b9a35c fix(whatsapp.gblib): Fixed check status. 2025-01-27 11:37:41 -03:00
Rodrigo Rodriguez
e17f4c8800 fix(whatsapp.gblib): Fixed check status. 2025-01-27 10:57:47 -03:00
Rodrigo Rodriguez
8aff53ef86 fix(whatsapp.gblib): Fixed check status. 2025-01-27 10:55:04 -03:00
Rodrigo Rodriguez
8028c821cb fix(whatsapp.gblib): Fixed check status. 2025-01-27 10:49:57 -03:00
Rodrigo Rodriguez
fb5aeca78c fix(kb.gblib): Fixed crawler. 2025-01-19 16:06:43 -03:00
Rodrigo Rodriguez
8ae34432b9 new(kb.gblib): added postgres. 2025-01-17 16:48:45 -03:00
Rodrigo Rodriguez
fbedd78c74 new(kb.gblib): added postgres. 2025-01-17 16:28:40 -03:00
Rodrigo Rodriguez
d3ae8dd487 new(kb.gblib): added postgres. 2025-01-16 05:47:28 -03:00
Rodrigo Rodriguez
ded9026e91 new(kb.gblib): added postgres. 2025-01-16 05:42:50 -03:00
Rodrigo Rodriguez
4298303ea4 new(kb.gblib): added postgres. 2025-01-16 05:29:53 -03:00
Rodrigo Rodriguez
632010310b new(kb.gblib): added postgres. 2025-01-16 05:22:48 -03:00
Rodrigo Rodriguez
f6a1cf2820 new(kb.gblib): added postgres. 2025-01-16 05:12:08 -03:00
Rodrigo Rodriguez
41803803d5 new(kb.gblib): added postgres. 2025-01-16 05:07:35 -03:00
Rodrigo Rodriguez
745819b732 new(kb.gblib): added postgres. 2025-01-16 04:59:22 -03:00
Rodrigo Rodriguez
57b83aba2b new(kb.gblib): added postgres. 2025-01-16 04:53:05 -03:00
Rodrigo Rodriguez
c97a6ec0bf new(kb.gblib): added postgres. 2025-01-16 04:48:12 -03:00
Rodrigo Rodriguez
b751dbb418 new(kb.gblib): added postgres. 2025-01-16 04:34:43 -03:00
Rodrigo Rodriguez
fc7c4c5be1 new(kb.gblib): added postgres. 2025-01-16 02:52:59 -03:00
Rodrigo Rodriguez
76a4656ad6 new(kb.gblib): added postgres. 2025-01-16 02:51:30 -03:00
Rodrigo Rodriguez
e32261ec1d new(kb.gblib): added postgres. 2025-01-16 02:38:18 -03:00
Rodrigo Rodriguez
5817f5ead6 new(kb.gblib): added postgres. 2025-01-16 02:31:07 -03:00
Rodrigo Rodriguez
31301e29bc new(kb.gblib): added postgres. 2025-01-16 02:23:52 -03:00
Rodrigo Rodriguez
4be13899f5 new(kb.gblib): added postgres. 2025-01-16 02:11:12 -03:00
Rodrigo Rodriguez
284cdac428 Merge branch 'main' of https://github.com/GeneralBots/BotServer into main 2025-01-01 21:33:57 -03:00
Rodrigo Rodriguez
d39200568b fix(kb.gblib): fix in crawler. 2025-01-01 21:33:56 -03:00
Rodrigo Rodriguez
6d7e8ff909
Update README.md 2024-12-22 14:45:07 -03:00
Rodrigo Rodriguez
c83fa6d74b
Update README.md 2024-12-22 14:41:43 -03:00
Rodrigo Rodriguez
3bd3d72b48
Update README.md 2024-12-22 14:41:19 -03:00
Rodrigo Rodriguez
2275f34291
Merge pull request #437 from GeneralBots/rodrigorodriguez-patch-6
Update README.md
2024-12-22 14:34:40 -03:00
Rodrigo Rodriguez
ab54059d2b
Update README.md 2024-12-22 14:34:16 -03:00
Rodrigo Rodriguez
996caba2df
Add files via upload 2024-12-22 14:32:30 -03:00
Rodrigo Rodriguez
50cfc07966
Merge pull request #436 from GeneralBots/rodrigorodriguez-patch-5
Update README.md
2024-12-22 14:31:28 -03:00
Rodrigo Rodriguez
484027377a
Update README.md 2024-12-22 14:31:05 -03:00
Rodrigo Rodriguez
5be2294893
Merge pull request #435 from GeneralBots/rodrigorodriguez-patch-4
Update README.md
2024-12-22 14:28:14 -03:00
163 changed files with 51910 additions and 4758 deletions

View file

@ -1,2 +0,0 @@
[config]
command = bash ./deploy.sh

View file

@ -0,0 +1,46 @@
name: GBCI
run: git config --global http.sslVerify false
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: gbo
steps:
- name: Disable SSL verification (temporary)
run: git config --global http.sslVerify false
- uses: actions/checkout@v4
# - name: Setup Node.js
# uses: actions/setup-node@v4
# with:
# node-version: '20'
# cache: 'npm'
- name: Copy files to deployment location
run: |
echo "[General Bots Deployer] Copying files to deploy location..."
sudo rm -rf /opt/gbo/bin/bot/botserver/dist
sudo cp -r ./* /opt/gbo/bin/bot/botserver
- name: Building BotServer
run: |
echo "[General Bots Deployer] Building BotServer..."
# rm -rf /opt/gbo/bin/bot/botserver/node_modules
cd /opt/gbo/bin/bot/botserver
sudo npm ci --production
npm run build-server
npm run build-gbui
- name: Restart Bots Deployer
run: |
echo "[General Bots Deployer] Restarting..."
lxc restart pragmatismo-bot

View file

@ -1,9 +0,0 @@
<!-- File a GitHub issue only for bugs or feature requests related to the code **in this repository**. For other topics you can get more information in the README file. -->
### Observed Results:
<!-- This could be a description, error output, steps to reproduce, a feature missed, etc. -->
### Expected behavior:
<!-- What did you expect to happen? -->

View file

@ -1,35 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View file

@ -1,7 +0,0 @@
---
name: Custom issue template
about: Describe this issue template's purpose here.
---

View file

@ -1,17 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View file

@ -1,2 +0,0 @@
**Description**
A clear and concise description of what the requirement is.

View file

@ -1,16 +0,0 @@
### Changes description
<!-- Describe results, user mentions, screenshots, screencast (gif) -->
### Checklist
Please check if your PR fulfills the following specifications:
- [ ] Tests for the changes have been done
- [ ] Docs have been added/updated
### References
<!-- issues related (for reference or to be closed) and/or links of discuss -->
Closes #N/A

View file

@ -1,3 +0,0 @@
isOutside: true
# Team Name
team: contributors

44
.github/settings.yml vendored
View file

@ -1,44 +0,0 @@
repository:
name: botserver
description: botserver
homepage: http://pragmatismo.cloud/general-bots
topics: node-module
private: false
has_issues: true
has_wiki: false
has_downloads: true
default_branch: develop
allow_squash_merge: true
allow_merge_commit: false
allow_rebase_merge: true
labels:
- name: bug
color: f44336
- name: build
color: 795548
- name: ci
color: fbca04
- name: documentation
color: 607d8b
- name: duplicate
color: 9e9e9e
- name: feature
color: 3f51b5
- name: invalid
color: cddc39
- name: performance
color: 009688
- name: question
color: ff5722
- name: refactor
color: 9c27b0
- name: style
color: 2196f3
- name: test
color: 8bc34a
- name: wontfix
color: ffffff
- name: help wanted
color: 33aa3f
- name: good first issue
color: 7057ff

3
.gitignore vendored
View file

@ -25,9 +25,10 @@ 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*

View file

@ -1,33 +0,0 @@
dist: focal
language: node_js
node_js:
- 19.7.0
notifications:
email: false
before_script:
- npm run build
branches:
only:
- main
- /^greenkeeper/.*$/
except:
- /^v\d+\.\d+\.\d+$/
after_success:
- npm install -g travis-deploy-once
- npm run travis-deploy-once "npm run semantic-release"
- npm pack
deploy:
- provider: pages
skip_cleanup: true
local_dir: docs/reference
github_token: $GITHUB_TOKEN
on:
tags: false
branch: main

30
.vscode/launch.json vendored
View file

@ -1,30 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"sourceMaps": true,
"name": "Debug Program",
"runtimeExecutable": "node",
"program": "${workspaceRoot}/boot.mjs",
"cwd": "${workspaceRoot}",
"env": {
"NODE_ENV": "development",
"NODE_NO_WARNINGS": "1"
},
"args": [
"--require", "${workspaceRoot}/suppress-node-warnings.cjs"
],
"skipFiles": [
"node_modules/**/*.js",
"<node_internals>/**"
],
"outFiles": [
"${workspaceRoot}/dist/**/*.js"
],
"stopOnEntry": false,
"console": "integratedTerminal"
}
]
}

View file

@ -1,4 +0,0 @@
{
"git.ignoreLimitWarning": true,
"cmake.ignoreCMakeListsMissing": true
}

30
.vscode/tasks.json vendored
View file

@ -1,30 +0,0 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"type": "typescript",
"tsconfig": "tsconfig.json",
"option": "watch",
"problemMatcher": [
"$tsc-watch"
],
"group": {
"kind": "build",
"isDefault": true
}
},
{
"type": "typescript",
"tsconfig": "tsconfig.json",
"problemMatcher": [
"$tsc"
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

View file

@ -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.cloud team. Your pull request should include a link to the bug that you are fixing. If you've submitted a PR for a bug, please post a comment in the bug to avoid duplication of effort.
A bug must have an issue tracking it in the issue tracker that has been approved by the pragmatismo.com.br team. Your pull request should include a link to the bug that you are fixing. If you've submitted a PR for a bug, please post a comment in the bug to avoid duplication of effort.
## Contributing features
@ -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.cloud. By signing a contributor license agreement, we ensure that the community is free to use your contributions.
We appreciate community contributions to code repositories open sourced by pragmatismo.com.br. By signing a contributor license agreement, we ensure that the community is free to use your contributions.
## Housekeeping

View file

@ -1,8 +0,0 @@
# General Bots Features
| Feature | BF | GB |
|----------------------------------------------------------------------------|----|----|
| Use of conversational administration to manage bot packages (Talk to admin)| - | X |
| F5 to run on VSCode | - | X |
| Isolated code on packages | - | X |
| Breaking changes protected | - | X |

View file

@ -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.cloud
edition of General bots you have installed, please ask info@pragmatismo.com.br
informing your Customer ID.
If you modify this Program, or any covered work, by combining it

View file

@ -1,7 +0,0 @@
# Localization in General Bots
## .gbapp
The localization is done by adding a strings.ts file to the root of the .gbapp package.

115
README.md
View file

@ -1,16 +1,19 @@
### Key Facts
- AGPL License (to use as custom-label SaaS)
- LLM Orchestrator AGPL licensed (to use as custom-label SaaS, contributing back)
- True community governance
- 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 |
|------------------------------|----------------------------------------------------------------------------------------------------|
@ -18,17 +21,16 @@
| Community | [![StackExchange](https://img.shields.io/stackexchange/stackoverflow/t/generalbots.svg)](https://stackoverflow.com/questions/tagged/generalbots) [![Open-source](https://badges.frapsoft.com/os/v2/open-source.svg)](https://badges.frapsoft.com) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) [![License](https://img.shields.io/badge/license-AGPL-blue.svg)](https://github.com/GeneralBots/BotServer/blob/master/LICENSE.txt)|
| Management | [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://gitHub.com/GeneralBots/BotServer/graphs/commit-activity) |
| Security | [![Known Vulnerabilities](https://snyk.io/test/github/GeneralBots/BotServer/badge.svg)](https://snyk.io/test/github/GeneralBots/BotServer) |
| Building & Quality | [![Build Status](https://travis-ci.com/GeneralBots/BotServer.svg?branch=master)](https://app.travis-ci.com/github/GeneralBots/BotServer) [![Coverage Status](https://coveralls.io/repos/github/GeneralBots/BotServer/badge.svg)](https://coveralls.io/github/GeneralBots/BotServer) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) |
| Packaging | [![forthebadge](https://badge.fury.io/js/botserver.svg)](https://badge.fury.io) [![ZipFile](https://camo.githubusercontent.com/0150c0f148d50fe9750ebc5d313581da699a8c50/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7a69702d646f776e6c6f61642d626c75652e737667)](https://github.com/GeneralBots/BotServer/releases/latest) [![Dependencies](https://david-dm.org/GeneralBots/botserver.svg)](https://david-dm.org) [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/) |
| Samples | [VBA](https://github.com/GeneralBots/BotServer/tree/master/packages/default.gbdialog) or [![TypeScript](https://badges.frapsoft.com/typescript/code/typescript.svg?v=101)](https://github.com/GeneralBots/AzureADPasswordReset.gbapp)
| [Docker Image](https://github.com/lpicanco/docker-botserver) | ![Docker Automated build](https://img.shields.io/docker/automated/lpicanco/botserver.svg) ![Docker Build Status](https://img.shields.io/docker/build/lpicanco/botserver.svg) ![MicroBadger Size](https://img.shields.io/microbadger/image-size/lpicanco/botserver.svg) ![MicroBadger Layers](https://img.shields.io/microbadger/layers/lpicanco/botserver.svg) ![Docker Pulls](https://img.shields.io/docker/pulls/lpicanco/botserver.svg) <br/> *Provided by [@lpicanco](https://github.com/lpicanco/docker-botserver)* |
| Building & Quality | [![Coverage Status](https://coveralls.io/repos/github/GeneralBots/BotServer/badge.svg)](https://coveralls.io/github/GeneralBots/BotServer) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) |
| Packaging | [![forthebadge](https://badge.fury.io/js/botserver.svg)](https://badge.fury.io) [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/) |
| Samples | [BASIC](https://github.com/GeneralBots/BotServer/tree/master/packages/default.gbdialog) or [![TypeScript](https://badges.frapsoft.com/typescript/code/typescript.svg?v=101)](https://github.com/GeneralBots/AzureADPasswordReset.gbapp)
| [Docker Image](https://github.com/lpicanco/docker-botserver) ![Docker Pulls](https://img.shields.io/docker/pulls/lpicanco/botserver.svg) <br/> *Provided by [@lpicanco](https://github.com/lpicanco/docker-botserver)* |
General Bots
------------------
# General Bots
![General Bot Logo](https://raw.githubusercontent.com/pragmatismo-io/BotServer/master/logo.png)
![General Bot Logo](https://github.com/GeneralBots/BotServer/blob/main/logo.png?raw=true))
General Bot is a strongly typed package based chat bot server focused in convention over configuration and code-less approaches, which brings software packages and application server concepts to help parallel bot development.
General Bot is a strongly typed LLM conversational platform package based chat bot server focused in convention over configuration and code-less approaches, which brings software packages and application server concepts to help parallel bot development.
## What is a Bot Server?
@ -42,9 +44,78 @@ advanced fashion writing custom code in editors like Visual Studio Code, Atom or
Everyone can create bots by just copying and pasting some files and using their
favorite tools from Office (or any text editor) or Photoshop (or any image
editor). BASIC can be used to build custom dialogs so Bot can be extended just like VBA for Excel (currently in alpha).
editor). LLM and BASIC can be mixed used to build custom dialogs so Bot can be extended just like VBA for Excel.
![General Bot Reference Architecture](https://raw.githubusercontent.com/GeneralBots/BotBook/master/images/general-bots-reference-architecture.png)
## 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
@ -76,18 +147,12 @@ SEND FILE img
## Guide
[Read the General Bots BotBook Guide](https://github.com/GeneralBots/BotBook/tree/master/book).
[Read the General Bots BotBook Guide](https://docs.pragmatismo.com.br)
# Videos
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.
[![General Bot Video](https://raw.githubusercontent.com/pragmatismo-io/BotServer/master/docs/images/video-01-thumb.jpg)](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.
[![See how easy is to use 'hear' and 'talk' to build Microsoft BOT Framework v4 logic with plain BASIC](https://raw.githubusercontent.com/pragmatismo-io/BotServer/master/docs/images/video-02-thumb.jpg)](https://www.youtube.com/watch?v=yX1sF9n9628)
7 AI General Bots LLM Templates for Goodness
[https://www.youtube.com/watch?v=KJgvUPXi3Fw](https://www.youtube.com/watch?v=KJgvUPXi3Fw)
# Contributing
@ -96,14 +161,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.cloud Security
team at [security@pragmatismo.cloud](mailto:security@pragmatismo.cloud). You should
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
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.cloud. All rights reserved.
General Bot Copyright (c) pragmatismo.com.br. All rights reserved.
Licensed under the AGPL-3.0.
According to our dual licensing model, this program can be used either
@ -119,7 +184,7 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
"General Bot" is a registered trademark of pragmatismo.cloud.
"General Bot" is a registered trademark of pragmatismo.com.br.
The licensing of the program under the AGPLv3 does not imply a
trademark license. Therefore any rights, title and interest in
our trademarks remain entirely with us.

View file

@ -1,6 +0,0 @@
# Roadmap
| Title | Priority | Release | Status |
|-------------------------------|------------------------------------------------------------------------------------------------------------|---------|--------|
| Isolation of .gbapp per .gbot | Today .gbapp loaded is shared across all bot instances and must be associated to one or more individually. | Medium | 2019Q4 |
| Python based .gbapps | Write conversational login in Python | Low | - |

View file

@ -1,7 +0,0 @@
# General Bots Server Samples
| Sample | Description |
|--------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|
| [IntranetBotQuickStart-gbai](https://github.com/pragmatismo-io/IntranetBotQuickStart.gbai) | Free modules from General Bots Intranet based bot. |
| [AzureADPasswordReset-gbapp](https://github.com/pragmatismo-io/AzureADPasswordReset.gbapp) | Custom General Bot App (gbapp) for resetting an user password in Azure Active Directory, Office 365, Dynamics 365 or any app published through Azure AD. |
| [ProjectOnline.gbkb](https://github.com/pragmatismo-io/ProjectOnline.gbkb) | The .gbkb file demonstring a Knowledge Base for pragmatismo.cloud KBot for Microsoft Project. |

View file

@ -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.cloud
or feedback, please contact security@pragmatismo.com.br
We will only classify information which is necessary for the completion of our duties. We will also limit
@ -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.cloud
security@pragmatismo.com.br

View file

@ -7,7 +7,7 @@
},
"servers": [
{
"url": "https://gb.pragmatismo.cloud/api",
"url": "https://generalbots.online/api",
"description": "General Bots Online"
}
]

View file

@ -1,6 +1,6 @@
#!/usr/bin/env node
process.stdout.write(`General Bots VM: node@${process.version.replace('v', '')}, ${process.platform} ${process.arch} `);
process.stdout.write(`General Bots 5 VM: node@${process.version.replace('v', '')}, ${process.platform} ${process.arch} `);
import fs from 'fs/promises';
import os from 'node:os';

View file

@ -1,10 +0,0 @@
{
"groups": {
"default": {
"packages": [
"package.json",
"packages/default.gbui/package.json"
]
}
}
}

BIN
logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

48942
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -102,7 +102,7 @@
"@semantic-release/git": "10.0.1",
"@sendgrid/mail": "8.1.3",
"@sequelize/core": "7.0.0-alpha.37",
"@types/node": "22.5.2",
"@sequelize/postgres": "^7.0.0-alpha.43",
"@types/validator": "13.12.1",
"adm-zip": "0.5.16",
"ai2html": "^0.121.1",
@ -113,6 +113,7 @@
"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",
@ -169,11 +170,13 @@
"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",
@ -183,6 +186,7 @@
"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",
@ -192,7 +196,7 @@
"pdf-parse": "1.1.1",
"pdf-to-png-converter": "3.3.0",
"pdfjs-dist": "4.6.82",
"pdfkit": "0.15.0",
"pg": "^8.13.1",
"phone": "3.1.50",
"pizzip": "3.1.7",
"pptxtemplater": "1.0.5",
@ -221,6 +225,9 @@
"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",
@ -248,6 +255,9 @@
"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",
@ -261,8 +271,6 @@
"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",

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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,6 +47,7 @@ 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 {
@ -86,7 +87,7 @@ class AdminDialog extends IGBDialog {
const locale = step.context.activity.locale;
const sensitive = step.context.activity['originalText'];
if (sensitive === min.instance.adminPass) {
if (await GBUtil.comparePassword( sensitive, min.instance.adminPass)) {
await min.conversationalService.sendText(min, step, Messages[locale].welcome);
return await step.endDialog(true);
@ -120,7 +121,7 @@ class AdminDialog extends IGBDialog {
const locale = step.context.activity.locale;
const sensitive = step.context.activity['originalText'];
if (sensitive === min.instance.adminPass) {
if (await GBUtil.comparePassword( sensitive, min.instance.adminPass)) {
await min.conversationalService.sendText(min, step, Messages[locale].welcome);
return await min.conversationalService.prompt(min, step, Messages[locale].which_task);
@ -292,6 +293,8 @@ class AdminDialog extends IGBDialog {
await min.conversationalService.sendText(min, step, `Starting publishing for ${botId} packages...`);
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;
@ -304,6 +307,8 @@ class AdminDialog extends IGBDialog {
if (
packageName.toLowerCase() === 'gbdialog' ||
packageName.toLowerCase() === 'gbdrive' ||
packageName.toLowerCase() === 'gbdata' ||
packageName.toLowerCase() === 'gbkb' ||
packageName.toLowerCase() === 'gbot' ||
packageName.toLowerCase() === 'gbtheme'

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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.split(' ')[2];
const folderName = text.substring(text.indexOf(packageName) + packageName.length + 1);
const packageType = path.extname(folderName).substr(1);
const gbaiPath = GBUtil.getGBAIPath(min.instance.botId, packageType, null);
const localFolder = path.join('work', gbaiPath);

View file

@ -1,7 +1,7 @@
export const Messages = {
'en-US': {
authenticate: 'Please, authenticate:',
welcome: 'Welcome to pragmatismo.cloud GeneralBots Administration.',
welcome: 'Welcome to pragmatismo.com.br GeneralBots Administration.',
which_task: 'Which task do you wanna run now?',
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.cloud GeneralBots Administration.',
welcome: 'Welcome to pragmatismo.com.br GeneralBots Administration.',
which_task: 'Which task do you wanna run now?',
working: command => `I'm working on ${command}...`,
finished_working: 'Done.',

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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 = GBAdminService.getRndPassword();
instance.adminPass = await GBUtil.hashPassword(GBAdminService.getRndPassword());
return { instance, credentials, subscriptionId , installationDeployer};
}

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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 = GBAdminService.getRndPassword();
instance.adminPass = await GBUtil.hashPassword(GBAdminService.getRndPassword());
const credentials = await GBAdminService.getADALCredentialsFromUsername(username, password);
// tslint:disable-next-line:no-http-string
@ -986,7 +986,6 @@ 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}` },

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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,7 +30,6 @@
'use strict';
import sgMail from '@sendgrid/mail';
import { ActivityTypes } from 'botbuilder';
import { GBLog, GBMinInstance } from 'botlib';
import * as df from 'date-diff';
@ -43,7 +42,7 @@ import mime from 'mime-types';
import tesseract from 'node-tesseract-ocr';
import path from 'path';
import { CollectionUtil } from 'pragmatismo-io-framework';
import puppeteer from 'puppeteer';
import puppeteer, { executablePath } from 'puppeteer';
import qrcode from 'qrcode';
import urlJoin from 'url-join';
import pkg from 'whatsapp-web.js';
@ -61,6 +60,8 @@ 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;
@ -93,7 +94,11 @@ export class DialogKeywords {
// Launch Puppeteer to render the chart
const browser = await puppeteer.launch();
const browser = await puppeteer.launch({
headless: process.env.CHROME_HEADLESS === 'true',
executablePath: process.env.CHROME_PATH ? process.env.CHROME_PATH : executablePath(),
}
);
const page = await browser.newPage();
// Load Billboard.js styles and scripts
@ -573,7 +578,6 @@ 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.
@ -582,24 +586,36 @@ export class DialogKeywords {
body = result.value;
}
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
};
sgMail.send(msg, false, (err, res) => {
if (err) {
reject(err);
} else {
resolve(res);
}
});
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'
// }
};
await transporter.sendMail(mailOptions);
GBLogEx.info(min, `E-mail ${to} (${subject}) sent via NodeMailer.`);
} else {
let { client } = await GBDeployer.internalGetDriveClient(min);
@ -709,8 +725,9 @@ export class DialogKeywords {
proc.roles = role;
// Checks access.
const filters = ['People.xlsx', `${role}=x`, `id=${user.userSystemId}`];
const file = process.env.GB_MODE === 'legacy' ? 'People.xlsx' : 'people.csv';
const filters = [file, `${role}=x`, `id=${user.userSystemId}`];
const people = await sys.find({ pid, handle: null, args: filters });
if (!people) {
@ -1087,7 +1104,7 @@ export class DialogKeywords {
// In case of unmatch, asks the person to try again.
if (result === null) {
await this.talk({ pid, text: `Escolha por favor um dos itens sugeridos.` });
await this.talk({ pid, text: `Digite por favor um dos itens sugeridos ou uma parte do texto.` });
return await this.hear({ pid, kind, args });
}
} else if (kind === 'file') {
@ -1392,7 +1409,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;
@ -1495,7 +1512,7 @@ export class DialogKeywords {
else {
if (GBConfigService.get('STORAGE_NAME')) {
if (GBConfigService.get('GB_MODE') === 'legacy') {
const ext = path.extname(filename);
const gbaiName = GBUtil.getGBAIPath(min.botId);
@ -1520,17 +1537,52 @@ export class DialogKeywords {
'cache',
`${fileOnly.replace(/\s/gi, '')}-${GBAdminService.getNumberIdentifier()}.${ext}`
);
await fs.writeFile(localName, buf, { encoding: null });
await fs.writeFile(localName, new Uint8Array(buf), { encoding: null });
url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
} 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('.pdf')) {
if (localName.endsWith('.image.pdf')) {
GBLogEx.info(min, `Converting PDF to images...`);
const pngs = await GBUtil.pdfPageAsImage(min, localName, undefined);
await CollectionUtil.asyncForEach(pngs, async png => {
@ -1548,8 +1600,11 @@ export class DialogKeywords {
contentUrl: url
});
if (!isNaN(mobile)) {
await min.whatsAppDirectLine.sendFileToDevice(mobile, url, filename, caption, undefined, true);
await min.whatsAppDirectLine.sendFileToDevice(mobile, url, filename, caption, undefined, true, true);
} else {
await min.conversationalService['sendOnConversation'](min, user, reply);
}
@ -1568,8 +1623,10 @@ 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);
@ -1581,8 +1638,8 @@ export class DialogKeywords {
contentUrl: url
});
if (channel === 'omnichannel' || !user) {
await min.conversationalService.sendFile(min, null, mobile, url, caption);
if (!isNaN(mobile)) {
await min.whatsAppDirectLine.sendFileToDevice(mobile, url, filename, caption, undefined, false);
} else {
await min.conversationalService['sendOnConversation'](min, user, reply);
}

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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,6 +39,7 @@ 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';
@ -149,7 +150,7 @@ export class GBVMService extends GBService {
let mainName = GBVMService.getMethodNameFromVBSFilename(filename);
min.scriptMap[filename] = mainName;
if (writeVBS && GBConfigService.get('STORAGE_NAME')) {
if (writeVBS && GBConfigService.get('GB_MODE') === 'legacy') {
let text = await this.getTextFromWord(folder, wordFile);
// Write VBS file without pragma keywords.
@ -204,7 +205,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",
@ -244,42 +245,133 @@ 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'));
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
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
}
},
pool: {
max: 5,
min: 0,
idle: 10000,
evict: 10000,
acquire: acquire
}
};
};
}
if (!min[connectionName]) {
GBLogEx.info(min, `Loading data connection ${connectionName}...`);
GBLogEx.info(min, `Loading data connection ${connectionName} (${dialect})...`);
min[connectionName] = new Sequelize(storageName, username, password, sequelizeOptions);
min[connectionName]['gbconnection'] = con;
}
@ -415,10 +507,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;
}
@ -512,13 +604,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) {
@ -717,7 +809,13 @@ export class GBVMService extends GBService {
if (!table && !talk && !systemPrompt) {
for (let j = 0; j < keywords.length; j++) {
line = line.replace(keywords[j][0], keywords[j][1]); // TODO: Investigate delay here.
const oldLine = line;
line = line.replace(keywords[j][0], keywords[j][1]);
if(line != oldLine){
break;
}
}
}
@ -877,7 +975,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++) {
@ -936,12 +1034,12 @@ export class GBVMService extends GBService {
let result;
try {
if (!GBConfigService.get('GBVM')) {
if (GBConfigService.get('GBVM') !== false) {
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,

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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,16 +124,17 @@ 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,
size: '1024x1024'
});
// Make a request to the image generation endpoint
const response = await client.images.generate({
prompt: prompt,
n: 1, // Don't include for DALL-E 3 (always generates 1 image)
style: 'vivid', // optional ('natural' or 'vivid')
size: '1024x1024',
quality: 'standard', // optional
});
const gbaiName = GBUtil.getGBAIPath(min.botId);
const localName = path.join('work', gbaiName, 'cache', `DALL-E${GBAdminService.getRndReadableIdentifier()}.png`);

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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,6 +522,14 @@ export class KeywordsExpressions {
}
];
keywords[i++] = [
/^\s*(LOG)(\s*)(.*)/gim,
($0, $1, $2, $3) => {
const params = this.getParams($3, ['obj']);
return `await sys.log ({pid: pid, ${params}})`;
}
];
keywords[i++] = [
/^\s*(.*)\=\s*(DIR)(\s*)(.*)/gim,
($0, $1, $2, $3, $4) => {
@ -572,6 +580,14 @@ export class KeywordsExpressions {
}
];
keywords[i++] = [
/^\s*hear (\w+\$*) as\s*number/gim,
($0, $1) => {
return `${$1} = await dk.hear({pid: pid, kind:"integer"})`;
}
];
keywords[i++] = [
/^\s*hear (\w+\$*) as\s*integer/gim,
($0, $1) => {
@ -906,6 +922,15 @@ export class KeywordsExpressions {
}
];
keywords[i++] = [
/^\s*(POST TO INSTAGRAM)(\s*)(.*)/gim,
($0, $1, $2, $3) => {
const params = this.getParams($3, ['username', 'password', 'imagePath', 'caption']);
return `await sys.postToInstagram ({pid: pid, ${params}})`;
}
];
keywords[i++] = [
/^\s*((?:[a-z]+.?)(?:(?:\w+).)(?:\w+)*)\s*=\s*(datediff)(\s*)(.*)/gim,
($0, $1, $2, $3, $4) => {
@ -1287,7 +1312,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}})`;
}
];
@ -1299,13 +1324,13 @@ export class KeywordsExpressions {
];
keywords[i++] = [
/^\s*(save)(\s*)(.*\.xlsx)(.*)/gim,
($0, $1, $2, $3, $4) => {
/^\s*(save)(\s*)(.*\.(xlsx|csv))(.*)/gim,
($0, $1, $2, $3, $4, $5) => {
$3 = $3.replace(/\'/g, '');
$3 = $3.replace(/\"/g, '');
$3 = $3.replace(/\`/g, '');
$4 = $4.substr(2);
return `await sys.save({pid: pid, file: "${$3}", args: [${$4}]})`;
$5 = $5.substr(2);
return `await sys.save({pid: pid, file: "${$3}", args: [${$5}]})`;
}
];

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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,49 +29,53 @@
\*****************************************************************************/
'use strict';
import { setFlagsFromString } from 'v8';
import { runInNewContext } from 'vm';
import { IgApiClient } from 'instagram-private-api';
import { readFile } from 'fs';
import ai2html from 'ai2html';
import path, { resolve } from 'path';
import { GBLog, GBMinInstance } from 'botlib';
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
import { CollectionUtil } from 'pragmatismo-io-framework';
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js';
import { GBDeployer } from '../../core.gbapp/services/GBDeployer.js';
import { DialogKeywords } from './DialogKeywords.js';
import { GBServer } from '../../../src/app.js';
import { GBVMService } from './GBVMService.js';
import fs from 'fs/promises';
import { GBSSR } from '../../core.gbapp/services/GBSSR.js';
import urlJoin from 'url-join';
import Excel from 'exceljs';
import { BufferWindowMemory } from 'langchain/memory';
import csvdb from 'csv-database';
import { Sequelize, QueryTypes, DataTypes } from '@sequelize/core';
import packagePath from 'path';
import ComputerVisionClient from '@azure/cognitiveservices-computervision';
import ApiKeyCredentials from '@azure/ms-rest-js';
import alasql from 'alasql';
import PizZip from 'pizzip';
import Docxtemplater from 'docxtemplater';
import pptxTemplaterModule from 'pptxtemplater';
import _ from 'lodash';
import { pdfToPng, PngPageOutput } from 'pdf-to-png-converter';
import ImageModule from 'open-docxtemplater-image-module';
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService.js';
import { WebAutomationServices } from './WebAutomationServices.js';
import { KeywordsExpressions } from './KeywordsExpressions.js';
import { ChatServices } from '../../llm.gblib/services/ChatServices.js';
import mime from 'mime-types';
import { SecService } from '../../security.gbapp/services/SecService.js';
import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
import retry from 'async-retry';
import { BlobServiceClient, BlockBlobClient, StorageSharedKeyCredential } from '@azure/storage-blob';
import { 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 { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService.js';
import { GBDeployer } from '../../core.gbapp/services/GBDeployer.js';
import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
import { GBSSR } from '../../core.gbapp/services/GBSSR.js';
import { ChatServices } from '../../llm.gblib/services/ChatServices.js';
import { SecService } from '../../security.gbapp/services/SecService.js';
import { DialogKeywords } from './DialogKeywords.js';
import { GBVMService } from './GBVMService.js';
import { KeywordsExpressions } from './KeywordsExpressions.js';
import { WebAutomationServices } from './WebAutomationServices.js';
import { exec } from 'child_process';
import util from 'util';
// Promisify the exec function for async/await usage
const execPromise = util.promisify(exec);
import { md5 } from 'js-md5';
import { Client } from 'minio';
import { GBUtil } from '../../../src/util.js';
/**
@ -173,22 +177,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;
}
}
@ -362,8 +366,42 @@ export class SystemKeywords {
);
}
public async asPDF({ pid, data }) {
let file = await this.renderTable(pid, data, true, false);
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);
}
return file;
}
@ -391,7 +429,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)));
stream.on('end', () => resolve(Buffer.concat(chunks.map(chunk => new Uint8Array(chunk)))));
});
};
@ -415,7 +453,7 @@ export class SystemKeywords {
const buffer = pngPages[0].content;
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
await fs.writeFile(localName, buffer, { encoding: null });
await fs.writeFile(localName, new Uint8Array(buffer), { encoding: null });
return { localName: localName, url: url, data: buffer };
}
@ -708,7 +746,7 @@ export class SystemKeywords {
// Writes it to disk and calculate hash.
const data = await response.arrayBuffer();
await fs.writeFile(localName, Buffer.from(data), { encoding: null });
await fs.writeFile(localName, new Uint8Array(Buffer.from(data)), { encoding: null });
const hash = new Uint8Array(md5.array(data));
// Performs uploading passing local hash.
@ -785,7 +823,7 @@ export class SystemKeywords {
const minRef = min;
await retry(
async (bail) => {
async bail => {
const t = this.getTableFromName(tableName, minRef);
try {
await t.bulkCreate(rowsDest);
@ -837,7 +875,13 @@ export class SystemKeywords {
/**
* Saves the content of several variables to a new row in a tabular file.
*
* @example SAVE "customers.xlsx", name, email, phone, address, city, state, country
* @example SAVE "customers.csv", name, email, phone, address, city, state, country
*
*/
/**
* Saves the content of several variables to a new row in a tabular file.
*
* @example SAVE "customers.csv", id, name, email, phone
*
*/
public async save({ pid, file, args }): Promise<any> {
@ -847,6 +891,89 @@ 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');
@ -859,13 +986,11 @@ 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 {
@ -876,51 +1001,44 @@ export class SystemKeywords {
let address;
let body = { values: [[]] };
// Processes FILTER option to ensure parallel SET calls.
// TODO: Check if first column is ID
// const firstCell = await client
// .api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A1:A1')`)
// .get();
const filter = await DialogKeywords.getOption({ pid, name: 'filter' });
if (filter) {
// Creates id row.
// const hasIdColumn = firstCell.text.toLowerCase() === 'id';
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;
// // 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();
// 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) {
// 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) {
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`;
}
// 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}`;
for (let j = 0; j < args.length; j++) {
body.values[0][j] = args[j];
}
// If filter is defined, skips id column.
body.values[0][filter ? index + 1 : index] = value;
}
await retry(
@ -946,6 +1064,30 @@ export class SystemKeywords {
);
}
// Helper methods for Minio file locking (unchanged)
private async lockFile(minioClient: Client, bucketName: string, filePath: string): Promise<void> {
const lockFile = `${filePath}.lock`;
try {
await minioClient.statObject(bucketName, lockFile);
throw new Error(`File ${filePath} is currently locked for editing`);
} catch (error) {
if (error.code === 'NotFound') {
// Create lock file
await minioClient.putObject(bucketName, lockFile, 'locked');
return;
}
throw error;
}
}
private async unlockFile(minioClient: Client, bucketName: string, filePath: string): Promise<void> {
const lockFile = `${filePath}.lock`;
try {
await minioClient.removeObject(bucketName, lockFile);
} catch (error) {
GBLog.error(`Error removing lock file: ${error.message}`);
}
}
/**
* Retrives the content of a cell in a tabular file.
*
@ -1128,7 +1270,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, Buffer.from(await response.arrayBuffer()), { encoding: null });
await fs.writeFile(localName, new Uint8Array(Buffer.from(await response.arrayBuffer())), { encoding: null });
var workbook = new Excel.Workbook();
let worksheet = await workbook.csv.readFile(localName);
@ -1175,11 +1317,47 @@ export class SystemKeywords {
} else if (file.indexOf('.csv') !== -1) {
let res;
let packagePath = GBUtil.getGBAIPath(min.botId, `gbdata`);
const csvFile = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath, file);
let csvFile = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath, file);
if (GBConfigService.get('GB_MODE') === 'gbcluster') {
const fileUrl = urlJoin('/', `${min.botId}.gbdata`, file);
GBLogEx.info(min, `Direct data from .csv: ${fileUrl}.`);
const fileOnly = fileUrl.substring(fileUrl.lastIndexOf('/') + 1);
const minioClient = new Client({
endPoint: process.env.DRIVE_SERVER || 'localhost',
port: parseInt(process.env.DRIVE_PORT || '9000', 10),
useSSL: process.env.DRIVE_USE_SSL === 'true',
accessKey: process.env.DRIVE_ACCESSKEY,
secretKey: process.env.DRIVE_SECRET
});
const gbaiName = GBUtil.getGBAIPath(min.botId);
const bucketName = (process.env.DRIVE_ORG_PREFIX + min.botId + '.gbai').toLowerCase();
const localName = path.join(
process.env.PWD,
'work',
gbaiName,
'cache',
`${fileOnly.replace(/\s/gi, '')}-${GBAdminService.getNumberIdentifier()}.csv`
);
await minioClient.fGetObject(bucketName, fileUrl, localName);
csvFile = localName;
GBLogEx.info(min, `Downloaded .csv: ${csvFile}.`);
}
GBLogEx.info(min, `Reading .csv: ${csvFile}.`);
const data = await fs.readFile(csvFile, 'utf8');
const 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 = {};
@ -1189,6 +1367,8 @@ 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);
@ -1698,13 +1878,9 @@ 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.
@ -1985,35 +2161,98 @@ export class SystemKeywords {
*
* Fills a .docx or .pptx with template data.
*
* doc = FILL "templates/template.docx", data
* doc = FILL "templates/template.docx" WITH data
*
*/
public async fill({ pid, templateName, data }) {
const { min, user } = await DialogKeywords.getProcessInfo(pid);
private async getTemplateBuffer(min: any, gbaiName: string, templateName: string): Promise<Buffer> {
const botId = min.instance.botId;
const gbaiName = GBUtil.getGBAIPath(botId, 'gbdata');
let localName;
// Downloads template from .gbdrive.
if (GBConfigService.get('GB_MODE') === 'legacy') {
// Legacy mode - using Microsoft Graph API
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);
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 });
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);
}
}
// Replace image path on all elements of data.
private async getImageBuffer(min: any, gbaiName: string, imagePath: string): Promise<Buffer> {
const botId = min.instance.botId;
if (GBConfigService.get('GB_MODE') === 'legacy') {
const { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
let packagePath = urlJoin(gbaiName, `${botId}.gbdrive`);
if (imagePath.indexOf('/') !== -1) {
packagePath = '/' + urlJoin(packagePath, path.dirname(imagePath));
imagePath = path.basename(imagePath);
}
const ref = await this.internalGetDocument(client, baseUrl, packagePath, imagePath);
const url = ref['@microsoft.graph.downloadUrl'];
const response = await fetch(url);
return Buffer.from(await response.arrayBuffer());
} else if (GBConfigService.get('GB_MODE') === 'gbcluster') {
const minioClient = this.createMinioClient();
const bucketName = (process.env.DRIVE_ORG_PREFIX + botId + '.gbai').toLowerCase();
const filePath = urlJoin(gbaiName, `${botId}.gbdrive`, imagePath);
return new Promise(async (resolve, reject) => {
const chunks: Buffer[] = [];
try {
const stream = await minioClient.getObject(bucketName, filePath);
stream.on('data', chunk => chunks.push(chunk));
stream.on('end', () => resolve(Buffer.concat(chunks)));
stream.on('error', reject);
} catch (err) {
reject(err);
}
});
} else {
const gbdriveName = GBUtil.getGBAIPath(botId, 'gbdrive');
const fullPath = path.join(GBConfigService.get('STORAGE_LIBRARY'), gbdriveName, imagePath);
return fs.readFile(fullPath);
}
}
private createMinioClient(): Client {
return new Client({
endPoint: process.env.DRIVE_SERVER || 'localhost',
port: parseInt(process.env.DRIVE_PORT || '9000', 10),
useSSL: process.env.DRIVE_USE_SSL === 'true',
accessKey: process.env.DRIVE_ACCESSKEY,
secretKey: process.env.DRIVE_SECRET
});
}
private async processImagesInData(min: any, gbaiName: string, data: any): Promise<any[]> {
const images = [];
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 => {
for (var i in o) {
const traverseDataToInjectImageUrl = async (o: any) => {
for (const i in o) {
let value = o[i];
if (value && value.gbarray) {
@ -2022,112 +2261,84 @@ export class SystemKeywords {
}
for (const kind of ['png', 'jpg', 'jpeg']) {
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'];
if (value?.endsWith?.(`.${kind}`)) {
const imageBuffer = await this.getImageBuffer(min, gbaiName, value);
const imageName = path.join(
'work',
gbaiName,
'cache',
`tmp${GBAdminService.getRndReadableIdentifier()}-${value}.png`
`tmp${GBAdminService.getRndReadableIdentifier()}-${path.basename(value)}.png`
);
const response = await fetch(url);
const buf = Buffer.from(await response.arrayBuffer());
await fs.writeFile(imageName, buf, { encoding: null });
await fs.writeFile(imageName, new Uint8Array(imageBuffer), { encoding: null });
const getNormalSize = ({ width, height, orientation }) => {
const getNormalSize = ({ width, height, orientation }: any) => {
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'
});
url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(imageName));
images[index++] = { url: url, size: size, buf: buf };
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(imageName));
images[index++] = { url, size, buf: imageBuffer };
}
}
if (o[i] !== null && typeof o[i] == 'object') {
if (o[i] !== null && typeof o[i] === 'object') {
await traverseDataToInjectImageUrl(o[i]);
}
}
};
await traverseDataToInjectImageUrl(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;
var opts = {
const opts = {
fileType: 'docx',
centered: false,
getImage: (tagValue, tagName) => {
return images[indexImage].buf;
},
getSize: (img, tagValue, tagName) => {
return images[indexImage++].size;
}
getImage: () => images[indexImage].buf,
getSize: () => images[indexImage++].size
};
// Loads the file as binary content.
let zip = new PizZip(buf);
let doc = new Docxtemplater();
// Process the template
const zip = new PizZip(templateBuffer);
const 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);
await traverseDataToInjectImageUrl(data);
doc.setData(data).render();
const outputBuffer = doc.getZip().generate({ type: 'nodebuffer', compression: 'DEFLATE' });
await fs.writeFile(localName, new Uint8Array(outputBuffer), { encoding: null });
buf = doc.getZip().generate({ type: 'nodebuffer', compression: 'DEFLATE' });
await fs.writeFile(localName, buf, { encoding: null });
return { localName: localName, url: url, data: buf };
return { localName, url, data: outputBuffer };
}
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);
// });
}
public screenCapture(pid) {}
private numberToLetters(num) {
let letters = '';
@ -2478,12 +2689,11 @@ 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;
}
@ -2495,9 +2705,9 @@ export class SystemKeywords {
*/
public async rewrite({ pid, text }) {
const { min, user } = await DialogKeywords.getProcessInfo(pid);
const prompt = `Rewrite this sentence in a better way: ${text}`;
const prompt = `${text}`;
const answer = await ChatServices.invokeLLM(min, prompt);
GBLogEx.info(min, `REWRITE ${text} TO ${answer}`);
GBLogEx.info(min, `REWRITE ${text} TO ${answer.text}`);
return answer;
}
@ -2558,7 +2768,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, buf, { encoding: null });
await fs.writeFile(localName, new Uint8Array(buf), { encoding: null });
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
GBLogEx.info(min, `GBPay: ${data.MerchantOrderId} OK: ${url}.`);
@ -2647,7 +2857,6 @@ export class SystemKeywords {
}
public async getExtensionInfo(ext: any): Promise<any> {
// TODO: Load exts.
let array = []; // exts.filter((v, i, a) => a[i]['extension'] === ext);
@ -2726,7 +2935,7 @@ export class SystemKeywords {
try {
let data;
if (GBConfigService.get('STORAGE_NAME')) {
if (GBConfigService.get('GB_MODE') === 'legacy') {
let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
const gbaiName = GBUtil.getGBAIPath(min.botId);
let packagePath = '/' + urlJoin(gbaiName, `${min.botId}.gbdrive`);
@ -2791,7 +3000,7 @@ export class SystemKeywords {
// Criação de um arquivo temporário para enviar
const tempFilePath = path.resolve('temp_image.jpg');
await fs.writeFile(tempFilePath, imageBuffer);
await fs.writeFile(tempFilePath, new Uint8Array(imageBuffer));
// Publicação da imagem
const page = new Page(pageId);
@ -2908,17 +3117,16 @@ 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');
@ -2930,10 +3138,8 @@ export class SystemKeywords {
await fs.writeFile(cacheFilePath, htmlContent);
return cacheFilePath;
}
public async refreshDataSourceCache({ pid, connectionName }) {
const { min, user, params, step } = await DialogKeywords.getProcessInfo(pid);
@ -2959,25 +3165,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
};

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -6,7 +6,7 @@
"title": "Default General Bot",
"description": "Default General Bot",
"whoAmIVideo": "TODO.mp4",
"author": "pragmatismo.cloud",
"author": "pragmatismo.com.br",
"license": "AGPL",
"engineName": "guaribas-1.0.0"
}

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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,8 +65,7 @@ export class WelcomeDialog extends IGBDialog {
async step => {
if (
GBServer.globals.entryPointDialog !== null &&
min.instance.botId === GBConfigService.get('BOT_ID') &&
step.context.activity.channelId === 'webchat'
min.instance.botId === GBConfigService.get('BOT_ID')
) {
return step.replaceDialog(GBServer.globals.entryPointDialog);
}

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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 = false;
value = true;
break;
case 'STORAGE_NAME':
value = null;

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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,6 +43,7 @@ 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';
@ -52,7 +53,7 @@ import { createWriteStream, createReadStream } from 'fs';
import fs from 'fs/promises';
import twilio from 'twilio';
import Nexmo from 'nexmo';
import { join } from 'path';
import path, { join } from 'path';
import shell from 'any-shell-escape';
import { exec } from 'child_process';
import prism from 'prism-media';
@ -473,7 +474,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);
@ -646,6 +647,15 @@ 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';
@ -1201,8 +1211,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);
@ -1252,11 +1262,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);
}
@ -1280,24 +1290,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('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);
});
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);
});
});
} 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']) {

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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,6 +67,7 @@ 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
@ -112,7 +113,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
@ -121,62 +122,86 @@ 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 (this.dialect === 'mssql') {
if (!['mssql', 'postgres', 'sqlite'].includes(this.dialect)) {
throw new Error(`Unknown or unsupported dialect: ${this.dialect}.`);
}
if (this.dialect === 'mssql' || this.dialect === 'postgres') {
host = GBConfigService.get('STORAGE_SERVER');
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 acquire = parseInt(GBConfigService.get('STORAGE_ACQUIRE_TIMEOUT'));
const acquireStr = GBConfigService.get('STORAGE_ACQUIRE_TIMEOUT');
const acquire = acquireStr ? parseInt(acquireStr, 10) : 10000; // Valor padrão de 10 segundos
const sequelizeOptions: SequelizeOptions = {
define: {
freezeTableName: true,
timestamps: false
timestamps: false,
},
host: host,
port: port,
logging: logging as boolean,
dialect: this.dialect as Dialect,
storage: storage,
quoteIdentifiers: false, // set case-insensitive
dialectOptions: {
quoteIdentifiers: this.dialect === 'postgres',
dialectOptions: this.dialect === 'mssql' ? {
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);
}
@ -252,12 +277,15 @@ export class GBCoreService implements IGBCoreService {
const options = {
where: {
[Op.or]: and
}
},
order: [['instanceId', 'ASC']]
};
return await GuaribasInstance.findAll(options);
return await GuaribasInstance.findAll(options as any);
} else {
const options = { where: { state: 'active' } };
return await GuaribasInstance.findAll(options);
const options = { where: { state: 'active' } ,
order: [['instanceId', 'ASC']]};
return await GuaribasInstance.findAll(options as any);
}
}
@ -295,7 +323,6 @@ 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}
@ -313,7 +340,7 @@ STORAGE_SYNC_ALTER=true
ENDPOINT_UPDATE=true
`;
await fs.writeFile('.env', env);
await fs.writeFile('.env', env);
}
/**
@ -523,7 +550,7 @@ await fs.writeFile('.env', env);
* Verifies that an complex global password has been specified
* before starting the server.
*/
public ensureAdminIsSecured() {}
public ensureAdminIsSecured() { }
public async createBootInstance(
core: GBCoreService,
@ -675,30 +702,30 @@ await fs.writeFile('.env', env);
}
public async setConfig(min, name: string, value: any): Promise<any> {
if (GBConfigService.get('STORAGE_NAME')) {
if (GBConfigService.get('GB_MODE') === 'legacy') {
// Handles calls for BASIC persistence on sheet files.
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];
@ -707,27 +734,27 @@ await fs.writeFile('.env', env);
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 {
let packagePath = GBUtil.getGBAIPath(min.botId, `gbot`);
}
else if (GBConfigService.get('GB_MODE') === 'local') {
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 });
@ -736,7 +763,7 @@ await fs.writeFile('.env', env);
}
}
}
/**
* Get a dynamic param from instance. Dynamic params are defined in Config.xlsx
* and loaded into the work folder from comida command.
@ -836,75 +863,72 @@ await fs.writeFile('.env', env);
}
public async ensureFolders(instances, deployer: GBDeployer) {
const storageMode = process.env.GB_MODE;
let libraryPath = GBConfigService.get('STORAGE_LIBRARY');
if (!(await GBUtil.exists(libraryPath))) {
mkdirp.sync(libraryPath);
}
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);
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/, '');
const bucketStream = await minioClient.listBuckets();
await this.syncBotStorage(instances, botId, deployer, libraryPath);
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);
}
});
}
}
private async syncBotStorage(instances: any, botId: any, deployer: GBDeployer, libraryPath: string) {
let instance = instances.find(p => p.botId.toLowerCase().trim() === botId.toLowerCase().trim());
if (!instance) {
GBLog.info(`Importing package ${botId}...`);
if (process.env.GB_MODE === 'local') {
if (!instance) {
GBLog.info(`Importing package ${botId}.gbai...`);
// Creates a bot.
// Creates a bot.
let mobile = null,
email = null;
let mobile = null,
email = null;
instance = await deployer.deployBlankBot(botId, mobile, email);
const gbaiPath = path.join(libraryPath, `${botId}.gbai`);
instance = await deployer.deployBlankBot(botId, mobile, email);
instances.push(instance);
const gbaiPath = path.join(libraryPath, `${botId}.gbai`);
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
});
if (!(await GBUtil.exists(gbaiPath))) {
fs.mkdir(gbaiPath, { recursive: true });
}
}
}
return instance;
}
public static async createWebDavServer(minInstances: GBMinInstance[]) {

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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,6 +39,8 @@ 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';
@ -47,7 +49,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 { GuaribasPackage } from '../models/GBModel.js';
import { GuaribasInstance, 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';
@ -220,7 +222,7 @@ export class GBDeployer implements IGBDeployer {
const instance = await this.importer.createBotInstance(botId);
const bootInstance = GBServer.globals.bootInstance;
if (GBConfigService.get('STORAGE_NAME')) {
if (GBConfigService.get('GB_MODE') === 'legacy') {
// Gets the access token to perform service operations.
const accessToken = await (GBServer.globals.minBoot.adminService as any)['acquireElevatedToken'](
@ -232,13 +234,14 @@ export class GBDeployer implements IGBDeployer {
const service = await AzureDeployerService.createInstance(this);
const 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 = GBAdminService.getRndPassword();
instance.adminPass = await GBUtil.hashPassword(GBAdminService.getRndPassword());
instance.title = botId;
instance.activationCode = instance.botId.substring(0, 15);
instance.state = 'active';
@ -249,13 +252,14 @@ export class GBDeployer implements IGBDeployer {
// Saves bot information to the store.
await this.core.saveInstance(instance);
if (GBConfigService.get('STORAGE_NAME')) {
if (GBConfigService.get('GB_MODE') === 'legacy') {
await this.deployBotOnAzure(instance, GBServer.globals.publicAddress);
}
// Makes available bot to the channels and .gbui interfaces.
await GBServer.globals.minService.mountBot(instance);
const min = await GBServer.globals.minService.mountBot(instance);
GBServer.globals.minInstances.push(min);
// Creates remaining objects on the cloud and updates instance information.
@ -266,9 +270,22 @@ 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);
return await service.botExists(botId);
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);
}
}
/**
@ -354,9 +371,20 @@ export class GBDeployer implements IGBDeployer {
vectorStore = await HNSWLib.load(min['vectorStorePath'], embedding);
} catch (e) {
GBLogEx.info(min, `Creating new store...`);
vectorStore = new HNSWLib(embedding, {
space: 'cosine'
});
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']);
}
return vectorStore;
}
@ -466,13 +494,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;
@ -487,93 +515,135 @@ export class GBDeployer implements IGBDeployer {
/**
*/
public async downloadFolder(
min: GBMinInstance,
localPath: string,
remotePath: string,
baseUrl: string = null,
client = null
client = null, onlyTextFiles = false
): Promise<any> {
GBLogEx.info(min, `downloadFolder: localPath=${localPath}, remotePath=${remotePath}, baseUrl=${baseUrl}`);
const storageMode = process.env.GB_MODE;
if (!baseUrl) {
let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
remotePath = remotePath.replace(/\\/gi, '/');
const parts = remotePath.split('/');
// Creates each subfolder.
let pathBase = localPath;
if (!(await GBUtil.exists(pathBase))) {
fs.mkdir(pathBase);
}
await CollectionUtil.asyncForEach(parts, async item => {
pathBase = path.join(pathBase, item);
if (!(await GBUtil.exists(pathBase))) {
fs.mkdir(pathBase);
}
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,
});
// Retrieves all files in remote folder.
const bucketName = (process.env.DRIVE_ORG_PREFIX + min.botId + '.gbai').toLowerCase();
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;
if (!(await GBUtil.exists(localPath))) {
await fs.mkdir(localPath, { recursive: true });
}
// Download files or navigate to directory to recurse.
const objectsStream = minioClient.listObjects(bucketName, remotePath, true);
for await (const obj of objectsStream) {
const itemPath = path.join(localPath, obj.name);
await CollectionUtil.asyncForEach(documents, async item => {
const itemPath = path.join(localPath, remotePath, item.name);
if (item.folder) {
if (obj.name.endsWith('/')) {
if (!(await GBUtil.exists(itemPath))) {
fs.mkdir(itemPath);
await fs.mkdir(itemPath, { recursive: true });
}
const nextFolder = urlJoin(remotePath, item.name);
await this.downloadFolder(min, localPath, nextFolder);
} else {
let download = true;
if (await GBUtil.exists(itemPath)) {
const dt = await fs.stat(itemPath);
if (new Date(dt.mtime) >= new Date(item.lastModifiedDateTime)) {
const stats = await fs.stat(itemPath);
if (stats.mtime >= new Date(obj.lastModified)) {
download = false;
}
}
if (download) {
GBLogEx.info(min, `Downloading: ${itemPath}...`);
const url = item['@microsoft.graph.downloadUrl'];
// 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;
}
}
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 {
GBLogEx.info(min, `Local is up to date: ${path.basename(itemPath)}...`);
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);
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);
} 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));
}
}
});
}
}
}
/**
* UndDeploys a bot to the storage.
* Undeploys a bot to the storage.
*/
public async undeployBot(botId: string, packageName: string): Promise<void> {
// Deletes Bot registration on cloud.
@ -621,11 +691,21 @@ export class GBDeployer implements IGBDeployer {
await this.cleanupPackage(min.instance, packageName);
}
if (!GBConfigService.get('STORAGE_NAME')) {
if (GBConfigService.get('GB_MODE') === 'local') {
const filePath = path.join(GBConfigService.get('STORAGE_LIBRARY'), gbai, packageName);
await GBUtil.copyIfNewerRecursive(filePath, packageWorkFolder);
if (packageType === '.gbdrive' || packageType === '.gbdata') {
await GBUtil.copyIfNewerRecursive(filePath, packageWorkFolder, true);
} else {
await GBUtil.copyIfNewerRecursive(filePath, packageWorkFolder, false);
}
} else {
await this.downloadFolder(min, path.join('work', `${gbai}`), packageName);
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);
}
}
}
@ -661,6 +741,10 @@ 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.
@ -678,7 +762,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) {

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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 = GBConfigService.get('ADMIN_PASS');
instance.adminPass = await GBUtil.hashPassword( GBConfigService.get('ADMIN_PASS'));
instance.botId = GBConfigService.get('BOT_ID');
instance.cloudSubscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
instance.cloudLocation = GBConfigService.get('CLOUD_LOCATION');

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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,6 +37,7 @@ 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';
@ -105,6 +106,7 @@ 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.
@ -160,16 +162,15 @@ 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: 'http://localhost:8081',
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization', 'x-requested-with'
, 'x-ms-bot-agent'
]
}));
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.get('/instances/:botId', this.handleGetInstanceForClient.bind(this));
}
@ -211,14 +212,11 @@ export class GBMinService {
const user = await sec.ensureUser(min, 'testuser', 'testuser', '', 'test', 'testuser', null);
const 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;
@ -237,7 +235,7 @@ export class GBMinService {
name: 'test',
channelIdEx: 'web',
pid: pid
},
}
}
});
@ -284,7 +282,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,
@ -424,7 +422,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.
@ -459,26 +457,78 @@ 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.verbose(min, `WhatsApp: ${status.recipient_id} ${status.status}`);
GBLogEx.info(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);
}
@ -492,8 +542,13 @@ export class GBMinService {
// Not meta, multiples bots on root bot.
if (!req.body.object) {
const to = req.body.To.replace(/whatsapp\:\+/gi, '');
whatsAppDirectLine = WhatsappDirectLine.botsByNumber[to];
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;
}
}
if (whatsAppDirectLine) {
@ -502,6 +557,50 @@ 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;
@ -529,26 +628,14 @@ 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.
GBLog.error(error);
res.status(500).send(error.toString());
GBLogEx.error(min, error);
res.status(500).send('Service with erros. Please, check service log.');
}
});
}
@ -682,8 +769,9 @@ 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);
});
@ -721,7 +809,7 @@ export class GBMinService {
let logo = this.core.getParam(instance, 'Logo', null);
logo = logo ? urlJoin(instance.botId, 'cache', logo) : 'images/logo-gb.png';
logo = logo ? urlJoin(instance.botId, 'cache', logo) : 'https://pragmatismo.com.br/icons/general-bots-text.svg';
let config = {
instanceId: instance.instanceId,
@ -740,8 +828,12 @@ export class GBMinService {
color2: this.core.getParam(instance, 'Color2', null)
};
if (!GBConfigService.get('STORAGE_NAME')) {
config['domain'] = `http://localhost:${GBConfigService.get('PORT')}/directline/${botId}`;
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);
} else {
const webchatTokenContainer = await this.getWebchatToken(instance);
config['conversationId'] = webchatTokenContainer.conversationId;
@ -812,9 +904,11 @@ export class GBMinService {
? instance.marketplacePassword
: GBConfigService.get('MARKETPLACE_SECRET')
};
if (!GBConfigService.get('STORAGE_NAME')) {
if (GBConfigService.get('GB_MODE') !== 'legacy') {
const url = process.env.BOT_URL || `http://localhost:${GBConfigService.get('PORT')}`;
startRouter(GBServer.globals.server, instance.botId);
config['clientOptions'] = { baseUri: `http://localhost:${GBConfigService.get('PORT')}` };
config['clientOptions'] = { baseUri: url };
}
const adapter = new BotFrameworkAdapter(config);
@ -829,8 +923,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');
@ -866,8 +960,7 @@ 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);
@ -941,7 +1034,7 @@ export class GBMinService {
await min.whatsAppDirectLine.setup(true);
} else {
if (min !== minBoot && minBoot.instance.whatsappServiceKey && min.instance.webchatKey) {
if (min !== minBoot && minBoot.instance.whatsappServiceKey) {
min.whatsAppDirectLine = new WhatsappDirectLine(
min,
min.botId,
@ -1040,7 +1133,6 @@ export class GBMinService {
// Default activity processing and handler.
const handler = async context => {
// Handle activity text issues.
if (!context.activity.text) {
@ -1052,21 +1144,58 @@ 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 (process.env.STORAGE_NAME || !member) {
if (context.activity.type === 'conversationUpdate') {
if (
context.activity.membersAdded &&
context.activity.membersAdded.length > 0 &&
context.activity.membersAdded[0].id === context.activity.recipient.id
) {
GBLogEx.info(min, `Bot added to conversation: ${member.name}`);
return;
}
}
if (process.env.GB_MODE === 'legacy' || !member) {
member = context.activity.from;
}
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.
@ -1105,34 +1234,18 @@ 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);
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);
if (data.length > 0) {
await min.conversationalService.sendEvent(min, step, 'play', {
playerType: 'bullet',
data: data.slice(0, 10)
});
}
}
}
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.
@ -1146,7 +1259,6 @@ 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,
@ -1171,6 +1283,8 @@ 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,
@ -1189,53 +1303,37 @@ export class GBMinService {
if (context.activity.type === 'installationUpdate') {
GBLogEx.info(min, `Bot installed on Teams.`);
} 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.
} else if (context.activity.type === 'conversationUpdate') {
// Calls onNewSession event on each .gbapp package.
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...`);
await CollectionUtil.asyncForEach(appPackages, async e => {
await e.onNewSession(min, step);
});
// Calls onNewSession event on each .gbapp package.
// Auto starts dialogs if any is specified.
await CollectionUtil.asyncForEach(appPackages, async e => {
await e.onNewSession(min, step);
});
if (!startDialog && !(await sec.getParam(user, 'welcomed'))) {
// Otherwise, calls / (root) to default welcome users.
// Auto starts dialogs if any is specified.
if (!startDialog && !(await sec.getParam(user, 'welcomed'))) {
// Otherwise, calls / (root) to default welcome users.
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);
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);
}
}
await step.beginDialog('/');
} else {
GBLogEx.info(min, `Person added to conversation: ${member.name}`);
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 });
return;
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 if (context.activity.type === 'message') {
// Required for F0 handling of persisted conversations.
GBLogEx.info(
@ -1243,7 +1341,6 @@ export class GBMinService {
`Human: pid:${pid} ${context.activity.from.id} ${GBUtil.toYAML(WhatsappDirectLine.pidByNumber)} ${context.activity.text} (type: ${context.activity.type}, name: ${context.activity.name}, channelId: ${context.activity.channelId})`
);
// Processes messages activities.
await this.processMessageActivity(context, min, step, pid);
@ -1266,10 +1363,10 @@ export class GBMinService {
};
try {
if (!GBConfigService.get('STORAGE_NAME')) {
if (GBConfigService.get('GB_MODE') !== 'legacy') {
const context = adapter['createContext'](req);
context['_activity'] = context.activity.body;
await handler(context);
await adapter['processActivity'](req, res, handler);
// Return status
res.status(200);
@ -1302,12 +1399,13 @@ 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,
@ -1393,7 +1491,6 @@ 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.
@ -1437,16 +1534,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) {
@ -1554,15 +1651,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);
}
}
@ -1616,7 +1713,7 @@ export class GBMinService {
// Removes unwanted chars in input text.
step.context.activity['originalText'] = context.activity.text;
const text = await GBConversationalService.handleText(min, user, step, context.activity.text);
const text = context.activity.text;
step.context.activity['originalText'];
step.context.activity['text'] = text;
@ -1662,8 +1759,9 @@ 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,
@ -1786,10 +1884,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();
},
@ -1810,7 +1908,7 @@ export class GBMinService {
private mutex: Mutex = new Mutex();
public async watchPackages(min: GBMinInstance, packageType: string): Promise<void> {
if (!GBConfigService.get('STORAGE_NAME')) {
if (GBConfigService.get('GB_MODE') !== 'legacy') {
const packagePath = GBUtil.getGBAIPath(min.botId, packageType);
const libraryPath = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath);

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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,6 +99,7 @@ export class GBSSR {
'--disable-features=site-per-process',
'--disable-gpu',
'--no-first-run',
'--no-sandbox',
'--no-default-browser-check'
];
@ -117,7 +118,7 @@ export class GBSSR {
return {
args: args,
ignoreHTTPSErrors: true,
headless: false,
headless: process.env.CHROME_HEADLESS === 'true',
defaultViewport: null,
executablePath: process.env.CHROME_PATH ? process.env.CHROME_PATH : executablePath(),
ignoreDefaultArgs: ['--enable-automation', '--enable-blink-features=IdleDetection']
@ -335,6 +336,9 @@ 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);
}

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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,6 +55,18 @@ 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 => {

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

View file

@ -6,7 +6,7 @@
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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', () => {

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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} />;

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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.cloud">pragmatismo.cloud</a>
<a href="http://pragmatismo.com.br">pragmatismo.com.br</a>
</div>
);
export default footer

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| According to our dual licensing model, this program can be used either |
@ -21,66 +21,58 @@
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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"
src={this.props.instance.logo}
alt="General Bots Logo" />
<img className="pragmatismoLogo" width="64px" 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://pragmatismo.sharepoint.com/sites/bots/Online/${this.props.instance.botId}.gbai`)}
<span
className="iconText"
onClick={() =>
window.open(`https://drive.pragmatismo.com.br/browser/${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.cloud')}
>
<span className="iconText" onClick={() => window.open('mailto:talk@pragmatismo.com.br')}>
Suggestions
</span>
</div>
</div>
</div>

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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. |

View file

@ -5,7 +5,7 @@
| |
| |
| |
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
| General Bots Copyright (c) pragmatismo.com.br. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| 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.cloud. |
| "General Bots" is a registered trademark of pragmatismo.com.br. |
| 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