├── .editorconfig ├── .eslintignore ├── .eslintrc.json ├── .github ├── issue_template.md └── stale.yml ├── .gitignore ├── .npmignore ├── .travis.yml ├── ATTRIBUTIONS.md ├── CONTRIBUTING.md ├── LICENSE.md ├── banner.png ├── build ├── botkit-ci.yml ├── botkit-daily.yml └── scripts │ └── rebasePackageLock.js ├── changelog.md ├── lerna.json ├── package-lock.json ├── package.json ├── packages ├── botbuilder-adapter-facebook │ ├── .eslintrc.js │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── package-lock.json │ ├── package.json │ ├── readme.md │ ├── src │ │ ├── botworker.ts │ │ ├── facebook_adapter.ts │ │ ├── facebook_api.ts │ │ ├── facebook_event_middleware.ts │ │ └── index.ts │ ├── tests │ │ ├── FacebookAdapter.tests.js │ │ ├── FacebookEventMiddleware.tests.js │ │ └── shared.js │ └── tsconfig.json ├── botbuilder-adapter-hangouts │ ├── .eslintrc.js │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── package-lock.json │ ├── package.json │ ├── readme.md │ ├── src │ │ ├── botworker.ts │ │ ├── hangouts_adapter.ts │ │ └── index.ts │ ├── tests │ │ └── HangoutsAdapter.tests.js │ └── tsconfig.json ├── botbuilder-adapter-slack │ ├── .eslintrc.js │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── examples │ │ ├── index.js │ │ └── multiteam.js │ ├── package-lock.json │ ├── package.json │ ├── readme.md │ ├── src │ │ ├── botworker.ts │ │ ├── index.ts │ │ ├── messagetype_middleware.ts │ │ ├── slack_adapter.ts │ │ ├── slack_dialog.ts │ │ └── slackevent_middleware.ts │ ├── tests │ │ └── SlackAdapter.tests.js │ └── tsconfig.json ├── botbuilder-adapter-twilio-sms │ ├── .eslintrc.js │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── package-lock.json │ ├── package.json │ ├── readme.md │ ├── src │ │ ├── botworker.ts │ │ ├── index.ts │ │ └── twilio_adapter.ts │ ├── tests │ │ └── TwilioAdapter.tests.js │ └── tsconfig.json ├── botbuilder-adapter-web │ ├── .eslintrc.js │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── client │ │ ├── client.js │ │ ├── css │ │ │ ├── embed.css │ │ │ ├── embed.css.map │ │ │ ├── styles.css │ │ │ └── styles.css.map │ │ ├── embed.js │ │ ├── index.html │ │ ├── readme.md │ │ └── sass │ │ │ ├── _botkit.scss │ │ │ ├── _chat.scss │ │ │ ├── _home.scss │ │ │ ├── embed.scss │ │ │ └── styles.scss │ ├── package-lock.json │ ├── package.json │ ├── readme.md │ ├── src │ │ ├── index.ts │ │ └── web_adapter.ts │ ├── tests │ │ └── WebAdapter.tests.js │ └── tsconfig.json ├── botbuilder-adapter-webex │ ├── .eslintrc.js │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── package-lock.json │ ├── package.json │ ├── readme.md │ ├── src │ │ ├── botworker.ts │ │ ├── index.ts │ │ └── webex_adapter.ts │ ├── tests │ │ └── WebexAdapter.tests.js │ └── tsconfig.json ├── botkit-plugin-cms │ ├── .eslintrc.js │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── package-lock.json │ ├── package.json │ ├── readme.md │ ├── src │ │ ├── cms.ts │ │ └── index.ts │ └── tsconfig.json ├── botkit │ ├── .eslintrc.js │ ├── .gitignore │ ├── LICENSE.md │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── adapter.ts │ │ ├── botworker.ts │ │ ├── conversation.ts │ │ ├── conversationState.ts │ │ ├── core.ts │ │ ├── dialogWrapper.ts │ │ ├── index.ts │ │ ├── teamsHelpers.ts │ │ └── testClient.ts │ ├── tests │ │ ├── Core.tests.js │ │ ├── CustomAdapter.tests.js │ │ ├── Dialog.tests.js │ │ └── State.tests.js │ └── tsconfig.json ├── docs │ ├── .gitignore │ ├── advanced.md │ ├── build │ │ ├── adapter.hbs │ │ ├── build.sh │ │ ├── parse.js │ │ ├── plugin.hbs │ │ ├── template.hbs │ │ ├── toc-platforms.hbs │ │ └── toc.hbs │ ├── conversations.md │ ├── core.md │ ├── glitch.png │ ├── index.json │ ├── index.md │ ├── package-lock.json │ ├── package.json │ ├── platforms │ │ ├── facebook.md │ │ ├── hangouts.md │ │ ├── index.md │ │ ├── slack.md │ │ ├── twilio-sms.md │ │ ├── web.md │ │ └── webex.md │ ├── plugins │ │ ├── cms.md │ │ └── index.md │ ├── provisioning │ │ ├── IMG │ │ │ ├── Slack-eventsenable.png │ │ │ ├── botkit_icon.png │ │ │ ├── cisco_add.png │ │ │ ├── fb_app_perm.png │ │ │ ├── fb_mess.png │ │ │ ├── fb_new.png │ │ │ ├── fb_tokengen.png │ │ │ ├── fb_webhooks.png │ │ │ ├── fb_webhooks_com.png │ │ │ ├── slack-botuser.png │ │ │ ├── slack-im.png │ │ │ ├── slack-new.png │ │ │ ├── slack_botevents.png │ │ │ ├── slack_client_secret.png │ │ │ └── slack_oauth.png │ │ ├── cisco-spark.md │ │ ├── facebook_messenger.md │ │ ├── index.md │ │ ├── slack-events-api.md │ │ ├── teams.md │ │ └── twilio-sms.md │ ├── readme.md │ └── reference │ │ ├── cms.md │ │ ├── core.md │ │ ├── facebook.md │ │ ├── hangouts.md │ │ ├── index.md │ │ ├── slack.md │ │ ├── twilio-sms.md │ │ ├── web.md │ │ └── webex.md ├── generator-botkit │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── generators │ │ ├── app │ │ │ ├── index.js │ │ │ └── templates │ │ │ │ ├── bot.js │ │ │ │ ├── features │ │ │ │ ├── sample_echo.js │ │ │ │ └── sample_hears.js │ │ │ │ ├── gitignore │ │ │ │ ├── package.json │ │ │ │ └── readme.md │ │ ├── botframework │ │ │ ├── index.js │ │ │ └── templates │ │ │ │ ├── .env │ │ │ │ └── features │ │ │ │ └── botframework_features.js │ │ ├── facebook │ │ │ ├── index.js │ │ │ └── templates │ │ │ │ ├── .env │ │ │ │ └── features │ │ │ │ └── facebook_features.js │ │ ├── hangouts │ │ │ ├── index.js │ │ │ └── templates │ │ │ │ ├── .env │ │ │ │ └── features │ │ │ │ └── hangouts_features.js │ │ ├── slack │ │ │ ├── index.js │ │ │ └── templates │ │ │ │ ├── .env │ │ │ │ └── features │ │ │ │ ├── routes_oauth.js │ │ │ │ └── slack_features.js │ │ ├── twilio-sms │ │ │ ├── index.js │ │ │ └── templates │ │ │ │ ├── .env │ │ │ │ └── features │ │ │ │ └── twilio_features.js │ │ ├── web │ │ │ ├── index.js │ │ │ └── templates │ │ │ │ ├── .env │ │ │ │ ├── features │ │ │ │ ├── chat.js │ │ │ │ ├── typing.js │ │ │ │ └── websocket_features.js │ │ │ │ ├── public │ │ │ │ ├── client.js │ │ │ │ ├── css │ │ │ │ │ ├── embed.css │ │ │ │ │ ├── embed.css.map │ │ │ │ │ ├── styles.css │ │ │ │ │ └── styles.css.map │ │ │ │ └── index.html │ │ │ │ └── sass │ │ │ │ ├── _botkit.scss │ │ │ │ ├── _chat.scss │ │ │ │ ├── _home.scss │ │ │ │ ├── embed.scss │ │ │ │ └── styles.scss │ │ └── webex │ │ │ ├── index.js │ │ │ └── templates │ │ │ ├── .env │ │ │ └── features │ │ │ └── webex_features.js │ ├── package-lock.json │ ├── package.json │ ├── readme.md │ └── yeoman-generator.gif └── testbot │ ├── .gitignore │ ├── bot.js │ ├── botframework.js │ ├── custom_express.js │ ├── features │ ├── bot_inspector_mode.js │ ├── botframework_features.js │ ├── convo.js │ ├── convo_test.js │ ├── dynamic_attachments.js │ ├── facebook_features.js │ ├── flip_table.js │ ├── get_reference.js │ ├── hangouts_features.js │ ├── hear_patterns.js │ ├── interruptions.js │ ├── looping_dialog.js │ ├── luis_recognizer.js │ ├── middlewares.js │ ├── random_text_middleware.js │ ├── sample_onboarding.js │ ├── shutdown.js │ ├── slack_features.js │ ├── slack_modals.js │ ├── teams_features.js │ ├── test_convo.js │ ├── twilio_features.js │ ├── typescript.ts │ ├── waterfall_dialog.js │ ├── webex_features.js │ ├── websocket_features.js │ └── z_fallback.js │ ├── multiadapter.js │ ├── package-lock.json │ ├── package.json │ ├── plugins │ └── verbose │ │ ├── index.js │ │ ├── public │ │ └── test.txt │ │ └── views │ │ ├── layout.hbs │ │ └── template.hbs │ ├── public │ ├── client.js │ ├── css │ │ ├── embed.css │ │ ├── embed.css.map │ │ ├── styles.css │ │ └── styles.css.map │ └── index.html │ └── testbot.bot ├── readme.md └── todo.md /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 4 9 | 10 | [*.json] 11 | indent_size = 2 12 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | packages/testbot 2 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "plugins": ["@typescript-eslint"], 4 | "extends": ["plugin:@typescript-eslint/recommended"], 5 | "parserOptions": { 6 | "ecmaVersion": 9, 7 | "sourceType": "module", 8 | "ecmaFeatures": { 9 | "impliedStrict": true 10 | } 11 | }, 12 | "rules": { 13 | "semi": ["error", "always"], 14 | "no-return-await": 0, 15 | "space-before-function-paren": ["error", { 16 | "named": "never", 17 | "anonymous": "never", 18 | "asyncArrow": "always" 19 | }], 20 | "quotes": ["error", "single", {"allowTemplateLiterals": true}], 21 | "template-curly-spacing": ["error", "always"], 22 | "@typescript-eslint/camelcase": 0, 23 | "@typescript-eslint/indent": ["error", 4], 24 | "@typescript-eslint/interface-name-prefix": 0, 25 | "@typescript-eslint/no-explicit-any": 0, 26 | "@typescript-eslint/no-object-literal-type-assertion": ["error", { 27 | "allowAsParameter": true 28 | }], 29 | "@typescript-eslint/no-use-before-define": ["error", { "functions": false, "classes": true }] 30 | } 31 | } -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | 2 | ** DO NOT ERASE THESE INSTRUCTIONS WITHOUT READING THEM FIRST ** 3 | 4 | Please read this entire template before posting any issue to get faster response. 5 | 6 | Open an issue on this repository with your topic or question, providing as much detail as possible. The more we know, the better we can help. 7 | 8 | Before posting, search the repository to see if there's already an issue opened to avoid duplicates. 9 | 10 | ### Are you sure this is an issue with the Botkit core module? 11 | 12 | For all other questions, requests or help, please feel free to join the discussion slack : https://community.botkit.ai 13 | 14 | ### What are you trying to achieve or the steps to reproduce? 15 | 16 | Describe your issue here, include as much detail as necessary to reproduce the issue or implement a missing functionality. 17 | 18 | ```` 19 | // Wrap code in markdown source tags 20 | ```` 21 | 22 | ### What was the result you received? 23 | 24 | ### What did you expect? 25 | 26 | ### Screenshots and animated GIFs 27 | 28 | ### Context: 29 | 30 | - Botkit version: 31 | - Messaging Platform: 32 | - Node version: 33 | - Os: 34 | - Any other relevant information: 35 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - bug 8 | - next_release 9 | - platform request 10 | # Label to use when marking an issue as stale 11 | staleLabel: stale 12 | # Comment to post when marking an issue as stale. Set to `false` to disable 13 | markComment: > 14 | This issue has been automatically marked as stale because it has not had 15 | recent activity. It will be closed if no further activity occurs. Thank you 16 | for your contributions. 17 | # Comment to post when closing a stale issue. Set to `false` to disable 18 | closeComment: false 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | start.sh 3 | start_button.sh 4 | db/ 5 | examples/db_slackbutton_bot/ 6 | examples/db_slackbutton_incomingwebhook/ 7 | examples/db_slackbutton_slashcommand/ 8 | examples/db_team_bot/ 9 | .DS_Store 10 | */.DS_Store 11 | .idea 12 | .vscode 13 | .env 14 | coverage 15 | 16 | # simple_storage files 17 | /channels/ 18 | /teams/ 19 | /users/ 20 | 21 | # temp test files 22 | tests/**/temp/ 23 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | docs/provisioning/IMG 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - lts/* 4 | script: 5 | - lerna bootstrap --hoist 6 | - lerna run build 7 | - lerna run test -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Instructions for Contributing Code 2 | 3 | This project welcomes contributions and suggestions. Most contributions require you to agree to a 4 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us 5 | the rights to use your contribution. For details, visit https://cla.microsoft.com. 6 | 7 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide 8 | a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions 9 | provided by the bot. You will only need to do this once across all repos using our CLA. 10 | 11 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide 12 | a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions 13 | provided by the bot. You will only need to do this once across all repos using our CLA. 14 | 15 | ## Code of Conduct 16 | 17 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 18 | 19 | ## Submitting Issues 20 | 21 | * You can create an issue [here](https://github.com/howdyai/botkit/issues/new), 22 | but before doing that please read the notes below and include as many details as 23 | possible with your report. If you can, please include: 24 | * The version of Botkit you are using 25 | * The operating system you are using 26 | * If applicable, what you were doing when the issue arose and what you 27 | expected to happen 28 | * Other things that will help resolve your issue: 29 | * Screenshots and animated GIFs 30 | * Error output that appears in your terminal, dev tools or as an alert 31 | * Perform a [cursory search](https://github.com/howdyai/botkit/issues?utf8=✓&q=is%3Aissue+) 32 | to see if a similar issue has already been submitted 33 | 34 | ## Submitting Pull Requests 35 | 36 | * Pull requests should contain a concise topic and detailed accompanying text that clearly identifies both the purpose and justification for acceptance of any changes. 37 | * Create, or link to an existing issue identifying the need driving your PR request. The issue can contain more details of the need for the PR as well as host debate as to which course of action the PR will take that will most serve the common good. 38 | * Include screenshots and animated GIFs in your pull request whenever possible. 39 | * Run `npm test` before submitting and fix any issues. 40 | * Add tests to cover any new functionality. Add and/or update tests for any updates to the code. 41 | * Write documentation in [Markdown](https://daringfireball.net/projects/markdown). 42 | * Please follow, [JSDoc](http://usejsdoc.org/) for proper documentation. 43 | * Use short, present tense commit messages. See [Commit Message Styleguide](#git-commit-messages). 44 | 45 | ## Styleguides 46 | 47 | ### General Code 48 | 49 | * End files with a newline. 50 | * Place requires in the following order: 51 | * Built in Node Modules (such as `path`) 52 | * Local Modules (using relative paths) 53 | * Avoid platform-dependent code: 54 | * Use `path.join()` to concatenate filenames. 55 | * Using a plain `return` when returning explicitly at the end of a function. 56 | * Not `return null`, `return undefined`, `null`, or `undefined` 57 | 58 | ### Git Commit Messages 59 | 60 | * Use the present tense ("Add feature" not "Added feature") 61 | * Use the imperative mood ("Move cursor to..." not "Moves cursor to...") 62 | * Limit the first line to 72 characters or less 63 | * Reference issues and pull requests liberally 64 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howdyai/botkit/b8f0e3e7fd9238a585ffdcec4a691acb23d0adcf/banner.png -------------------------------------------------------------------------------- /build/scripts/rebasePackageLock.js: -------------------------------------------------------------------------------- 1 | #!/bin/node 2 | 3 | 'use strict'; 4 | 5 | // Usage: 6 | // cat package-lock.json | node rebasePackageLock.mjs https://your-project.pkgs.visualstudio.com/_packaging/your-feed/npm/registry/ > new-package-lock.json 7 | 8 | async function readAllStdin() { 9 | return new Promise((resolve, reject) => { 10 | const bufferList = []; 11 | let numBytes = 0; 12 | 13 | process.stdin.on('close', () => { 14 | resolve(Buffer.concat(bufferList, numBytes)); 15 | }); 16 | 17 | process.stdin.on('data', buffer => { 18 | bufferList.push(buffer); 19 | numBytes += buffer.length; 20 | }); 21 | 22 | process.stdin.on('error', reject); 23 | }); 24 | } 25 | 26 | function rebaseV1Inline(name, dependency, baseURL) { 27 | const { resolved: actual, version } = dependency; 28 | const singleName = name.split('/').reverse()[0]; 29 | 30 | const { href: expected } = new URL(`${name}/-/${singleName}-${version}.tgz`, 'https://registry.npmjs.org/'); 31 | const { href: rebased } = new URL(`${name}/-/${singleName}-${version}.tgz`, baseURL); 32 | 33 | if (expected !== actual) { 34 | throw new Error(`v1: Expecting "resolved" field to be "${expected}", actual is "${actual}".`); 35 | } 36 | 37 | dependency.resolved = rebased; 38 | 39 | rebaseV1InlineAll(dependency, baseURL); 40 | } 41 | 42 | function rebaseV1InlineAll({ dependencies }, baseURL) { 43 | for (const [name, dependency] of Object.entries(dependencies || {})) { 44 | rebaseV1Inline(name, dependency, baseURL); 45 | } 46 | } 47 | 48 | function rebaseV2Inline(path, dependency, baseURL) { 49 | const { resolved: actual, version } = dependency; 50 | const name = path.split('node_modules/').reverse()[0]; 51 | 52 | const singleName = name.split('/').reverse()[0]; 53 | 54 | const { href: expected } = new URL(`${name}/-/${singleName}-${version}.tgz`, 'https://registry.npmjs.org/'); 55 | const { href: rebased } = new URL(`${name}/-/${singleName}-${version}.tgz`, baseURL); 56 | 57 | if (expected !== actual) { 58 | throw new Error(`v2: Expecting "resolved" field to be "${expected}", actual is "${actual}".`); 59 | } 60 | 61 | dependency.resolved = rebased; 62 | } 63 | 64 | function rebaseV2InlineAll(packages, baseURL) { 65 | for (const [path, dependency] of Object.entries(packages || {})) { 66 | // "path" is falsy if it is iterating the current package. 67 | path && rebaseV2Inline(path, dependency, baseURL); 68 | } 69 | } 70 | 71 | async function main() { 72 | const baseURL = process.argv[2]; 73 | 74 | if (!baseURL) { 75 | throw new Error('New registry base URL must be passed as first argument.'); 76 | } 77 | 78 | const packageLockJSON = JSON.parse(await readAllStdin()); 79 | 80 | // v1 81 | rebaseV1InlineAll(packageLockJSON, baseURL); 82 | 83 | // v2 84 | rebaseV2InlineAll(packageLockJSON.packages, baseURL); 85 | 86 | const json = JSON.stringify(packageLockJSON, null, 2); 87 | 88 | if (~json.indexOf('://registry.npmjs.org')) { 89 | throw new Error('After rebase, "://registry.npmjs.org" should not be detected in the output.'); 90 | } 91 | 92 | console.log(json); 93 | } 94 | 95 | main(); 96 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | "packages/*" 4 | ], 5 | "version": "independent" 6 | } 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "botkit-packages", 3 | "private": true, 4 | "scripts": { 5 | "postinstall": "lerna bootstrap --hoist", 6 | "build": "lerna run build", 7 | "test": "lerna run build ; lerna run test", 8 | "build-docs": "lerna run build-docs", 9 | "eslint": "./node_modules/.bin/eslint ./packages/*/src/*.ts ./packages/*/src/**/*.ts", 10 | "eslint-fix": "./node_modules/.bin/eslint ./packages/*/src/*.ts ./packages/*/src/**/*.ts --fix", 11 | "lerna:pack": "lerna run pack" 12 | }, 13 | "devDependencies": { 14 | "@typescript-eslint/eslint-plugin": "^5.16.0", 15 | "@typescript-eslint/parser": "^5.16.0", 16 | "eslint": "^8.11.0", 17 | "eslint-config-standard": "^16.0.3", 18 | "lerna": "^4.0.0", 19 | "mocha": "^9.1.3", 20 | "nyc": "^15.1.0", 21 | "typescript": "^3.7.5" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-facebook/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "extends": "standard", 3 | "rules": { 4 | "semi": [2, "always"], 5 | "indent": [2, 4], 6 | "no-return-await": 0, 7 | "camelcase": 0, 8 | "no-unused-vars": 0, 9 | "@typescript-eslint/indent": 0, 10 | "@typescript-eslint/ban-ts-ignore": 1, 11 | "@typescript-eslint/no-object-literal-type-assertion": 0, 12 | "@typescript-eslint/explicit-member-accessibility": 1, 13 | "space-before-function-paren": [2, { 14 | "named": "never", 15 | "anonymous": "never", 16 | "asyncArrow": "always" 17 | }], 18 | "template-curly-spacing": [2, "always"] 19 | } 20 | }; -------------------------------------------------------------------------------- /packages/botbuilder-adapter-facebook/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .env 3 | lib/ 4 | .nyc_output/ 5 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-facebook/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # botbuilder-adapter-facebook changelog 2 | 3 | # 1.0.11 4 | 5 | * Update dependencies to Botkit 4.10, Bot Framework 4.10 6 | 7 | # 1.0.10 8 | 9 | * Update dependencies to Botkit 4.9, Bot Framework 4.9 10 | 11 | # 1.0.7 12 | 13 | * Fix for Facebook typing indicators. To send a typing indicator, use `await bot.say({sender_action: 'typing_on'});` 14 | 15 | # 1.0.6 16 | 17 | * Query parameters for GET apis can now be passed in using an object parameter (like POST): [Thanks to @adantoscano](https://github.com/howdyai/botkit/pull/1768) 18 | 19 | * Update dependencies (Bot Framework to 4.6, Botkit to 4.6) 20 | 21 | # 1.0.5 22 | 23 | * Properly export the facebook_api class so it can be used directly. Thanks to [@luckyluo](https://github.com/howdyai/botkit/pull/1766)! 24 | 25 | # 1.0.4 26 | 27 | * Update dependencies (Bot Framework to 4.5.2, Botkit to 4.5) 28 | * Fix for over-pruning of quick replies and attachments in dialogs 29 | 30 | # 1.0.3 31 | 32 | * Add `enable_incomplete` option to allow adapter to start without a complete config. 33 | 34 | # 1.0.2 35 | 36 | This was the first public release 37 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-facebook/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-facebook/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "botbuilder-adapter-facebook", 3 | "version": "1.0.12", 4 | "description": "Connect Botkit or BotBuilder to Facebook Messenger", 5 | "main": "lib/index.js", 6 | "typings": "./lib/index.d.ts", 7 | "files": [ 8 | "/lib", 9 | "/src" 10 | ], 11 | "scripts": { 12 | "build": "tsc", 13 | "test": "tsc ; nyc mocha tests/*.tests.js", 14 | "eslint": "./node_modules/.bin/eslint --fix src/*", 15 | "pack": "npm pack" 16 | }, 17 | "author": "Microsoft Corp.", 18 | "license": "MIT", 19 | "keywords": [ 20 | "facebook", 21 | "facebook messenger", 22 | "botkit", 23 | "botbuilder", 24 | "botframework", 25 | "bots", 26 | "chatbots", 27 | "azure" 28 | ], 29 | "homepage": "https://github.com/howdyai/botkit/blob/master/packages/botbuilder-adapter-facebook#readme", 30 | "bugs": { 31 | "url": "https://github.com/howdyai/botkit/issues" 32 | }, 33 | "repository": { 34 | "type": "git", 35 | "url": "https://github.com/howdyai/botkit.git" 36 | }, 37 | "dependencies": { 38 | "botbuilder": "^4.15.0", 39 | "botkit": "^4.15.0", 40 | "debug": "^4.1.0" 41 | }, 42 | "devDependencies": { 43 | "eslint": "^8.3.0", 44 | "eslint-config-standard": "^16.0.3", 45 | "eslint-plugin-import": "^2.25.3", 46 | "eslint-plugin-node": "^11.1.0", 47 | "eslint-plugin-promise": "^5.1.1", 48 | "eslint-plugin-standard": "^4.0.1" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-facebook/src/botworker.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module botbuilder-adapter-facebook 3 | */ 4 | /** 5 | * Copyright (c) Microsoft Corporation. All rights reserved. 6 | * Licensed under the MIT License. 7 | */ 8 | 9 | import { Botkit, BotWorker } from 'botkit'; 10 | import { FacebookAPI } from './facebook_api'; 11 | 12 | /** 13 | * This is a specialized version of [Botkit's core BotWorker class](core.md#BotWorker) that includes additional methods for interacting with Facebook. 14 | * It includes all functionality from the base class, as well as the extension methods below. 15 | * 16 | * When using the FacebookAdapter with Botkit, all `bot` objects passed to handler functions will include these extensions. 17 | */ 18 | export class FacebookBotWorker extends BotWorker { 19 | /** 20 | * A copy of the FacebookAPI client giving access to `let res = await bot.api.callAPI(path, method, parameters);` 21 | */ 22 | public api: FacebookAPI; 23 | 24 | /** 25 | * Reserved for use internally by Botkit's `controller.spawn()`, this class is used to create a BotWorker instance that can send messages, replies, and make other API calls. 26 | * 27 | * When used with the FacebookAdapter's multi-tenancy mode, it is possible to spawn a bot instance by passing in the Facebook page ID representing the appropriate bot identity. 28 | * Use this in concert with [startConversationWithUser()](#startConversationWithUser) and [changeContext()](core.md#changecontext) to start conversations 29 | * or send proactive alerts to users on a schedule or in response to external events. 30 | * 31 | * ```javascript 32 | * let bot = await controller.spawn(FACEBOOK_PAGE_ID); 33 | * ``` 34 | * @param botkit The Botkit controller object responsible for spawning this bot worker. 35 | * @param config Normally, a DialogContext object. Can also be the ID of a Facebook page managed by this app. 36 | */ 37 | public constructor(botkit: Botkit, config: any) { 38 | // allow a page id to be passed in 39 | if (typeof config === 'string') { 40 | const page_id = config; 41 | config = { 42 | // an activity is required to spawn the bot via the api 43 | activity: { 44 | channelId: 'facebook', 45 | recipient: { 46 | id: page_id 47 | } 48 | } 49 | }; 50 | } 51 | 52 | super(botkit, config); 53 | } 54 | 55 | // TODO: Typing indicators 56 | 57 | /** 58 | * Change the operating context of the worker to begin a conversation with a specific user. 59 | * After calling this method, any calls to `bot.say()` or `bot.beginDialog()` will occur in this new context. 60 | * 61 | * This method can be used to send users scheduled messages or messages triggered by external events. 62 | * ```javascript 63 | * let bot = await controller.spawn(FACEBOOK_PAGE_ID); 64 | * await bot.startConversationWithUser(FACEBOOK_USER_PSID); 65 | * await bot.say('Howdy human!'); 66 | * ``` 67 | * 68 | * @param userId the PSID of a user the bot has previously interacted with 69 | */ 70 | public async startConversationWithUser(userId): Promise { 71 | await this.changeContext({ 72 | channelId: 'facebook', 73 | // @ts-ignore 74 | conversation: { id: userId }, 75 | bot: this.getConfig('activity').recipient, 76 | // @ts-ignore 77 | user: { id: userId } 78 | }); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-facebook/src/facebook_api.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module botbuilder-adapter-facebook 3 | */ 4 | /** 5 | * Copyright (c) Microsoft Corporation. All rights reserved. 6 | * Licensed under the MIT License. 7 | */ 8 | 9 | import * as request from 'request'; 10 | import * as crypto from 'crypto'; 11 | 12 | /** 13 | * A simple API client for the Facebook API. Automatically signs requests with the access token and app secret proof. 14 | * It can be used to call any API provided by Facebook. 15 | * 16 | */ 17 | export class FacebookAPI { 18 | private token: string; 19 | private secret: string; 20 | private api_host: string; 21 | private api_version: string; 22 | 23 | /** 24 | * Create a FacebookAPI client. 25 | * ``` 26 | * let api = new FacebookAPI(TOKEN, SECRET); 27 | * await api.callAPI('/some/api','POST', {some_options}); 28 | * ``` 29 | * @param token a page access token 30 | * @param secret an app secret 31 | * @param api_host optional root hostname for constructing api calls, defaults to graph.facebook.com 32 | * @param api_version optional api version used when constructing api calls, defaults to v3.2 33 | */ 34 | public constructor(token: string, secret: string, api_host = 'graph.facebook.com', api_version = 'v3.2') { 35 | if (!token) { 36 | throw new Error('Token is required!'); 37 | } 38 | this.token = token; 39 | this.secret = secret; 40 | this.api_host = api_host; 41 | this.api_version = api_version; 42 | } 43 | 44 | /** 45 | * Call one of the Facebook APIs 46 | * @param path Path to the API endpoint, for example `/me/messages` 47 | * @param method HTTP method, for example POST, GET, DELETE or PUT. 48 | * @param payload An object to be sent as parameters to the API call. 49 | */ 50 | public async callAPI(path: string, method = 'POST', payload: any = {}): Promise { 51 | const proof = this.getAppSecretProof(this.token, this.secret); 52 | 53 | let queryString = '?'; 54 | let body = {}; 55 | 56 | if (method.toUpperCase() === 'GET') { 57 | for (const key in payload) { 58 | queryString = queryString + `${ encodeURIComponent(key) }=${ encodeURIComponent(payload[key]) }&`; 59 | } 60 | } else { 61 | body = payload; 62 | } 63 | 64 | return new Promise((resolve, reject) => { 65 | request({ 66 | method: method.toUpperCase(), 67 | json: true, 68 | body, 69 | uri: `https://${ this.api_host }/${ this.api_version }${ path }${ queryString }access_token=${ this.token }&appsecret_proof=${ proof }` 70 | }, (err, res, body) => { 71 | if (err) { 72 | reject(err); 73 | } else if (body.error) { 74 | reject(body.error.message); 75 | } else { 76 | resolve(body); 77 | } 78 | }); 79 | }); 80 | } 81 | 82 | /** 83 | * Generate the app secret proof used to increase security on calls to the graph API 84 | * @param access_token a page access token 85 | * @param app_secret an app secret 86 | */ 87 | private getAppSecretProof(access_token, app_secret): string { 88 | const hmac = crypto.createHmac('sha256', app_secret || ''); 89 | return hmac.update(access_token).digest('hex'); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-facebook/src/facebook_event_middleware.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module botbuilder-adapter-facebook 3 | */ 4 | /** 5 | * Copyright (c) Microsoft Corporation. All rights reserved. 6 | * Licensed under the MIT License. 7 | */ 8 | 9 | import { MiddlewareSet, ActivityTypes } from 'botbuilder'; 10 | 11 | /** 12 | * This adapter middleware, when used in conjunction with FacebookAdapter and Botkit, will result in Botkit emitting events with 13 | * names based on their event type. 14 | * 15 | * ```javascript 16 | * const adapter = new FacebookAdapter(MY_OPTIONS); 17 | * adapter.use(new FacebookEventTypeMiddleware()); 18 | * const controller = new Botkit({ 19 | * adapter: adapter, 20 | * }); 21 | * 22 | * // define a handler for one of the new events 23 | * controller.on('facebook_option', async(bot, message) => { 24 | * // ... 25 | * }); 26 | * ``` 27 | * 28 | * When used, events emitted may include: 29 | * * facebook_postback 30 | * * facebook_referral 31 | * * facebook_optin 32 | * * message_delivered 33 | * * message_read 34 | * * facebook_account_linking 35 | * * message_echo 36 | * * facebook_app_roles 37 | * * standby 38 | * * facebook_receive_thread_control 39 | * * facebook_request_thread_control 40 | * 41 | */ 42 | export class FacebookEventTypeMiddleware extends MiddlewareSet { 43 | /** 44 | * Implements the middleware's onTurn function. Called automatically. 45 | * @ignore 46 | * @param context 47 | * @param next 48 | */ 49 | public async onTurn(context, next): Promise { 50 | if (context.activity && context.activity.channelData) { 51 | let type = null; 52 | if (context.activity.channelData.postback) { 53 | type = 'facebook_postback'; 54 | } else if (context.activity.channelData.referral) { 55 | type = 'facebook_referral'; 56 | } else if (context.activity.channelData.optin) { 57 | type = 'facebook_optin'; 58 | } else if (context.activity.channelData.delivery) { 59 | type = 'message_delivered'; 60 | } else if (context.activity.channelData.read) { 61 | type = 'message_read'; 62 | } else if (context.activity.channelData.account_linking) { 63 | type = 'facebook_account_linking'; 64 | } else if (context.activity.channelData.message && context.activity.channelData.message.is_echo) { 65 | type = 'message_echo'; 66 | context.activity.type = ActivityTypes.Event; 67 | } else if (context.activity.channelData.app_roles) { 68 | type = 'facebook_app_roles'; 69 | } else if (context.activity.channelData.standby) { 70 | type = 'standby'; 71 | } else if (context.activity.channelData.pass_thread_control) { 72 | type = 'facebook_receive_thread_control'; 73 | } else if (context.activity.channelData.take_thread_control) { 74 | type = 'facebook_lose_thread_control'; 75 | } else if (context.activity.channelData.request_thread_control) { 76 | type = 'facebook_request_thread_control'; 77 | } 78 | 79 | context.activity.channelData.botkitEventType = type; 80 | } 81 | 82 | await next(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-facebook/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module botbuilder-adapter-facebook 3 | */ 4 | /** 5 | * Copyright (c) Microsoft Corporation. All rights reserved. 6 | * Licensed under the MIT License. 7 | */ 8 | 9 | export * from './botworker'; 10 | export * from './facebook_adapter'; 11 | export * from './facebook_api'; 12 | export * from './facebook_event_middleware'; 13 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-facebook/tests/FacebookEventMiddleware.tests.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const { FacebookAdapter, FacebookEventTypeMiddleware } = require('../'); 3 | const { Res, Req, fakeVerifySignature } = require('./shared'); 4 | 5 | describe('FacebookEventTypeMiddleware', function() { 6 | 7 | it ('should process a non-message incoming request into an event...', function(done) { 8 | 9 | const adapter = new FacebookAdapter({ 10 | access_token: '123', 11 | app_secret: '123', 12 | verify_token: '123', 13 | }); 14 | 15 | adapter.use(new FacebookEventTypeMiddleware()); 16 | 17 | adapter.verifySignature = fakeVerifySignature; 18 | let res = new Res(); 19 | adapter.processActivity(new Req({ 20 | entry: [ 21 | { 22 | messaging: [ 23 | { 24 | sender: { id: 1 }, 25 | recipient: { id: 2 }, 26 | read: { 27 | mid: 1, 28 | } 29 | } 30 | ] 31 | } 32 | ] 33 | }), res, async(context) => { 34 | assert(context.activity.type === 'event', 'activity is not a event'); 35 | assert(context.activity.channelData.botkitEventType === 'message_read', 'botkitEventType not set properly'); 36 | 37 | done(); 38 | }); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-facebook/tests/shared.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports.FakeAPI = class FakeAPI { 3 | constructor(cb) { 4 | this.cb = cb; 5 | } 6 | callAPI(endpoint, method, params) { 7 | this.cb(endpoint, method, params); 8 | } 9 | } 10 | module.exports.Req = class Req { 11 | constructor(body) { 12 | this.body = body; 13 | } 14 | } 15 | 16 | module.exports.Res = class Res { 17 | send(val) { 18 | this._sent = val; 19 | // console.log('SEND', val); 20 | return this; 21 | } 22 | status(status) { 23 | this._status = status; 24 | // console.log('STATUS', status); 25 | return this; 26 | } 27 | json(json) { 28 | this._json = json; 29 | // console.log('JSON', json); 30 | return this; 31 | } 32 | end(val) { 33 | // console.log('END', val); 34 | return this; 35 | } 36 | } 37 | 38 | module.exports.fakeVerifySignature = fakeVerifySignature = async (req, res) => { 39 | return true; 40 | } -------------------------------------------------------------------------------- /packages/botbuilder-adapter-facebook/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2015", 4 | "module": "commonjs", 5 | "declaration": true, 6 | "sourceMap": true, 7 | "outDir": "./lib", 8 | "rootDir": "./src", 9 | "types" : ["node"], 10 | "lib": [ 11 | "es5", 12 | "es2015", 13 | "es2016.array.include", 14 | "esnext.asynciterable", 15 | "dom" 16 | ] 17 | }, 18 | "include": [ 19 | "src/**/*" 20 | ] 21 | } -------------------------------------------------------------------------------- /packages/botbuilder-adapter-hangouts/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "extends": "standard", 3 | "rules": { 4 | "semi": [2, "always"], 5 | "indent": [2, 4], 6 | "no-return-await": 0, 7 | "camelcase": 0, 8 | "no-unused-vars": 0, 9 | "@typescript-eslint/indent": 0, 10 | "@typescript-eslint/ban-ts-ignore": 1, 11 | "@typescript-eslint/no-object-literal-type-assertion": 0, 12 | "@typescript-eslint/explicit-member-accessibility": 1, 13 | "space-before-function-paren": [2, { 14 | "named": "never", 15 | "anonymous": "never", 16 | "asyncArrow": "always" 17 | }], 18 | "template-curly-spacing": [2, "always"] 19 | } 20 | }; -------------------------------------------------------------------------------- /packages/botbuilder-adapter-hangouts/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .env 3 | lib/ 4 | .nyc_output/ 5 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-hangouts/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # botbuilder-adapter-hangouts changelog 2 | 3 | 4 | # 1.0.8 5 | 6 | * Update dependencies to Botkit 4.10, Bot Framework 4.10 7 | 8 | # 1.0.7 9 | 10 | * Update dependencies to Botkit 4.9, Bot Framework 4.9 11 | 12 | # 1.0.4 13 | 14 | * Update dependencies (Bot Framework to 4.6, Botkit to 4.6) 15 | 16 | # 1.0.3 17 | 18 | * Update dependencies (Bot Framework to 4.5.2, Botkit to 4.5) 19 | 20 | # 1.0.2 21 | 22 | * Add `enable_incomplete` option to allow adapter to start without a complete config. 23 | 24 | # 1.0.1 25 | 26 | First public release -------------------------------------------------------------------------------- /packages/botbuilder-adapter-hangouts/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-hangouts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "botbuilder-adapter-hangouts", 3 | "version": "1.0.9", 4 | "description": "Connect Botkit or BotBuilder to Google Hangouts", 5 | "main": "./lib/index.js", 6 | "typings": "./lib/index.d.ts", 7 | "files": [ 8 | "/lib", 9 | "/src" 10 | ], 11 | "scripts": { 12 | "build": "tsc", 13 | "test": "tsc ; nyc mocha tests/*.tests.js", 14 | "eslint": "./node_modules/.bin/eslint --fix src/*", 15 | "pack": "npm pack" 16 | }, 17 | "author": "Microsoft Corp.", 18 | "license": "MIT", 19 | "keywords": [ 20 | "google hangouts", 21 | "hangouts", 22 | "botkit", 23 | "botbuilder", 24 | "botframework", 25 | "bots", 26 | "chatbots", 27 | "azure" 28 | ], 29 | "homepage": "https://github.com/howdyai/botkit/blob/master/packages/botbuilder-adapter-hangouts#readme", 30 | "bugs": { 31 | "url": "https://github.com/howdyai/botkit/issues" 32 | }, 33 | "repository": { 34 | "type": "git", 35 | "url": "https://github.com/howdyai/botkit.git" 36 | }, 37 | "dependencies": { 38 | "botbuilder": "^4.15.0", 39 | "googleapis": "^92.0.0", 40 | "botkit": "^4.15.0", 41 | "debug": "^4.1.0" 42 | }, 43 | "devDependencies": { 44 | "eslint": "^8.3.0", 45 | "eslint-config-standard": "^16.0.3", 46 | "eslint-plugin-import": "^2.25.3", 47 | "eslint-plugin-node": "^11.1.0", 48 | "eslint-plugin-promise": "^5.1.1", 49 | "eslint-plugin-standard": "^4.0.1" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-hangouts/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module botbuilder-adapter-hangouts 3 | */ 4 | /** 5 | * Copyright (c) Microsoft Corporation. All rights reserved. 6 | * Licensed under the MIT License. 7 | */ 8 | 9 | export * from './hangouts_adapter'; 10 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-hangouts/tests/HangoutsAdapter.tests.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const { HangoutsAdapter } = require('../'); 3 | 4 | describe('HangoutsAdapter', function() { 5 | 6 | let adapter; 7 | 8 | // beforeEach(function () { 9 | // adapter = new HangoutsAdapter({ 10 | // token: '123', 11 | // }); 12 | // }); 13 | 14 | it('should not construct without required parameters', function () { 15 | assert.throws(function () { let adapter = new HangoutsAdapter({}) }, 'Foo'); 16 | }); 17 | 18 | // it('should create a HangoutsAdapter object', function () { 19 | // assert((adapter instanceof HangoutsAdapter), 'Adapter is wrong type'); 20 | // }); 21 | 22 | }); 23 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-hangouts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2015", 4 | "module": "commonjs", 5 | "declaration": true, 6 | "sourceMap": true, 7 | "outDir": "./lib", 8 | "rootDir": "./src", 9 | "types" : ["node"], 10 | "lib": [ 11 | "es5", 12 | "es2015", 13 | "es2016.array.include", 14 | "esnext.asynciterable", 15 | "dom" 16 | ] 17 | }, 18 | "include": [ 19 | "src/**/*" 20 | ] 21 | } -------------------------------------------------------------------------------- /packages/botbuilder-adapter-slack/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "extends": "standard", 3 | "rules": { 4 | "semi": [2, "always"], 5 | "indent": [2, 4], 6 | "no-return-await": 0, 7 | "camelcase": 0, 8 | "no-unused-vars": 0, 9 | "@typescript-eslint/ban-ts-ignore": 1, 10 | "@typescript-eslint/no-object-literal-type-assertion": 0, 11 | "@typescript-eslint/indent": 0, 12 | "@typescript-eslint/explicit-member-accessibility": 1, 13 | "space-before-function-paren": [2, { 14 | "named": "never", 15 | "anonymous": "never", 16 | "asyncArrow": "always" 17 | }], 18 | "template-curly-spacing": [2, "always"] 19 | } 20 | }; -------------------------------------------------------------------------------- /packages/botbuilder-adapter-slack/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .env 3 | lib/ 4 | .nyc_output/ 5 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-slack/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # botbuilder-adapter-slack changelog 2 | 3 | 4 | # 1.0.13 5 | 6 | * Update dependencies to Botkit 4.10, Bot Framework 4.10 7 | * Update @slack/web-api to 5.11.0 8 | 9 | 10 | # 1.0.12 11 | 12 | * Adjust startPrivateConversation to use converations.open instead of im.open 13 | 14 | 15 | # 1.0.11 16 | 17 | * Update dependencies to Botkit 4.9, Bot Framework 4.9 18 | * Fox: Remove enforcement of as_user field when using v2 oauth - Thanks to [@garytowers](https://github.com/GaryTowers) for [this pull request](https://github.com/howdyai/botkit/pull/1944). 19 | 20 | # 1.0.10 21 | 22 | * FIX: Fixing a bug introduced in 4.8 pertaining to spawning proactive bots for Slack. [#1937](https://github.com/howdyai/botkit/issues/1937) 23 | 24 | # 1.0.9 25 | 26 | * Update @slack/web-api to 5.8.0 27 | * Add `oauthVersion` parameter to constructor. If set to `v2`, oauth features will use Slack's latest auth functions and urls. [More info](readme.md#using-slacks-v2-oauth) 28 | * Make `authed_users` field available. [Fix for #1911](https://github.com/howdyai/botkit/issues/1911) 29 | 30 | # 1.0.8 31 | 32 | * Update @slack/web-api to 5.7.0 which includes access to new Oauth features (see [#1890](https://github.com/howdyai/botkit/pull/1890)) 33 | * Make `redirectUri` optional in type definition - thanks @yakirn [#1895](https://github.com/howdyai/botkit/pull/1895/files) 34 | 35 | # 1.0.7 36 | 37 | * Update @slack/web-api to 5.5.0 38 | 39 | # 1.0.6 40 | 41 | * Update dependencies (Bot Framework to 4.6, Botkit to 4.6) 42 | 43 | # 1.0.5 44 | 45 | * Add support for using the new [Block Kit modals](https://api.slack.com/block-kit/surfaces/modals). Check out [this sample code for examples of using them](https://github.com/howdyai/botkit/blob/master/packages/testbot/features/slack_modals.js). 46 | * Update to the latest version of the [@slack/web-api](https://www.npmjs.com/package/@slack/web-api), granting access to recently added methods like views.open, views.update 47 | * Fix: previous versions incorrectly labeled incoming `block_actions` and `interactive_message` events as `message` events. This version corrects this - `controller.on('block_actions',...)` and `controller.hears(pattern,'block_actions',...)` should now work. 48 | * Expand ability to "hear" block actions and use them in conversations. Selections from dropdowns and datepickers can now be heard by the bot and will be included as `message.text` in incoming messages. Thanks to [@sfny](https://github.com/sfny) for the [pull request](https://github.com/howdyai/botkit/pull/1809) 49 | 50 | 51 | # 1.0.4 52 | 53 | * Update dependencies (Bot Framework to 4.5.2, Botkit to 4.5) 54 | * Block actions and interactive button clicks are now classified as "message" type events, and thus included in conversations 55 | * Update some type definitions in the Slack Dialog class. 56 | 57 | 58 | # 1.0.3 59 | 60 | * Fix typo in replyInteractive - Thanks to [@VictorGrycuk](https://github.com/VictorGrycuk) for [the fix](https://github.com/howdyai/botkit/pull/1650) 61 | * Fix for handling some events that do not have a channel id - Thanks to [@roger-king](https://github.com/roger-king) and [@jebarjonet](https://github.com/jebarjonet) for help [trackign this down](https://github.com/howdyai/botkit/issues/1641) 62 | * Update Typedef of Slack dialog options - Thanks to [@roger-king](https://github.com/roger-king) for [the fix](https://github.com/howdyai/botkit/pull/1653) 63 | * Add `enable_incomplete` option to allow adapter to start without a complete config. 64 | 65 | # 1.0.2 66 | 67 | * Fix for [getInstallLink()](https://github.com/howdyai/botkit/pull/1642) - now includes redirectUri if set. Thanks to [@jebarjonet](https://github.com/jebarjonet) for the fix. 68 | * Fix to TypeScript definition, - Thanks to [@roger-king](https://github.com/roger-king) for [this contribution](https://github.com/howdyai/botkit/pull/1634). 69 | 70 | # 1.0.1 71 | 72 | This was the first public release! 73 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-slack/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-slack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "botbuilder-adapter-slack", 3 | "version": "1.0.14", 4 | "description": "Connect Botkit or BotBuilder to Slack", 5 | "main": "./lib/index.js", 6 | "typings": "./lib/index.d.ts", 7 | "files": [ 8 | "/lib", 9 | "/src" 10 | ], 11 | "scripts": { 12 | "build": "tsc", 13 | "test": "tsc ; nyc mocha tests/*.tests.js", 14 | "eslint": "./node_modules/.bin/eslint --fix src/*", 15 | "pack": "npm pack" 16 | }, 17 | "author": "Microsoft Corp.", 18 | "license": "MIT", 19 | "keywords": [ 20 | "slack", 21 | "botkit", 22 | "botbuilder", 23 | "botframework", 24 | "bots", 25 | "chatbots", 26 | "azure" 27 | ], 28 | "homepage": "https://github.com/howdyai/botkit/blob/master/packages/botbuilder-adapter-slack#readme", 29 | "bugs": { 30 | "url": "https://github.com/howdyai/botkit/issues" 31 | }, 32 | "repository": { 33 | "type": "git", 34 | "url": "https://github.com/howdyai/botkit.git" 35 | }, 36 | "dependencies": { 37 | "@slack/web-api": "^6.5.1", 38 | "botbuilder": "^4.15.0", 39 | "botkit": "^4.15.0", 40 | "debug": "^4.1.0" 41 | }, 42 | "devDependencies": { 43 | "eslint": "^8.3.0", 44 | "eslint-config-standard": "^16.0.3", 45 | "eslint-plugin-import": "^2.25.3", 46 | "eslint-plugin-node": "^11.1.0", 47 | "eslint-plugin-promise": "^5.1.1", 48 | "eslint-plugin-standard": "^4.0.1" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-slack/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module botbuilder-adapter-slack 3 | */ 4 | /** 5 | * Copyright (c) Microsoft Corporation. All rights reserved. 6 | * Licensed under the MIT License. 7 | */ 8 | 9 | export * from './slack_adapter'; 10 | export * from './slack_dialog'; 11 | export * from './messagetype_middleware'; 12 | export * from './slackevent_middleware'; 13 | export * from './botworker'; 14 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-slack/src/slackevent_middleware.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module botbuilder-adapter-slack 3 | */ 4 | /** 5 | * Copyright (c) Microsoft Corporation. All rights reserved. 6 | * Licensed under the MIT License. 7 | */ 8 | 9 | import { ActivityTypes, MiddlewareSet, TurnContext } from 'botbuilder'; 10 | 11 | /** 12 | * A middleware for Botkit developers using the BotBuilder SlackAdapter class. 13 | * This middleware causes Botkit to emit message events by their `type` or `subtype` field rather than their default BotBuilder Activity type (limited to message or event). 14 | * This keeps the new Botkit behavior consistent withprevious versions, and provides helpful filtering on the many event types that Slack sends. 15 | * To use this, bind it to the adapter before creating the Botkit controller: 16 | * ```javascript 17 | * const adapter = new SlackAdapter(options); 18 | * adapter.use(new SlackEventMiddleware()); 19 | * const controller = new Botkit({ 20 | * adapter: adapter, 21 | * // ... 22 | * }); 23 | * 24 | * // can bind directly to channel_join (which starts as a message with type message and subtype channel_join) 25 | * controller.on('channel_join', async(bot, message) => { 26 | * // send a welcome 27 | * }); 28 | * ``` 29 | */ 30 | export class SlackEventMiddleware extends MiddlewareSet { 31 | /** 32 | * Not for direct use - implements the MiddlewareSet's required onTurn function used to process the event 33 | * @param context 34 | * @param next 35 | */ 36 | public async onTurn(context: TurnContext, next: () => Promise): Promise { 37 | if (context.activity.type === ActivityTypes.Event && context.activity.channelData) { 38 | // Handle message sub-types 39 | if (context.activity.channelData.subtype) { 40 | context.activity.channelData.botkitEventType = context.activity.channelData.subtype; 41 | } else if (context.activity.channelData.type) { 42 | context.activity.channelData.botkitEventType = context.activity.channelData.type; 43 | } 44 | } 45 | await next(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-slack/tests/SlackAdapter.tests.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const { SlackAdapter } = require('../'); 3 | 4 | describe('SlackAdapter', function() { 5 | 6 | let adapter; 7 | 8 | beforeEach(function () { 9 | adapter = new SlackAdapter({ 10 | clientSigningSecret: '123', 11 | clientId: '123', 12 | clientSecret: '123', 13 | scopes: ['bot'], 14 | redirectUri: 'https://fake.com/install/auth', 15 | getBotUserByTeam: async(team) => '123', 16 | getTokenForTeam: async(team) => '123', 17 | }); 18 | }); 19 | 20 | it('should not construct without required parameters', function () { 21 | assert.throws(function () { let adapter = new SlackAdapter({}) }, 'Foo'); 22 | }); 23 | 24 | it('should create a SlackAdapter object', function () { 25 | assert((adapter instanceof SlackAdapter), 'Adapter is wrong type'); 26 | }); 27 | 28 | }); 29 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-slack/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2015", 4 | "module": "commonjs", 5 | "declaration": true, 6 | "sourceMap": true, 7 | "outDir": "./lib", 8 | "rootDir": "./src", 9 | "types" : ["node"], 10 | "lib": [ 11 | "es5", 12 | "es2015", 13 | "es2016.array.include", 14 | "esnext.asynciterable", 15 | "dom" 16 | ] 17 | }, 18 | "include": [ 19 | "src/**/*" 20 | ] 21 | } -------------------------------------------------------------------------------- /packages/botbuilder-adapter-twilio-sms/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "extends": "standard", 3 | "rules": { 4 | "semi": [2, "always"], 5 | "indent": [2, 4], 6 | "no-return-await": 0, 7 | "camelcase": 0, 8 | "no-unused-vars": 0, 9 | "@typescript-eslint/indent": 0, 10 | "@typescript-eslint/no-object-literal-type-assertion": 0, 11 | "@typescript-eslint/explicit-member-accessibility": 1, 12 | "space-before-function-paren": [2, { 13 | "named": "never", 14 | "anonymous": "never", 15 | "asyncArrow": "always" 16 | }], 17 | "template-curly-spacing": [2, "always"] 18 | } 19 | }; -------------------------------------------------------------------------------- /packages/botbuilder-adapter-twilio-sms/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .env 3 | lib/ 4 | .nyc_output/ 5 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-twilio-sms/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # botbuilder-adapter-twilio changelog 2 | 3 | # 1.0.7 4 | 5 | * Update dependencies to Botkit 4.10, Bot Framework 4.10 6 | 7 | # 1.0.6 8 | 9 | * Update dependencies to Botkit 4.9, Bot Framework 4.9 10 | 11 | # 1.0.4 12 | 13 | * Update dependencies (Bot Framework to 4.6, Botkit to 4.6) 14 | 15 | # 1.0.2 16 | 17 | * Update dependencies (Bot Framework to 4.5.2, Botkit to 4.5) 18 | 19 | # 1.0.1 20 | 21 | * Add `enable_incomplete` option to allow adapter to start without a complete config. 22 | 23 | # 1.0.0 24 | 25 | first public release -------------------------------------------------------------------------------- /packages/botbuilder-adapter-twilio-sms/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-twilio-sms/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "botbuilder-adapter-twilio-sms", 3 | "version": "1.0.8", 4 | "description": "Connect Botkit or BotBuilder to Twilio SMS", 5 | "main": "./lib/index.js", 6 | "typings": "./lib/index.d.ts", 7 | "files": [ 8 | "/lib", 9 | "/src" 10 | ], 11 | "scripts": { 12 | "build": "tsc", 13 | "test": "tsc ; nyc mocha tests/*.tests.js", 14 | "eslint": "./node_modules/.bin/eslint --fix src/*", 15 | "pack": "npm pack" 16 | }, 17 | "author": "Microsoft Corp.", 18 | "license": "MIT", 19 | "keywords": [ 20 | "twilio", 21 | "sms", 22 | "twilio sms", 23 | "texting", 24 | "txting", 25 | "botkit", 26 | "botbuilder", 27 | "botframework", 28 | "bots", 29 | "chatbots", 30 | "azure" 31 | ], 32 | "homepage": "https://github.com/howdyai/botkit/blob/master/packages/botbuilder-adapter-twilio-sms#readme", 33 | "bugs": { 34 | "url": "https://github.com/howdyai/botkit/issues" 35 | }, 36 | "repository": { 37 | "type": "git", 38 | "url": "https://github.com/howdyai/botkit.git" 39 | }, 40 | "dependencies": { 41 | "botbuilder": "^4.15.0", 42 | "botkit": "^4.15.0", 43 | "debug": "^4.1.0", 44 | "twilio": "^3.29.2" 45 | }, 46 | "devDependencies": { 47 | "eslint": "^8.3.0", 48 | "eslint-config-standard": "^16.0.3", 49 | "eslint-plugin-import": "^2.25.3", 50 | "eslint-plugin-node": "^11.1.0", 51 | "eslint-plugin-promise": "^5.1.1", 52 | "eslint-plugin-standard": "^4.0.1" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-twilio-sms/src/botworker.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module botbuilder-adapter-twilio-sms 3 | */ 4 | /** 5 | * Copyright (c) Microsoft Corporation. All rights reserved. 6 | * Licensed under the MIT License. 7 | */ 8 | 9 | import { BotWorker } from 'botkit'; 10 | import * as Twilio from 'twilio'; 11 | import { ConversationAccount, ChannelAccount } from 'botbuilder'; 12 | 13 | /** 14 | * This is a specialized version of [Botkit's core BotWorker class](core.md#BotWorker) that includes additional methods for interacting with Twilio SMS. 15 | * It includes all functionality from the base class, as well as the extension methods below. 16 | * 17 | * When using the TwilioAdapter with Botkit, all `bot` objects passed to handler functions will include these extensions. 18 | */export class TwilioBotWorker extends BotWorker { 19 | /** 20 | * A copy of the Twilio API client. 21 | */ 22 | public api: Twilio.Twilio; // Twilio api 23 | 24 | /** 25 | * Start a conversation with a given user identified by their phone number. Useful for sending pro-active messages: 26 | * 27 | * ```javascript 28 | * let bot = await controller.spawn(); 29 | * await bot.startConversationWithUser(MY_PHONE_NUMBER); 30 | * await bot.send('An important update!'); 31 | * ``` 32 | * 33 | * @param userId A phone number in the form +1XXXYYYZZZZ 34 | */ 35 | public async startConversationWithUser(userId: string): Promise { 36 | return this.changeContext({ 37 | channelId: 'twilio-sms', 38 | conversation: { id: userId } as ConversationAccount, 39 | bot: { id: this.controller.getConfig('twilio_number'), name: 'bot' }, 40 | user: { id: userId } as ChannelAccount 41 | }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-twilio-sms/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module botbuilder-adapter-twilio-sms 3 | */ 4 | /** 5 | * Copyright (c) Microsoft Corporation. All rights reserved. 6 | * Licensed under the MIT License. 7 | */ 8 | 9 | export * from './twilio_adapter'; 10 | export * from './botworker'; 11 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-twilio-sms/tests/TwilioAdapter.tests.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const { TwilioAdapter } = require('../'); 3 | 4 | describe('TwilioAdapter', function() { 5 | 6 | let adapter; 7 | 8 | beforeEach(function () { 9 | adapter = new TwilioAdapter({ 10 | twilio_number: '14155551212', 11 | account_sid: 'AC123123', 12 | auth_token: '123123', 13 | }); 14 | }); 15 | 16 | it('should not construct without required parameters', function () { 17 | assert.throws(function () { let adapter = new TwilioAdapter({}) }, 'Foo'); 18 | }); 19 | 20 | it('should create a TwilioAdapter object', function () { 21 | assert((adapter instanceof TwilioAdapter), 'Adapter is wrong type'); 22 | }); 23 | 24 | }); 25 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-twilio-sms/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2015", 4 | "module": "commonjs", 5 | "declaration": true, 6 | "sourceMap": true, 7 | "outDir": "./lib", 8 | "rootDir": "./src", 9 | "types" : ["node"], 10 | "lib": [ 11 | "es5", 12 | "es2015", 13 | "es2016.array.include", 14 | "esnext.asynciterable", 15 | "dom" 16 | ] 17 | }, 18 | "include": [ 19 | "src/**/*" 20 | ] 21 | } -------------------------------------------------------------------------------- /packages/botbuilder-adapter-web/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "extends": "standard", 3 | "rules": { 4 | "semi": [2, "always"], 5 | "indent": [2, 4], 6 | "no-return-await": 0, 7 | "camelcase": 0, 8 | "no-unused-vars": 0, 9 | "@typescript-eslint/ban-ts-ignore": 1, 10 | "@typescript-eslint/no-object-literal-type-assertion": 0, 11 | "@typescript-eslint/indent": 0, 12 | "@typescript-eslint/explicit-member-accessibility": 1, 13 | "space-before-function-paren": [2, { 14 | "named": "never", 15 | "anonymous": "never", 16 | "asyncArrow": "always" 17 | }], 18 | "template-curly-spacing": [2, "always"] 19 | } 20 | }; -------------------------------------------------------------------------------- /packages/botbuilder-adapter-web/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .env 3 | lib/ 4 | .nyc_output/ 5 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-web/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # botbuilder-adapter-web changelog 2 | 3 | # 1.0.9 4 | 5 | * Update dependencies to Botkit 4.10, Bot Framework 4.10 6 | 7 | * Fix to websocket ping call. [Issue #2003](https://github.com/howdyai/botkit/issues/2003) 8 | 9 | # 1.0.8 10 | 11 | * Update dependencies to Botkit 4.9, Bot Framework 4.9 12 | 13 | # 1.0.6 14 | 15 | * Update dependencies on Bot Framework and Botkit 16 | * Fix syntax error in sample client - Thanks @naktibalda! [#1881](https://github.com/howdyai/botkit/pull/1881) 17 | 18 | # 1.0.5 19 | 20 | * Update dependencies (Bot Framework to 4.6, Botkit to 4.6) 21 | 22 | # 1.0.4 23 | 24 | * Update dependencies (Bot Framework to 4.5.2, Botkit to 4.5, WS to 7.1.1) 25 | 26 | # 1.0.3 27 | 28 | * Fix - will not attempt to send a message if socket is closed. - Thanks [@naktibalda](https://github.com/Naktibalda) for [the fix](https://github.com/howdyai/botkit/pull/1657) 29 | * Add getConnection method() - Thanks to [@naktibalda](https://github.com/Naktibalda) for [the contribution](https://github.com/howdyai/botkit/pull/1666) 30 | 31 | # 1.0.2 32 | 33 | * Add [isConnected()](https://botkit.ai/docs/v4/reference/web.html#isconnected) method to WebAdapter. This allows a bot to check the status of a (potentially stale) websocket connection before sending messages. Thanks to [@Naktibalda](https://github.com/Naktibalda) for [this contribution](https://github.com/howdyai/botkit/pull/1644). 34 | 35 | # 1.0.1 36 | 37 | This was the first public release! -------------------------------------------------------------------------------- /packages/botbuilder-adapter-web/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-web/client/css/embed.css: -------------------------------------------------------------------------------- 1 | #embedded_messenger { 2 | position: fixed; 3 | z-index: 1000; 4 | bottom: -400px; 5 | right: 2rem; 6 | height: 434px; 7 | transition: 0.5s ease-in-out bottom; 8 | } 9 | #embedded_messenger.active { 10 | bottom: 0; 11 | } 12 | #embedded_messenger iframe { 13 | height: 400px; 14 | width: 100%; 15 | border: 0; 16 | } 17 | #embedded_messenger #message_header { 18 | background: #000; 19 | padding: 0.5rem 1rem; 20 | color: #FFF; 21 | } 22 | 23 | /*# sourceMappingURL=embed.css.map */ 24 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-web/client/css/embed.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sourceRoot":"","sources":["../../sass/embed.scss"],"names":[],"mappings":"AAEA;EAEE;EACA;EAEA;EACA;EAEA;EACA;;AAEA;EACE;;AAGF;EACE,QAlBK;EAmBL;EACA;;AAGF;EACE;EACA;EACA","file":"embed.css"} -------------------------------------------------------------------------------- /packages/botbuilder-adapter-web/client/css/styles.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sourceRoot":"","sources":["../../sass/styles.scss","../../sass/_botkit.scss","../../sass/_chat.scss","../../sass/_home.scss"],"names":[],"mappings":"AAAA;ACSA;EACI;;;AAGJ;AAAA;EAEI;EACA;EACA;EACA;EACA;;;AAGJ;EAEI;EACA;EACA;;AAxBA;EACI;EACA;EACA;;;AAwBR;EAEI;EACA;EACA;;AA/BA;EACI;EACA;EACA;;AA8BJ;AAAA;AAAA;EAGI;;;AAIR;EACI;;;AAGJ;EACI;EACA;;AAEA;EACI;EACA;;;AAKR;EACI,OA1DY;;;AA6DhB;EACI;EACA;;;AAIA;EACI;EACA;;;AAIR;EACI;EACA;EACA;EACA;EACA;;AAEA;AAAA;EAEI;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAGJ;EACI;EACA,OArGI;;;AA0GhB;EACI;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;;AAEA;EAEI;;;AD/HR;AEIA;EACI,YAPS;EAQT;EACA;AAEA;AAAA;EAEA;EACA;AACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAEJ;EACI;;AAEJ;EACI;;AAIF;EACE;;AAEF;EACE;EACA;EACA;EACA;;AAIJ;EACE;EACA;EAEA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAIL;EACG;EACA;EACA;EACA;;AAED;EACG;EACA;;AAIN;EACI;EACA;;AACA;EACI;EACA;EACA;EACA;;AAEJ;EACG;EACA;EACA;EACA;EACA;EACA;;AAIP;EACI;EACA;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA,YA1GmB;EA2GnB,OA1Ga;EA2Gb;EACA;EACA;EACA;;AAIJ;EAEE,YArHqB;EAsHrB,OArHe;EAsHf;EACA;EACA;;AAEA;EACE;EACA;;AAKF;EACE;EACA;EACA,cAvIS;EAwIT;EACA,OAzIS;EA0IT;EACA;EACA;EACA;EACA;EACA;;AAIJ;EACI;EACA;;AAGJ;EACI;;AAGJ;EACI;EAEA,YD/JU;ECgKV,OA3Je;;AA+JnB;EACI;EACA;EACA;EACA;AAAmC;;AAEnC;EACI;EACA;EACA;;AACA;EACI;EACA;EACA;;AAIR;EACG;EACA;EACA;EACA,ODzLO;EC0LP;EACA;EACA;EACA;;AAEA;EACE,YDhMK;ECiML;;;AAQX;AACA;EACE;EACA;EACA;;AACA;EACE;EACA;EACA;EACA;EACA,kBAhNe;EAiNf;EACA;EACA;;AAEE;EACE;;AADF;EACE;;AADF;EACE;;;AAMR;EACE;IACE;;;AF3NJ;AGNA;EAEI;EACA;EACA;;AFFA;EACI;EACA;EACA;;;AEER;EACI;EACA;EACA;EACA;EAOA;;AALA;EACI;EACA;EACA;;;AAKR;EACI","file":"styles.css"} -------------------------------------------------------------------------------- /packages/botbuilder-adapter-web/client/embed.js: -------------------------------------------------------------------------------- 1 | var Botkit = { 2 | 3 | setCookie: function(cname, cvalue, exdays) { 4 | var d = new Date(); 5 | d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000)); 6 | var expires = "expires=" + d.toUTCString(); 7 | document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/"; 8 | }, 9 | getCookie: function(cname) { 10 | var name = cname + "="; 11 | var decodedCookie = decodeURIComponent(document.cookie); 12 | var ca = decodedCookie.split(';'); 13 | for (var i = 0; i < ca.length; i++) { 14 | var c = ca[i]; 15 | while (c.charAt(0) == ' ') { 16 | c = c.substring(1); 17 | } 18 | if (c.indexOf(name) == 0) { 19 | return c.substring(name.length, c.length); 20 | } 21 | } 22 | return ""; 23 | }, 24 | active: false, 25 | activate: function() { 26 | this.active = true; 27 | if (this.container) { 28 | this.container.className = 'active'; 29 | } 30 | this.setCookie('botkit_messenger_active', this.active); 31 | }, 32 | deactivate: function() { 33 | this.active = false; 34 | if (this.container) { 35 | this.container.className = ''; 36 | } 37 | this.setCookie('botkit_messenger_active', this.active); 38 | }, 39 | toggle: function() { 40 | if (this.active) { 41 | this.deactivate(); 42 | } else { 43 | this.activate(); 44 | } 45 | }, 46 | trigger: function(event) { 47 | this.chatClient.postMessage(event, '*'); 48 | }, 49 | receiveMessage: function(message) { 50 | // message contains the following fields: 51 | // message.data, message.origin, message.source 52 | 53 | switch (message.data.name) { 54 | case 'booted': 55 | Botkit.trigger({ 56 | name: 'connect', 57 | user: Botkit.current_user ? Botkit.current_user : null, 58 | }); 59 | 60 | if (Botkit.getCookie('botkit_messenger_active') == 'true') { 61 | Botkit.activate(); 62 | } 63 | console.log('Embedded Botkit: Ready!'); 64 | break; 65 | case 'connected': 66 | // console.log('100% CONNECTED AND READY TO GO'); 67 | break; 68 | } 69 | }, 70 | triggerScript: function(script, thread) { 71 | 72 | this.trigger({ 73 | type: 'event', 74 | name: 'trigger', 75 | script: script, 76 | thread: thread, 77 | }); 78 | }, 79 | identifyUser: function(user) { 80 | 81 | // user should contain any of the following: 82 | // id, email, name, first_name, last_name, full_name, gender, timezone, timezone_offset 83 | 84 | this.current_user = user; 85 | 86 | this.trigger({ 87 | type: 'event', 88 | name: 'identify', 89 | user: user, 90 | }); 91 | 92 | 93 | }, 94 | boot: function(user) { 95 | var that = this; 96 | 97 | that.container = document.getElementById('embedded_messenger'); 98 | that.header = document.getElementById('messenger_header'); 99 | that.chatClient = document.getElementById('botkit_client').contentWindow; 100 | 101 | if (user) { 102 | that.current_user = user; 103 | } 104 | 105 | if (!that.chatClient) { 106 | console.error('Cannot find Botkit chat client iframe. Make sure your iframe has the id #botkit_client'); 107 | } 108 | 109 | window.addEventListener('message', that.receiveMessage, false); 110 | 111 | return this; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-web/client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Botkit Anywhere 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 |
14 |
15 | Disconnected... reconnecting! 16 |
17 |
18 | Offline! Reload to reconnect. 19 |
20 |
21 | Powered by Botkit Logo Botkit 22 |
23 |
24 |
25 |
26 |
27 | {{#if message.isTyping}} 28 |
29 | 30 | 31 | 32 |
33 | {{/if}} 34 | {{{message.html}}} 35 | 36 | {{#if message.open_link}} 37 | {{#if message.link_title}}{{message.link_title}}{{else}}{{message.open_link}}{{/if}} 38 | {{/if}} 39 |
40 | {{#message.files}} 41 |
42 | {{#if image}} 43 | {{{url}}} 44 | {{else}} 45 | {{{url}}} 46 | {{/if}} 47 |
48 | {{/message.files}} 49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | 57 | 58 |
59 |
60 |
61 |
62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-web/client/sass/_botkit.scss: -------------------------------------------------------------------------------- 1 | $botkit_purple: #a795ef; 2 | @mixin clearfix { 3 | &:after { 4 | content: ""; 5 | display: table; 6 | clear: both; 7 | } 8 | } 9 | 10 | * { 11 | box-sizing: border-box; 12 | } 13 | 14 | body, 15 | html { 16 | margin: 0; 17 | padding: 0; 18 | font-size: 18px; 19 | background-color: #FFF; 20 | font-family: 'helvetica', sans-serif; 21 | } 22 | 23 | .wrapper { 24 | @include clearfix; 25 | position: relative; 26 | max-width: 1000px; 27 | margin: 0 auto; 28 | } 29 | 30 | .box { 31 | @include clearfix; 32 | border: 2px solid #CCC; 33 | padding: 1rem calc(1rem - 2px); 34 | margin-bottom: 1rem; 35 | 36 | h1, 37 | h2, 38 | h3 { 39 | margin-top: 0; 40 | } 41 | } 42 | 43 | footer { 44 | text-align: center; 45 | } 46 | 47 | .hero { 48 | text-align: center; 49 | padding: 2rem; 50 | 51 | h1 { 52 | font-size: 4rem; 53 | margin: 0; 54 | 55 | } 56 | } 57 | 58 | a { 59 | color: $botkit_purple; 60 | } 61 | 62 | .copyurl { 63 | width: 100%; 64 | font-size: 1.25rem; 65 | } 66 | 67 | div.input { 68 | label { 69 | font-weight: bold; 70 | font-size: smaller; 71 | } 72 | } 73 | 74 | .addon { 75 | display: flex; 76 | border: 1px solid #999; 77 | border-radius: 6px; 78 | padding: 5px; 79 | background: #F0F0F0; 80 | 81 | input, 82 | textarea { 83 | flex-grow: 1; 84 | border: 0; 85 | background: transparent; 86 | } 87 | 88 | button { 89 | flex-grow: 0; 90 | background: transparent; 91 | border: 1px solid #999; 92 | border-radius: 6px; 93 | font-weight: bold; 94 | 95 | &.textarea { 96 | align-self: flex-start; 97 | padding: 0.5rem; 98 | } 99 | 100 | &:hover { 101 | background: #FFF; 102 | color: $botkit_purple; 103 | } 104 | } 105 | } 106 | 107 | div.hr { 108 | border: 1px dashed #ccc; 109 | width: 10%; 110 | margin: 4rem auto; 111 | height: 1px; 112 | } 113 | 114 | a.button { 115 | border: 2px solid $botkit_purple; 116 | font-weight: bold; 117 | // font-size: 4rem; 118 | margin: 0; 119 | border-radius: 3px; 120 | display: inline-block; 121 | padding: 0.5rem 2rem; 122 | text-align: center; 123 | text-decoration: none; 124 | // color: #FFF; 125 | box-shadow: 5px 5px 5px rgba(0,0,0,0.2); 126 | background-color: #FFF; 127 | transition: box-shadow 0.1s linear; 128 | 129 | &:hover { 130 | // background-color: rgba($botkit_purple, 0.1); 131 | box-shadow: 1px 1px 5px rgba(0,0,0,0.1); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-web/client/sass/_home.scss: -------------------------------------------------------------------------------- 1 | #home { 2 | @include clearfix; 3 | position: relative; 4 | max-width: 650px; 5 | margin: auto; 6 | } 7 | 8 | #homepage_bot { 9 | width: 400px; 10 | height: 450px; 11 | float: left; 12 | border: 5px solid #333; 13 | 14 | iframe { 15 | border: 0; 16 | height: 100%; 17 | width: 100%; 18 | } 19 | box-shadow: 5px 5px 5px rgba(0,0,0,0.5); 20 | } 21 | 22 | #welcome { 23 | margin-left: 440px; 24 | } 25 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-web/client/sass/embed.scss: -------------------------------------------------------------------------------- 1 | $height: 400px; 2 | 3 | #embedded_messenger { 4 | 5 | position: fixed; 6 | z-index: 1000; 7 | 8 | bottom: -$height; 9 | right: 2rem; 10 | 11 | height: $height + 34; 12 | transition: 0.5s ease-in-out bottom; 13 | 14 | &.active { 15 | bottom: 0; 16 | } 17 | 18 | iframe { 19 | height: $height; 20 | width: 100%; 21 | border: 0; 22 | } 23 | 24 | #message_header { 25 | background: #000; 26 | padding: 0.5rem 1rem; 27 | color: #FFF; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-web/client/sass/styles.scss: -------------------------------------------------------------------------------- 1 | /* shared botkit ui styles */ 2 | @import "_botkit"; 3 | 4 | /* chat client */ 5 | @import "_chat"; 6 | 7 | /* special styles for homepage */ 8 | @import "_home"; 9 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-web/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "botbuilder-adapter-web", 3 | "version": "1.0.10", 4 | "description": "Connect Botkit or BotBuilder to the Web", 5 | "main": "./lib/index.js", 6 | "typings": "./lib/index.d.ts", 7 | "files": [ 8 | "/lib", 9 | "/src", 10 | "/client" 11 | ], 12 | "scripts": { 13 | "build": "tsc", 14 | "test": "tsc ; nyc mocha tests/*.tests.js", 15 | "eslint": "./node_modules/.bin/eslint --fix src/*", 16 | "pack": "npm pack" 17 | }, 18 | "author": "Microsoft Corp.", 19 | "license": "MIT", 20 | "keywords": [ 21 | "webchat", 22 | "websocket", 23 | "botkit", 24 | "botbuilder", 25 | "botframework", 26 | "bots", 27 | "chatbots", 28 | "azure" 29 | ], 30 | "homepage": "https://github.com/howdyai/botkit/blob/master/packages/botbuilder-adapter-web#readme", 31 | "bugs": { 32 | "url": "https://github.com/howdyai/botkit/issues" 33 | }, 34 | "repository": { 35 | "type": "git", 36 | "url": "https://github.com/howdyai/botkit.git" 37 | }, 38 | "dependencies": { 39 | "botkit": "^4.15.0", 40 | "botbuilder": "^4.15.0", 41 | "debug": "^4.1.0", 42 | "url": "^0.11.0", 43 | "ws": "^7.3.1" 44 | }, 45 | "devDependencies": { 46 | "eslint": "^8.3.0", 47 | "eslint-config-standard": "^16.0.3", 48 | "eslint-plugin-import": "^2.25.3", 49 | "eslint-plugin-node": "^11.1.0", 50 | "eslint-plugin-promise": "^5.1.1", 51 | "eslint-plugin-standard": "^4.0.1" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-web/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module botbuilder-adapter-web 3 | */ 4 | /** 5 | * Copyright (c) Microsoft Corporation. All rights reserved. 6 | * Licensed under the MIT License. 7 | */ 8 | 9 | export * from './web_adapter'; 10 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-web/tests/WebAdapter.tests.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const { WebAdapter } = require('../'); 3 | 4 | describe('WebAdapter', function() { 5 | 6 | let adapter; 7 | 8 | beforeEach(function () { 9 | adapter = new WebAdapter({ 10 | }); 11 | }); 12 | 13 | it('should contruct without any parameters (none are required)', function () { 14 | assert.doesNotThrow(function () { let adapter = new WebAdapter({}); }, 'Foo'); 15 | }); 16 | 17 | it('should create a WebAdapter object', function () { 18 | assert((adapter instanceof WebAdapter), 'Adapter is wrong type'); 19 | }); 20 | 21 | }); 22 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2015", 4 | "module": "commonjs", 5 | "declaration": true, 6 | "sourceMap": true, 7 | "outDir": "./lib", 8 | "rootDir": "./src", 9 | "types" : ["node"], 10 | "lib": [ 11 | "es5", 12 | "es2015", 13 | "es2016.array.include", 14 | "esnext.asynciterable", 15 | "dom" 16 | ] 17 | }, 18 | "include": [ 19 | "src/**/*" 20 | ] 21 | } -------------------------------------------------------------------------------- /packages/botbuilder-adapter-webex/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "extends": "standard", 3 | "rules": { 4 | "semi": [2, "always"], 5 | "indent": [2, 4], 6 | "no-return-await": 0, 7 | "camelcase": 0, 8 | "no-unused-vars": 0, 9 | "@typescript-eslint/ban-ts-ignore": 1, 10 | "@typescript-eslint/no-object-literal-type-assertion": 0, 11 | "@typescript-eslint/indent": 0, 12 | "@typescript-eslint/explicit-member-accessibility": 1, 13 | "space-before-function-paren": [2, { 14 | "named": "never", 15 | "anonymous": "never", 16 | "asyncArrow": "always" 17 | }], 18 | "template-curly-spacing": [2, "always"] 19 | } 20 | }; -------------------------------------------------------------------------------- /packages/botbuilder-adapter-webex/.gitignore: -------------------------------------------------------------------------------- 1 | .nyc_output/ 2 | node_modules/ 3 | .env 4 | lib/ -------------------------------------------------------------------------------- /packages/botbuilder-adapter-webex/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # botbuilder-adapter-webex changelog 2 | 3 | # 1.0.9 4 | 5 | * Test for presence of channelData before accessing it. Thanks [@viveksyngh](https://github.com/viveksyngh) for the [pull request](https://github.com/howdyai/botkit/pull/2010) 6 | 7 | * Update dependencies to Botkit 4.10, Bot Framework 4.10 8 | 9 | 10 | 11 | # 1.0.8 12 | 13 | * Update dependencies to Botkit 4.9, Bot Framework 4.9 14 | * New: Add abilbity to start conversations or reply in a thread. Thanks to [@billyzoellers](https://github.com/billyzoellers) for the [pull request](https://github.com/howdyai/botkit/pull/1942) 15 | 16 | # 1.0.6 17 | 18 | * Fix issue where empty files field would cause issues. Thanks to [@viveksyngh](https://github.com/viveksyngh) - [PR #1906](https://github.com/howdyai/botkit/pull/1906) 19 | * Update to latest Webex API client library. 20 | 21 | 22 | # 1.0.5 23 | 24 | * Update to latest Webex API client library. 25 | * Fix to mention stripping to better support Webex web client formatting 26 | * Update dependencies (Bot Framework to 4.6, Botkit to 4.6) 27 | 28 | # 1.0.3 29 | 30 | * Add support for [Adaptive Cards](https://developer.webex.com/blog/new-buttons-cards-webex-teams) thanks to [@darrenparkinson](https://github.com/howdyai/botkit/pull/1760) 31 | * Replace `ciscospark` package with `webex` package, thanks to [@teamup](https://github.com/howdyai/botkit/pull/1748) 32 | 33 | Developers who wish to use this brand new feature should add the following lines to their bot.js file 34 | in order to create a dedicated webhook for receiving card submissions from the Webex client. Note that this 35 | is necessary due to a bug in the Webex webhook service, and will be removed from future versions. 36 | 37 | ``` 38 | controller.ready(async function() { 39 | await controller.adapter.registerAdaptiveCardWebhookSubscription('/api/messages'); 40 | }); 41 | ``` 42 | 43 | Once enabled, your bot will receive `attachmentActions` events with `message.inputs` set to include values from the card. 44 | 45 | # 1.0.2 46 | 47 | * Update dependencies (Bot Framework to 4.5.2, Botkit to 4.5) 48 | * Fix for file attachments 49 | 50 | # 1.0.1 51 | 52 | * 1:1 messages between bot and user will now emit `direct_message` events instead of `message` events 53 | * Messages will now have `orgId`, `appId` and `actorId` fields 54 | * Add `enable_incomplete` option to allow adapter to start without a complete config. 55 | 56 | # 1.0.0 57 | 58 | First release 59 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-webex/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-webex/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "botbuilder-adapter-webex", 3 | "version": "1.0.10", 4 | "description": "Connect Botkit or BotBuilder to Webex Teams", 5 | "main": "./lib/index.js", 6 | "typings": "./lib/index.d.ts", 7 | "files": [ 8 | "/lib", 9 | "/src" 10 | ], 11 | "scripts": { 12 | "build": "tsc", 13 | "test": "tsc ; nyc mocha tests/*.tests.js", 14 | "eslint": "./node_modules/.bin/eslint --fix src/*", 15 | "pack": "npm pack" 16 | }, 17 | "author": "Microsoft Corp.", 18 | "license": "MIT", 19 | "keywords": [ 20 | "webex", 21 | "botkit", 22 | "botbuilder", 23 | "botframework", 24 | "bots", 25 | "chatbots", 26 | "azure" 27 | ], 28 | "homepage": "https://github.com/howdyai/botkit/blob/master/packages/botbuilder-adapter-webex#readme", 29 | "bugs": { 30 | "url": "https://github.com/howdyai/botkit/issues" 31 | }, 32 | "repository": { 33 | "type": "git", 34 | "url": "https://github.com/howdyai/botkit.git" 35 | }, 36 | "dependencies": { 37 | "botbuilder": "^4.15.0", 38 | "botkit": "^4.15.0", 39 | "debug": "^4.1.0", 40 | "url": "^0.11.0", 41 | "webex": "^1.80.148" 42 | }, 43 | "devDependencies": { 44 | "eslint": "^8.3.0", 45 | "eslint-config-standard": "^16.0.3", 46 | "eslint-plugin-import": "^2.25.3", 47 | "eslint-plugin-node": "^11.1.0", 48 | "eslint-plugin-promise": "^5.1.1", 49 | "eslint-plugin-standard": "^4.0.1" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-webex/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module botbuilder-adapter-webex 3 | */ 4 | /** 5 | * Copyright (c) Microsoft Corporation. All rights reserved. 6 | * Licensed under the MIT License. 7 | */ 8 | 9 | export * from './webex_adapter'; 10 | export * from './botworker'; 11 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-webex/tests/WebexAdapter.tests.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const { WebexAdapter } = require('../'); 3 | 4 | describe('WebexAdapter', function() { 5 | 6 | let adapter; 7 | 8 | beforeEach(function () { 9 | adapter = new WebexAdapter({ 10 | access_token: '123123123', 11 | secret: '123', 12 | public_address: 'https://fakebot.com' 13 | }); 14 | }); 15 | 16 | it('should not construct without required parameters', function () { 17 | assert.throws(function () { let adapter = new WebexAdapter({}) }, 'Foo'); 18 | }); 19 | 20 | it('should create a WebexAdapter object', function () { 21 | assert((adapter instanceof WebexAdapter), 'Adapter is wrong type'); 22 | }); 23 | 24 | }); 25 | -------------------------------------------------------------------------------- /packages/botbuilder-adapter-webex/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2015", 4 | "module": "commonjs", 5 | "declaration": true, 6 | "sourceMap": true, 7 | "outDir": "./lib", 8 | "rootDir": "./src", 9 | "types" : ["node"], 10 | "lib": [ 11 | "es5", 12 | "es2015", 13 | "es2016.array.include", 14 | "esnext.asynciterable", 15 | "dom" 16 | ] 17 | }, 18 | "include": [ 19 | "src/**/*" 20 | ] 21 | } -------------------------------------------------------------------------------- /packages/botkit-plugin-cms/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "extends": "standard", 3 | "rules": { 4 | "semi": [2, "always"], 5 | "indent": [2, 4], 6 | "no-return-await": 0, 7 | "camelcase": 0, 8 | "no-unused-vars": 0, 9 | "@typescript-eslint/ban-ts-ignore": 1, 10 | "@typescript-eslint/no-object-literal-type-assertion": 0, 11 | "@typescript-eslint/indent": 0, 12 | "@typescript-eslint/explicit-member-accessibility": 1, 13 | "space-before-function-paren": [2, { 14 | "named": "never", 15 | "anonymous": "never", 16 | "asyncArrow": "always" 17 | }], 18 | "template-curly-spacing": [2, "always"] 19 | } 20 | }; -------------------------------------------------------------------------------- /packages/botkit-plugin-cms/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | lib/ -------------------------------------------------------------------------------- /packages/botkit-plugin-cms/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # botkit-plugin-cms 2 | 3 | # botkit-plugin-cms changelog 4 | 5 | # 1.0.3 6 | 7 | * Emit a better error when an invalid token has been provided 8 | * Update dependencies (Bot Framework to 4.6, Botkit to 4.6) 9 | 10 | 11 | # 1.0.2 12 | 13 | * Update dependencies (Bot Framework to 4.5.2, Botkit to 4.5) 14 | * Improvements to reliability of the `uri` parameter on the constructor. 15 | 16 | 17 | # 1.0.1 18 | 19 | * Fix critical issue that causes CMS-powered dialogs to fail to load. 20 | 21 | # 1.0.0 22 | 23 | this was the initial release -------------------------------------------------------------------------------- /packages/botkit-plugin-cms/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /packages/botkit-plugin-cms/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "botkit-plugin-cms", 3 | "version": "1.0.4", 4 | "description": "Extend Botkit with access to botkit-cms", 5 | "main": "./lib/index.js", 6 | "typings": "./lib/index.d.ts", 7 | "files": [ 8 | "/lib", 9 | "/src" 10 | ], 11 | "scripts": { 12 | "build": "tsc", 13 | "eslint": "./node_modules/.bin/eslint --fix src/*" 14 | }, 15 | "author": "benbrown@gmail.com", 16 | "license": "MIT", 17 | "keywords": [ 18 | "botkit", 19 | "bots", 20 | "chatbots" 21 | ], 22 | "homepage": "https://github.com/howdyai/botkit/blob/master/packages/botkit-plugin-cms#readme", 23 | "bugs": { 24 | "url": "https://github.com/howdyai/botkit/issues" 25 | }, 26 | "repository": { 27 | "type": "git", 28 | "url": "https://github.com/howdyai/botkit.git" 29 | }, 30 | "dependencies": { 31 | "botkit": "^4.8.0", 32 | "debug": "^4.1.0" 33 | }, 34 | "devDependencies": { 35 | "@types/express": "^4.17.2", 36 | "@types/node": "^10.17.5", 37 | "eslint": "^8.3.0", 38 | "eslint-config-standard": "^16.0.3", 39 | "eslint-plugin-import": "^2.25.3", 40 | "eslint-plugin-node": "^11.1.0", 41 | "eslint-plugin-promise": "^5.1.1", 42 | "eslint-plugin-standard": "^4.0.1" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/botkit-plugin-cms/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module botkit-plugin-cms 3 | */ 4 | /** 5 | * Copyright (c) Microsoft Corporation. All rights reserved. 6 | * Licensed under the MIT License. 7 | */ 8 | 9 | export * from './cms'; 10 | -------------------------------------------------------------------------------- /packages/botkit-plugin-cms/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2015", 4 | "module": "commonjs", 5 | "declaration": true, 6 | "sourceMap": true, 7 | "outDir": "./lib", 8 | "rootDir": "./src", 9 | "types" : ["node"], 10 | "lib": [ 11 | "es5", 12 | "es2015", 13 | "es2016.array.include", 14 | "esnext.asynciterable", 15 | "dom" 16 | ] 17 | }, 18 | "include": [ 19 | "src/**/*" 20 | ] 21 | } -------------------------------------------------------------------------------- /packages/botkit/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "extends": "standard", 3 | "rules": { 4 | "semi": [2, "always"], 5 | "indent": [2, 4], 6 | "no-return-await": 0, 7 | "camelcase": 0, 8 | "no-unused-vars": 0, 9 | "@typescript-eslint/no-object-literal-type-assertion": 0, 10 | "@typescript-eslint/indent": 0, 11 | "@typescript-eslint/explicit-member-accessibility": 1, 12 | "space-before-function-paren": [2, { 13 | "named": "never", 14 | "anonymous": "never", 15 | "asyncArrow": "always" 16 | }], 17 | "template-curly-spacing": [2, "always"] 18 | } 19 | }; -------------------------------------------------------------------------------- /packages/botkit/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | lib/ 3 | .nyc_output -------------------------------------------------------------------------------- /packages/botkit/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /packages/botkit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "botkit", 3 | "version": "4.15.0", 4 | "description": "Building Blocks for Building Bots", 5 | "main": "lib/index.js", 6 | "typings": "./lib/index.d.ts", 7 | "files": [ 8 | "/lib", 9 | "/src" 10 | ], 11 | "scripts": { 12 | "build": "tsc", 13 | "eslint": "./node_modules/.bin/eslint --fix src/*", 14 | "test": "tsc ; nyc mocha tests/*.tests.js", 15 | "pack": "npm pack" 16 | }, 17 | "author": "benbrown@gmail.com", 18 | "license": "MIT", 19 | "keywords": [ 20 | "botkit", 21 | "botbuilder", 22 | "botframework", 23 | "bots", 24 | "chatbots" 25 | ], 26 | "homepage": "https://github.com/howdyai/botkit/blob/master/packages/botkit#readme", 27 | "bugs": { 28 | "url": "https://github.com/howdyai/botkit/issues" 29 | }, 30 | "repository": { 31 | "type": "git", 32 | "url": "https://github.com/howdyai/botkit.git" 33 | }, 34 | "dependencies": { 35 | "body-parser": "^1.19.0", 36 | "botbuilder": "^4.15.0", 37 | "botbuilder-core": "^4.15.0", 38 | "botbuilder-dialogs": "^4.15.0", 39 | "botframework-connector": "^4.15.0", 40 | "debug": "^4.1.0", 41 | "express": "^4.17.1", 42 | "mustache": "^4.0.1", 43 | "path": "^0.12.7", 44 | "ware": "^1.3.0" 45 | }, 46 | "devDependencies": { 47 | "@types/debug": "^4.1.5", 48 | "@types/express": "^4.17.2", 49 | "@types/node": "^10.17.5", 50 | "eslint": "^8.3.0", 51 | "eslint-config-standard": "^16.0.3", 52 | "eslint-plugin-import": "^2.25.3", 53 | "eslint-plugin-node": "^11.1.0", 54 | "eslint-plugin-promise": "^5.1.1", 55 | "eslint-plugin-standard": "^4.0.1" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/botkit/src/adapter.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module botkit 3 | */ 4 | /** 5 | * Copyright (c) Microsoft Corporation. All rights reserved. 6 | * Licensed under the MIT License. 7 | */ 8 | import { BotFrameworkAdapter, TurnContext, TeamsInfo, ChannelInfo } from 'botbuilder'; 9 | import { ConnectorClient, TokenApiClient } from 'botframework-connector'; 10 | import { TeamsBotWorker } from './teamsHelpers'; 11 | import * as os from 'os'; 12 | 13 | const pjson: any = require('../package.json'); // eslint-disable-line @typescript-eslint/no-var-requires 14 | 15 | // Retrieve additional information, i.e., host operating system, host OS release, architecture, Node.js version 16 | const ARCHITECTURE: any = os.arch(); 17 | const TYPE: any = os.type(); 18 | const RELEASE: any = os.release(); 19 | const NODE_VERSION: any = process.version; 20 | const USER_AGENT: string = `Microsoft-BotFramework/3.1 Botkit/${ pjson.version } ` + 21 | `(Node.js,Version=${ NODE_VERSION }; ${ TYPE } ${ RELEASE }; ${ ARCHITECTURE })`; 22 | 23 | /** 24 | * This class extends the [BotFrameworkAdapter](https://docs.microsoft.com/en-us/javascript/api/botbuilder/botframeworkadapter?view=botbuilder-ts-latest) with a few additional features to support Microsoft Teams. 25 | * * Changes userAgent to reflect Botkit instead of BotBuilder 26 | * * Adds getChannels() (MS Teams) 27 | * * Adds middleware for adjusting location of tenant id field (MS Teams) 28 | */ 29 | export class BotkitBotFrameworkAdapter extends BotFrameworkAdapter { 30 | public botkit_worker = TeamsBotWorker; 31 | 32 | /** 33 | * Allows for mocking of the connector client in unit tests. 34 | * Overridden by Botkit in order to change userAgent. 35 | * @ignore 36 | * @param serviceUrl Clients service url. 37 | */ 38 | public createConnectorClient(serviceUrl: string): ConnectorClient { 39 | const client: ConnectorClient = new ConnectorClient(this.credentials, { baseUri: serviceUrl, userAgent: USER_AGENT }); 40 | return client; 41 | } 42 | 43 | /** 44 | * Allows for mocking of the OAuth API Client in unit tests. 45 | * Overridden by Botkit in order to change userAgent. 46 | * @ignore 47 | * @param serviceUrl Clients service url. 48 | */ 49 | protected createTokenApiClient(serviceUrl: string): TokenApiClient { 50 | const client = new TokenApiClient(this.credentials, { baseUri: serviceUrl, userAgent: USER_AGENT }); 51 | return client; 52 | } 53 | 54 | /** 55 | * Get the list of channels in a MS Teams team. 56 | * Can only be called with a TurnContext that originated in a team conversation - 1:1 conversations happen _outside a team_ and thus do not contain the required information to call this API. 57 | * @param context A TurnContext object representing a message or event from a user in Teams 58 | * @returns an array of channels in the format [{name: string, id: string}] 59 | */ 60 | public async getChannels(context: TurnContext): Promise { 61 | if (context.activity.channelData && context.activity.channelData.team) { 62 | const channels = await TeamsInfo.getTeamChannels(context); 63 | return channels ? channels.map((c) => { if (!c.name) { c.name = 'General'; } return c; }) : []; 64 | } else { 65 | console.error('getChannels cannot be called from unknown team'); 66 | return []; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /packages/botkit/src/conversationState.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module botkit 3 | */ 4 | /** 5 | * Copyright (c) Microsoft Corporation. All rights reserved. 6 | * Licensed under the MIT License. 7 | */ 8 | import { Activity, ConversationState, TurnContext } from 'botbuilder'; 9 | 10 | /** 11 | * A customized version of [ConversationState](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/conversationstate?view=botbuilder-ts-latest) that overide the [getStorageKey](#getStorageKey) method to create a more complex key value. 12 | * This allows Botkit to automatically track conversation state in scenarios where multiple users are present in a single channel, 13 | * or when threads or sub-channels parent channel that would normally collide based on the information defined in the conversation address field. 14 | * Note: This is used automatically inside Botkit and developers should not need to directly interact with it. 15 | * @ignore 16 | */ 17 | export class BotkitConversationState extends ConversationState { 18 | public getStorageKey(context: TurnContext): string | undefined { 19 | const activity: Activity = context.activity; 20 | const channelId: string = activity.channelId; 21 | if (!activity.conversation || !activity.conversation.id) { 22 | throw new Error('missing activity.conversation'); 23 | } 24 | 25 | // create a combo key by sorting all the fields in the conversation address and combining them all 26 | // mix in user id as well, because conversations are between the bot and a single user 27 | const conversationId: string = Object.keys(activity.conversation).filter((key) => { return key !== 'properties'; }).sort().map((key) => activity.conversation[key]).filter((val) => val !== '' && val !== null && typeof val !== 'undefined').join('-') + '-' + activity.from.id; 28 | 29 | if (!channelId) { 30 | throw new Error('missing activity.channelId'); 31 | } 32 | 33 | if (!conversationId) { 34 | throw new Error('missing activity.conversation.id'); 35 | } 36 | 37 | // eslint-disable-next-line @typescript-eslint/ban-ts-ignore 38 | // @ts-ignore namespace is technically private 39 | return `${ channelId }/conversations/${ conversationId }/${ this.namespace }`; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/botkit/src/dialogWrapper.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module botkit 3 | */ 4 | /** 5 | * Copyright (c) Microsoft Corporation. All rights reserved. 6 | * Licensed under the MIT License. 7 | */ 8 | 9 | import { DialogContext } from 'botbuilder-dialogs'; 10 | import { BotkitConversationStep } from './conversation'; 11 | 12 | /** 13 | * This class is used to provide easy access to common actions taken on active BotkitConversation instances. 14 | * These objects are passed into handlers bound to BotkitConversations using .before .onChange and conditional handler functions passed to .ask and .addQuestion 15 | * Grants access to convo.vars convo.gotoThread() convo.setVar() and convo.repeat(). 16 | */ 17 | export class BotkitDialogWrapper { 18 | private dc: DialogContext; 19 | private step: BotkitConversationStep; 20 | /** 21 | * An object containing variables and user responses from this conversation. 22 | */ 23 | public vars: { 24 | [key: string]: any; 25 | } 26 | 27 | public constructor(dc: DialogContext, step: BotkitConversationStep) { 28 | this.dc = dc; 29 | this.step = step; 30 | this.vars = this.step.values; 31 | } 32 | 33 | /** 34 | * Jump immediately to the first message in a different thread. 35 | * @param thread Name of a thread 36 | */ 37 | public async gotoThread(thread: string): Promise { 38 | this.step.index = 0; 39 | this.step.thread = thread; 40 | } 41 | 42 | /** 43 | * Repeat the last message sent on the next turn. 44 | */ 45 | public async repeat(): Promise { 46 | // move back one step next turn the bot will repeat with the last message sent. 47 | this.step.index--; 48 | } 49 | 50 | /** 51 | * Stop the dialog. 52 | */ 53 | public async stop(): Promise { 54 | // set this to 1 bigger than the total length of the thread. 55 | this.step.index = this.step.threadLength + 1; 56 | } 57 | 58 | /** 59 | * Set the value of a variable that will be available to messages in the conversation. 60 | * Equivalent to convo.vars.key = val; 61 | * Results in {{vars.key}} being replaced with the value in val. 62 | * @param key the name of the variable 63 | * @param val the value for the variable 64 | */ 65 | public setVar(key, val): void { 66 | this.vars[key] = val; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /packages/botkit/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module botkit 3 | */ 4 | /** 5 | * Copyright (c) Microsoft Corporation. All rights reserved. 6 | * Licensed under the MIT License. 7 | */ 8 | 9 | export * from './core'; 10 | export * from './conversation'; 11 | export * from './botworker'; 12 | export * from './dialogWrapper'; 13 | export * from './teamsHelpers'; 14 | export * from './testClient'; 15 | -------------------------------------------------------------------------------- /packages/botkit/tests/Core.tests.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const { Botkit, TeamsBotWorker } = require('../'); 3 | const { TwilioAdapter, TwilioBotWorker } = require('../../botbuilder-adapter-twilio-sms'); 4 | 5 | describe('Botkit', function() { 6 | it('should create a Botkit controller', function() { 7 | assert((new Botkit({ disable_console: true, disable_webserver: true }) instanceof Botkit), 'Botkit is wrong type'); 8 | }); 9 | it ('should spawn appropriate bot worker with a single adapter', async function() { 10 | const controller = new Botkit({ 11 | disable_webserver: true, 12 | adapter: new TwilioAdapter({enable_incomplete: true}), 13 | }); 14 | 15 | const bot = await controller.spawn({}); 16 | assert((bot instanceof TwilioBotWorker), 'Bot worker is wrong type'); 17 | 18 | 19 | }); 20 | it ('should spawn appropriate bot worker with a multiple adapter', async function() { 21 | 22 | const controller = new Botkit({ 23 | disable_webserver: true, 24 | }); 25 | 26 | const anotherAdapter = new TwilioAdapter({enable_incomplete: true}); 27 | 28 | const bot = await controller.spawn({}); 29 | assert((bot instanceof TeamsBotWorker), 'Default Bot worker is wrong type'); 30 | 31 | const tbot = await controller.spawn({}, anotherAdapter); 32 | assert((tbot instanceof TwilioBotWorker), 'Secondary Bot worker is wrong type'); 33 | 34 | }); 35 | 36 | }); 37 | -------------------------------------------------------------------------------- /packages/botkit/tests/CustomAdapter.tests.js: -------------------------------------------------------------------------------- 1 | const { Botkit, BotkitConversation, BotkitTestClient, BotWorker } = require('..'); 2 | const { TestAdapter, AutoSaveStateMiddleware } = require('botbuilder'); 3 | const assert = require('assert'); 4 | 5 | class FakeBotWorker extends BotWorker { 6 | constructor(controller, config) { 7 | super(controller, config); 8 | } 9 | 10 | getUser() { 11 | return { 12 | id: 123, 13 | name: 'Roger' 14 | }; 15 | }; 16 | } 17 | 18 | class FakeAdapter extends TestAdapter { 19 | // Enables overriding the type of the BotWorker 20 | // (this uses a Botkit features that allows setting a worker type) 21 | botkit_worker = FakeBotWorker; 22 | } 23 | 24 | class CustomTestClient extends BotkitTestClient { 25 | constructor(channelId, bot, dialogToTest) { 26 | super(channelId, bot, dialogToTest); 27 | this._testAdapter = new FakeAdapter(this._callback, { channelId: channelId }).use(new AutoSaveStateMiddleware(this.conversationState)); 28 | } 29 | } 30 | 31 | function createDialog(controller) { 32 | const dialog = new BotkitConversation('try_custom_worker', controller); 33 | 34 | dialog.ask('How you like me now?', async (response, convo, bot) => { 35 | const botUser = bot.getUser(); 36 | return bot.say(`You are: ${ botUser.name }`); 37 | }, 'question'); 38 | 39 | return dialog; 40 | } 41 | 42 | describe('Test something with custom worker', () => { 43 | let botkit; 44 | let client; 45 | let testAdapter; 46 | 47 | it('bot can access user identity through custom bot worker', async () => { 48 | testAdapter = new FakeAdapter({}); 49 | botkit = new Botkit({ 50 | disable_webserver: true, 51 | disable_console: true, 52 | adapter: testAdapter 53 | }); 54 | botkit.addDialog(createDialog(botkit)); 55 | client = new CustomTestClient('test', botkit, ['try_custom_worker']); 56 | 57 | // Test the dialog through the client 58 | let message = await client.sendActivity(''); 59 | assert(message.text === 'How you like me now?'); 60 | message = await client.sendActivity('nice!'); 61 | assert(message.text === 'You are: Roger','Custom adapter spawning invalid bot'); 62 | }); 63 | 64 | afterEach(async () => { 65 | await botkit.shutdown(); 66 | }); 67 | }); 68 | -------------------------------------------------------------------------------- /packages/botkit/tests/State.tests.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const { BotkitConversationState } = require('../lib/conversationState'); 3 | const { MemoryStorage } = require('botbuilder'); 4 | 5 | const storage = new MemoryStorage(); 6 | const state = new BotkitConversationState(storage); 7 | 8 | describe('BotkitConversationState', function() { 9 | it('should generate appropriate state key', function() { 10 | const key = state.getStorageKey({ 11 | activity: { 12 | channelId: 'test', 13 | from: { 14 | id: 'foo' 15 | }, 16 | conversation: { 17 | id: 'bar' 18 | } 19 | } 20 | }); 21 | assert(key === 'test/conversations/bar-foo/', 'failed key gen'); 22 | }); 23 | it('should generate appropriate state key excluding properties field', function() { 24 | const key = state.getStorageKey({ 25 | activity: { 26 | channelId: 'test', 27 | from: { 28 | id: 'foo' 29 | }, 30 | conversation: { 31 | properties: { 32 | baz: true 33 | }, 34 | id: 'bar' 35 | } 36 | } 37 | }); 38 | assert(key === 'test/conversations/bar-foo/', 'failed key gen'); 39 | }); 40 | it('should generate appropriate state key including platform field', function() { 41 | const key = state.getStorageKey({ 42 | activity: { 43 | channelId: 'test', 44 | from: { 45 | id: 'foo' 46 | }, 47 | conversation: { 48 | threadId: '5', 49 | channel: '9', 50 | id: 'bar' 51 | } 52 | } 53 | }); 54 | assert(key === 'test/conversations/9-bar-5-foo/', 'failed key gen'); 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /packages/botkit/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2015", 4 | "module": "commonjs", 5 | "declaration": true, 6 | "sourceMap": true, 7 | "outDir": "./lib", 8 | "rootDir": "./src", 9 | "types" : ["node"], 10 | "lib": [ 11 | "es5", 12 | "es2015", 13 | "es2016.array.include", 14 | "esnext.asynciterable", 15 | "dom" 16 | ] 17 | }, 18 | "include": [ 19 | "src/**/*" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /packages/docs/.gitignore: -------------------------------------------------------------------------------- 1 | build/*.json 2 | -------------------------------------------------------------------------------- /packages/docs/build/adapter.hbs: -------------------------------------------------------------------------------- 1 | [← Botkit Documentation](../core.md) [← Platform Index](index.md) 2 | 3 | {{{body}}} 4 | -------------------------------------------------------------------------------- /packages/docs/build/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # generate main docs 3 | ./node_modules/.bin/typedoc --excludePrivate --ignoreCompilerErrors --module amd --hideGenerator --name "Botkit Core" --readme none --entryPoint botkit ../botkit/src/index.ts --json build/botkit.json 4 | ./node_modules/.bin/typedoc --excludePrivate --ignoreCompilerErrors --module amd --hideGenerator --name "Botkit for Slack" --readme none --entryPoint "botbuilder-adapter-slack" ../botbuilder-adapter-slack/src/index.ts --json build/slack.json 5 | ./node_modules/.bin/typedoc --excludePrivate --ignoreCompilerErrors --module amd --hideGenerator --name "Botkit for Facebook" --readme none --entryPoint "botbuilder-adapter-facebook" ../botbuilder-adapter-facebook/src/index.ts --json build/facebook.json 6 | ./node_modules/.bin/typedoc --excludePrivate --ignoreCompilerErrors --module amd --hideGenerator --name "Botkit for Hangouts" --readme none --entryPoint "botbuilder-adapter-hangouts" ../botbuilder-adapter-hangouts/src/index.ts --json build/hangouts.json 7 | ./node_modules/.bin/typedoc --excludePrivate --ignoreCompilerErrors --module amd --hideGenerator --name "Botkit for Twilio SMS" --readme none --entryPoint "botbuilder-adapter-twilio-sms" ../botbuilder-adapter-twilio-sms/src/index.ts --json build/twilio-sms.json 8 | ./node_modules/.bin/typedoc --excludePrivate --ignoreCompilerErrors --module amd --hideGenerator --name "Botkit for Webex Teams" --readme none --entryPoint "botbuilder-adapter-webex" ../botbuilder-adapter-webex/src/index.ts --json build/webex.json 9 | ./node_modules/.bin/typedoc --excludePrivate --ignoreCompilerErrors --module amd --hideGenerator --name "Botkit for the Web" --readme none --entryPoint "botbuilder-adapter-web" ../botbuilder-adapter-web/src/index.ts --json build/web.json 10 | ./node_modules/.bin/typedoc --excludePrivate --ignoreCompilerErrors --module amd --hideGenerator --name "Botkit CMS Plugin" --readme none --entryPoint "botkit-plugin-cms" ../botkit-plugin-cms/src/index.ts --json build/cms.json 11 | 12 | node build/parse.js 13 | -------------------------------------------------------------------------------- /packages/docs/build/plugin.hbs: -------------------------------------------------------------------------------- 1 | [← Botkit Documentation](../core.md) [← Plugin Index](index.md) 2 | 3 | {{{body}}} -------------------------------------------------------------------------------- /packages/docs/build/toc-platforms.hbs: -------------------------------------------------------------------------------- 1 | # {{title}} 2 | 3 | [← Botkit Core Docs](../core.md) 4 | 5 | {{#each index}} 6 | * [{{name}}](../{{path}}) 7 | {{#each classes}} 8 | * [{{name}}](../{{../path}}#{{name}}) 9 | {{/each}} 10 | {{/each}} 11 | * [Microsoft Teams](../core.md#using-bot-framework-channels) 12 | -------------------------------------------------------------------------------- /packages/docs/build/toc.hbs: -------------------------------------------------------------------------------- 1 | # {{title}} 2 | 3 | [← Botkit Core Docs](../core.md) 4 | 5 | {{#each index}} 6 | * [{{name}}](../{{path}}) 7 | {{#each classes}} 8 | * [{{name}}](../{{../path}}#{{name}}) 9 | {{/each}} 10 | {{/each}} -------------------------------------------------------------------------------- /packages/docs/glitch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howdyai/botkit/b8f0e3e7fd9238a585ffdcec4a691acb23d0adcf/packages/docs/glitch.png -------------------------------------------------------------------------------- /packages/docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "botkit-docs", 3 | "version": "1.0.0", 4 | "description": "Documentation for Botkit 4.x", 5 | "scripts": { 6 | "build-docs": "./build/build.sh" 7 | }, 8 | "author": "benbrown@gmail.com", 9 | "license": "MIT", 10 | "dependencies": { 11 | "handlebars": "^4.7.7", 12 | "typedoc": "^0.22.10", 13 | "typedoc-plugin-external-module-name": "4.0.6" 14 | }, 15 | "devDependencies": { 16 | "typedoc-plugin-no-inherit": "^1.1.10" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/docs/platforms/index.md: -------------------------------------------------------------------------------- 1 | # Platform Adapters 2 | 3 | [← Botkit Core Docs](../core.md) 4 | 5 | * [Websocket and Webhooks](../platforms/web.md) 6 | * [Webex Teams](../platforms/webex.md) 7 | * [Slack](../platforms/slack.md) 8 | * [Google Hangouts](../platforms/hangouts.md) 9 | * [Twilio SMS](../platforms/twilio-sms.md) 10 | * [Facebook Messenger](../platforms/facebook.md) 11 | * [Microsoft Teams](../core.md#using-bot-framework-channels) 12 | -------------------------------------------------------------------------------- /packages/docs/plugins/index.md: -------------------------------------------------------------------------------- 1 | # Botkit Plugins 2 | 3 | [← Botkit Core Docs](../core.md) 4 | 5 | * [Botkit CMS Plugin](../plugins/cms.md) 6 | -------------------------------------------------------------------------------- /packages/docs/provisioning/IMG/Slack-eventsenable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howdyai/botkit/b8f0e3e7fd9238a585ffdcec4a691acb23d0adcf/packages/docs/provisioning/IMG/Slack-eventsenable.png -------------------------------------------------------------------------------- /packages/docs/provisioning/IMG/botkit_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howdyai/botkit/b8f0e3e7fd9238a585ffdcec4a691acb23d0adcf/packages/docs/provisioning/IMG/botkit_icon.png -------------------------------------------------------------------------------- /packages/docs/provisioning/IMG/cisco_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howdyai/botkit/b8f0e3e7fd9238a585ffdcec4a691acb23d0adcf/packages/docs/provisioning/IMG/cisco_add.png -------------------------------------------------------------------------------- /packages/docs/provisioning/IMG/fb_app_perm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howdyai/botkit/b8f0e3e7fd9238a585ffdcec4a691acb23d0adcf/packages/docs/provisioning/IMG/fb_app_perm.png -------------------------------------------------------------------------------- /packages/docs/provisioning/IMG/fb_mess.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howdyai/botkit/b8f0e3e7fd9238a585ffdcec4a691acb23d0adcf/packages/docs/provisioning/IMG/fb_mess.png -------------------------------------------------------------------------------- /packages/docs/provisioning/IMG/fb_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howdyai/botkit/b8f0e3e7fd9238a585ffdcec4a691acb23d0adcf/packages/docs/provisioning/IMG/fb_new.png -------------------------------------------------------------------------------- /packages/docs/provisioning/IMG/fb_tokengen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howdyai/botkit/b8f0e3e7fd9238a585ffdcec4a691acb23d0adcf/packages/docs/provisioning/IMG/fb_tokengen.png -------------------------------------------------------------------------------- /packages/docs/provisioning/IMG/fb_webhooks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howdyai/botkit/b8f0e3e7fd9238a585ffdcec4a691acb23d0adcf/packages/docs/provisioning/IMG/fb_webhooks.png -------------------------------------------------------------------------------- /packages/docs/provisioning/IMG/fb_webhooks_com.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howdyai/botkit/b8f0e3e7fd9238a585ffdcec4a691acb23d0adcf/packages/docs/provisioning/IMG/fb_webhooks_com.png -------------------------------------------------------------------------------- /packages/docs/provisioning/IMG/slack-botuser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howdyai/botkit/b8f0e3e7fd9238a585ffdcec4a691acb23d0adcf/packages/docs/provisioning/IMG/slack-botuser.png -------------------------------------------------------------------------------- /packages/docs/provisioning/IMG/slack-im.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howdyai/botkit/b8f0e3e7fd9238a585ffdcec4a691acb23d0adcf/packages/docs/provisioning/IMG/slack-im.png -------------------------------------------------------------------------------- /packages/docs/provisioning/IMG/slack-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howdyai/botkit/b8f0e3e7fd9238a585ffdcec4a691acb23d0adcf/packages/docs/provisioning/IMG/slack-new.png -------------------------------------------------------------------------------- /packages/docs/provisioning/IMG/slack_botevents.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howdyai/botkit/b8f0e3e7fd9238a585ffdcec4a691acb23d0adcf/packages/docs/provisioning/IMG/slack_botevents.png -------------------------------------------------------------------------------- /packages/docs/provisioning/IMG/slack_client_secret.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howdyai/botkit/b8f0e3e7fd9238a585ffdcec4a691acb23d0adcf/packages/docs/provisioning/IMG/slack_client_secret.png -------------------------------------------------------------------------------- /packages/docs/provisioning/IMG/slack_oauth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howdyai/botkit/b8f0e3e7fd9238a585ffdcec4a691acb23d0adcf/packages/docs/provisioning/IMG/slack_oauth.png -------------------------------------------------------------------------------- /packages/docs/provisioning/cisco-spark.md: -------------------------------------------------------------------------------- 1 | # Configure Botkit and Cisco Webex Teams 2 | 3 | Setting up a bot for Cisco Webex Teams is one of the easiest experiences for bot developers! Follow these steps carefully to configure your bot. 4 | 5 | ### 1. Install Botkit 6 | 7 | You will need to [install Botkit](../platforms/webex.md#get-started) and run it before your bot can be configured with Cisco Spark. 8 | 9 | ### 2. Create a new bot in the Cisco Developer portal 10 | 11 | Follow the instructions to create a new bot in the [Cisco Webex Teams Developer Portal](https://developer.ciscospark.com/add-bot.html). 12 | 13 | ![Screenshot of the 'Add a bot' flow in Webex developer portal](IMG/cisco_add.png) 14 | 15 | Take note of the bot username, you'll need it later. 16 | 17 | **Note about your icon**: Cisco requires you host an avatar for your bot before you can create it in their portal. This bot needs to be a 512x512px image icon hosted anywhere on the web. This can be changed later. 18 | 19 | You can copy and paste this URL for a Botkit icon you can use right away: 20 | 21 | https://raw.githubusercontent.com/howdyai/botkit-starter-ciscospark/master/public/default_icon.png 22 | 23 | ### 3. Copy your access token 24 | 25 | Cisco will provide you an `access token` that is specific to your bot. Write this down, you won't be able to see this later (but you will be able revoke it and create a new one). 26 | 27 | ### 4. Run your bot with variables set 28 | 29 | [Follow these instructions](../platforms/webex.md#get-started) to run your bot locally, or by using a third-party service such as [Glitch](https://glitch.com) or [Heroku](https://heroku.com). 30 | 31 | You will need the following environment variables when running your bot: 32 | 33 | * `access_token` = Your token from Webex Teams (**required**) 34 | * `secret` = User-defined string to validate payloads (**required**) 35 | * `public_address`= URL of your bot server (**required**) 36 | 37 | You should now be able to search your Webex Teams for the bot username you defined, and add it to your team! 38 | 39 | ### Additional resources 40 | 41 | Read more about making bots for this platform in the [Webex Developer Portal](https://developer.webex.com/docs/bots). 42 | -------------------------------------------------------------------------------- /packages/docs/provisioning/facebook_messenger.md: -------------------------------------------------------------------------------- 1 | # Configure Botkit and Facebook Messenger 2 | 3 | *Note: This also applies for [Facebook Workplace](https://www.facebook.com/workplace)* 4 | 5 | Facebook is a constantly evolving platform, nominally you can find everything you [need to create a bot](https://developers.facebook.com/docs/messenger-platform/guides/quick-start) on their platform page, but that information is subject to change. 6 | 7 | ### 1. [Install Botkit](../index.md) 8 | 9 | Once installed, you will need to do steps 2-4, and steps 5 in parallel. It helps to have your development enviroment and the Facebook for Developers page open at the same time. 10 | 11 | ### 2. Create a Facebook App for Web 12 | 13 | Visit [Facebook for Developers page](https://developers.facebook.com/tools-and-support/) and create a new app. 14 | 15 | ![Screenshot of create an APP ID in Facebook developer portal](IMG/fb_new.png) 16 | 17 | * Select a Messenger application 18 | 19 | ![Screenshot of configuring your app in the Facebook developer portal](IMG/fb_mess.png) 20 | 21 | ### 3. Get a Page Access Token for your app 22 | Scroll down to `Token Generation` 23 | 24 | ![Screenshot of page access tokens in Facebook portal](IMG/fb_tokengen.png) 25 | 26 | If you have not yet created your page yet, you can go ahead and do this now, or associate this new bot with an existing page. 27 | 28 | Copy this `Page Access Token`, you'll need it when running your bot. 29 | 30 | ### 4. Setup webhooks 31 | Click `Setup Webhooks` to link this application to your Botkit instance. 32 | 33 | ![Screenshot of configuring webhooks in the Facebook portal](IMG/fb_webhooks.png) 34 | 35 | The callback url will be `https://YOURURL/api/messages`. This URL must be publically available, and SSL-secured. More information on this can be found in the next step. 36 | 37 | You will also need to define a `Verify Token` for your page subscription. This is a user-defined string that you will keep secret and pass in with your environment variables. 38 | 39 | ### 5. Run your application 40 | 41 | Run your application with your environment variables set: 42 | 43 | * `page_token` - Your Page Access Token (**required**) 44 | * `verify_token` - Your Verify Token (**required**) 45 | 46 | If your application has been configured correctly, you will be able to talk to your bot through the page you specified in Step 3. Congratulations! 47 | 48 | ### Additional resources 49 | * [Botkit Facebook readme](../platforms/facebook.md) 50 | * [Botkit Facebook Starter Kit](https://github.com/howdyai/botkit-starter-facebook) 51 | * [Messenger Platform Documentation](https://developers.facebook.com/products/messenger/) 52 | * [Submit your bot so it can be publically available](https://developers.facebook.com/docs/messenger-platform/submission-process) 53 | -------------------------------------------------------------------------------- /packages/docs/provisioning/index.md: -------------------------------------------------------------------------------- 1 | # Provisioning Botkit 2 | As Botkit adds more platforms, it becomes increasingly difficult to keep track of all the methods for provisioning your bot on the various platforms we support. 3 | 4 | To help Botkit developers, we are pulling out detailed provisioning documents for each platform and keeping them in this directory. Our hope is that this will make our docs more flexible to platform changes, and clearly show the fastest way to stand up your bot! 5 | 6 | ## Platforms 7 | 8 | ### [Slack Events API](slack-events-api.md) 9 | 10 | ### [Microsoft Teams](teams.md) 11 | 12 | ### [Facebook Messenger](facebook_messenger.md) 13 | 14 | ### [Webex Teams](cisco-spark.md) 15 | 16 | ### [SMS from Twilio](twilio-sms.md) 17 | -------------------------------------------------------------------------------- /packages/docs/provisioning/twilio-sms.md: -------------------------------------------------------------------------------- 1 | # Configure Botkit and Twilio SMS 2 | 3 | Setting up a bot for Twilio SMS is one of the easiest experiences for bot developers! Follow these steps carefully to configure your bot. 4 | 5 | ### 1. Install Botkit 6 | 7 | You will need to [install Botkit](../platforms/twilio-sms.md#get-started) and run it before your bot can be configured with Twilio SMS. 8 | 9 | ### 2. Create a new bot in the Twilio Developer Console 10 | 11 | Login and click `Get Started` in [Twilio SMS Developer Console](https://www.twilio.com/console/sms/dashboard). You will be taken through the process of obtaining a number to use with your bot. 12 | 13 | At this point you can use the Twilio wizard to help you create an application, or build one directly by clicking `Messanging Services`. You can give it a friendly, and chose `Mixed` for use case. 14 | 15 | Check the box `Process Inbound Messages` and under request URL, type the name of your request url. 16 | 17 | By default in Botkit, this is: 18 | https://*mybot.yoururl.com*/api/messages 19 | 20 | ### 3. Collect your tokens 21 | 22 | Next, visit [your console Dashboard](https://www.twilio.com/console) and copy your `Account SID` and `Auth Token`. You will use these in the next step along with your assignedmobile number to setup Botkit. 23 | 24 | ### 4. Run your bot with variables set 25 | 26 | [Follow these instructions](../platforms/twilio-sms.md#get-started) to run your bot locally, or by using a third-party service such as [Glitch](https://glitch.com) or [Heroku](https://heroku.com). 27 | 28 | You will need the following environment variables when running your bot: 29 | 30 | * TWILIO_ACCOUNT_SID= Your account's SID collected in step 3 above. 31 | * TWILIO_AUTH_TOKEN= Your account's Auth Token collected in step 3 above. 32 | * TWILIO_NUMBER= The number you were assigned in step 2 above. 33 | 34 | You should now be able to text message your number the words `Hello` and receive a friendly reply back! 35 | 36 | ### Additional resources 37 | 38 | Read more about making bots for this platform in the [Twilio Developer Portal](https://www.twilio.com/console). 39 | -------------------------------------------------------------------------------- /packages/docs/readme.md: -------------------------------------------------------------------------------- 1 | # Botkit 4.x Docs 2 | 3 | This repo contains the source material for the official Botkit 4.x docs. 4 | 5 | * [Get Started](index.md) 6 | * [Plugins](plugins/index.md) 7 | * [Platform Adapters](platforms/index.md) 8 | * [Class Reference](reference/index.md) 9 | 10 | #### Building the Docs 11 | 12 | _Most_ of these documents are automatically generated from the source and by aggregating information from the various adapter and plugin packages. Do not manually edit files in `platforms/` `plugins/` or `reference/` 13 | 14 | To build new versions of these docs, run: 15 | 16 | ```bash 17 | lerna run build 18 | lerna run build-docs 19 | ``` 20 | -------------------------------------------------------------------------------- /packages/docs/reference/index.md: -------------------------------------------------------------------------------- 1 | # Class Index 2 | 3 | [← Botkit Core Docs](../core.md) 4 | 5 | * [Botkit Core](../reference/core.md) 6 | * [Botkit](../reference/core.md#Botkit) 7 | * [BotkitBotFrameworkAdapter](../reference/core.md#BotkitBotFrameworkAdapter) 8 | * [TeamsBotWorker](../reference/core.md#TeamsBotWorker) 9 | * [BotWorker](../reference/core.md#BotWorker) 10 | * [BotkitConversation](../reference/core.md#BotkitConversation) 11 | * [BotkitDialogWrapper](../reference/core.md#BotkitDialogWrapper) 12 | * [BotkitTestClient](../reference/core.md#BotkitTestClient) 13 | * [TeamsInvokeMiddleware](../reference/core.md#TeamsInvokeMiddleware) 14 | * [Botkit for the Web](../reference/web.md) 15 | * [WebAdapter](../reference/web.md#WebAdapter) 16 | * [Botkit for Webex Teams](../reference/webex.md) 17 | * [WebexAdapter](../reference/webex.md#WebexAdapter) 18 | * [WebexBotWorker](../reference/webex.md#WebexBotWorker) 19 | * [Botkit for Slack](../reference/slack.md) 20 | * [SlackAdapter](../reference/slack.md#SlackAdapter) 21 | * [SlackBotWorker](../reference/slack.md#SlackBotWorker) 22 | * [SlackDialog](../reference/slack.md#SlackDialog) 23 | * [SlackEventMiddleware](../reference/slack.md#SlackEventMiddleware) 24 | * [SlackMessageTypeMiddleware](../reference/slack.md#SlackMessageTypeMiddleware) 25 | * [Botkit for Hangouts](../reference/hangouts.md) 26 | * [HangoutsAdapter](../reference/hangouts.md#HangoutsAdapter) 27 | * [HangoutsBotWorker](../reference/hangouts.md#HangoutsBotWorker) 28 | * [Botkit for Twilio SMS](../reference/twilio-sms.md) 29 | * [TwilioAdapter](../reference/twilio-sms.md#TwilioAdapter) 30 | * [TwilioBotWorker](../reference/twilio-sms.md#TwilioBotWorker) 31 | * [Botkit for Facebook](../reference/facebook.md) 32 | * [FacebookAdapter](../reference/facebook.md#FacebookAdapter) 33 | * [FacebookBotWorker](../reference/facebook.md#FacebookBotWorker) 34 | * [FacebookAPI](../reference/facebook.md#FacebookAPI) 35 | * [FacebookEventTypeMiddleware](../reference/facebook.md#FacebookEventTypeMiddleware) 36 | * [Botkit CMS Plugin](../reference/cms.md) 37 | * [BotkitCMSHelper](../reference/cms.md#BotkitCMSHelper) 38 | -------------------------------------------------------------------------------- /packages/generator-botkit/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 4.10.0 2 | 3 | * Update to Botkit 4.10 4 | 5 | # 4.6.3 6 | 7 | Fix issue introduced in 4.6.2 that removed required .env file templates 8 | 9 | # 4.6.1 10 | 11 | * Update all environment variables to UPPER_CASE 12 | 13 | # 4.5.1 14 | 15 | * Fix issue the typing indicator sample in the web starter kit 16 | 17 | # 4.5.0 18 | 19 | Update Botkit and Bot Framework package versions to latest 20 | -------------------------------------------------------------------------------- /packages/generator-botkit/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /packages/generator-botkit/generators/app/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. 4 | */ 5 | 6 | var Generator = require('yeoman-generator'); 7 | var _ = require('underscore'); 8 | _.extend(Generator.prototype, require('yeoman-generator/lib/actions/install')); 9 | 10 | var path = require('path'); 11 | 12 | const platforms = [ 13 | 'botframework', 14 | 'slack', 15 | 'hangouts', 16 | 'twilio-sms', 17 | 'webex', 18 | 'web', 19 | 'facebook' 20 | ]; 21 | 22 | module.exports = class extends Generator { 23 | 24 | async prompting() { 25 | this.answers = await this.prompt([ 26 | { 27 | type: "input", 28 | name: "name", 29 | message: "What is your bot's name?", 30 | default: this.appname 31 | }, 32 | { 33 | type: "list", 34 | name: "platform", 35 | choices: platforms, 36 | message: "Which messaging platform?", 37 | }, 38 | { 39 | type: "input", 40 | name: "mongo_uri", 41 | message: "(Optional) Mongo URI for state persistence:", 42 | } 43 | ]); 44 | 45 | this.answers.safe_name = this.answers.name.toLowerCase().replace(/\s+/,'-'); 46 | 47 | } 48 | 49 | async composing() { 50 | if (this.answers.platform === 'slack') { 51 | this.composeWith(require.resolve(path.join(__dirname,'..','slack')), this.answers); 52 | } else if (this.answers.platform === 'hangouts') { 53 | this.composeWith(require.resolve(path.join(__dirname,'..','hangouts')), this.answers); 54 | } else if (this.answers.platform === 'facebook') { 55 | this.composeWith(require.resolve(path.join(__dirname,'..','facebook')), this.answers); 56 | } else if (this.answers.platform === 'twilio-sms') { 57 | this.composeWith(require.resolve(path.join(__dirname,'..','twilio-sms')), this.answers); 58 | } else if (this.answers.platform === 'webex') { 59 | this.composeWith(require.resolve(path.join(__dirname,'..','webex')), this.answers); 60 | } else if (this.answers.platform === 'web') { 61 | this.composeWith(require.resolve(path.join(__dirname,'..','web')), this.answers); 62 | } else if (this.answers.platform === 'botframework') { 63 | this.composeWith(require.resolve(path.join(__dirname,'..','botframework')), this.answers); 64 | } 65 | } 66 | 67 | writing() { 68 | 69 | this.fs.copyTpl( 70 | this.templatePath('package.json'), 71 | this.destinationPath('package.json'), 72 | this.answers 73 | ); 74 | 75 | this.fs.copyTpl( 76 | this.templatePath('bot.js'), 77 | this.destinationPath('bot.js'), 78 | this.answers 79 | ); 80 | 81 | this.fs.copyTpl( 82 | this.templatePath('gitignore'), 83 | this.destinationPath('.gitignore'), 84 | this.answers 85 | ); 86 | 87 | this.fs.copyTpl( 88 | this.templatePath('readme.md'), 89 | this.destinationPath('readme.md'), 90 | this.answers 91 | ); 92 | 93 | 94 | this.fs.copy( 95 | this.templatePath('features'), 96 | this.destinationPath('features') 97 | ); 98 | } 99 | 100 | install() { 101 | this.npmInstall(); 102 | } 103 | 104 | }; -------------------------------------------------------------------------------- /packages/generator-botkit/generators/app/templates/features/sample_echo.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. 4 | */ 5 | 6 | module.exports = function(controller) { 7 | 8 | controller.hears('sample','message,direct_message', async(bot, message) => { 9 | await bot.reply(message, 'I heard a sample message.'); 10 | }); 11 | 12 | controller.on('message,direct_message', async(bot, message) => { 13 | await bot.reply(message, `Echo: ${ message.text }`); 14 | }); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /packages/generator-botkit/generators/app/templates/features/sample_hears.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. 4 | */ 5 | module.exports = function(controller) { 6 | 7 | // use a function to match a condition in the message 8 | controller.hears(async (message) => message.text && message.text.toLowerCase() === 'foo', ['message'], async (bot, message) => { 9 | await bot.reply(message, 'I heard "foo" via a function test'); 10 | }); 11 | 12 | // use a regular expression to match the text of the message 13 | controller.hears(new RegExp(/^\d+$/), ['message','direct_message'], async function(bot, message) { 14 | await bot.reply(message,{ text: 'I heard a number using a regular expression.' }); 15 | }); 16 | 17 | // match any one of set of mixed patterns like a string, a regular expression 18 | controller.hears(['allcaps', new RegExp(/^[A-Z\s]+$/)], ['message','direct_message'], async function(bot, message) { 19 | await bot.reply(message,{ text: 'I HEARD ALL CAPS!' }); 20 | }); 21 | 22 | } -------------------------------------------------------------------------------- /packages/generator-botkit/generators/app/templates/gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | node_modules/ -------------------------------------------------------------------------------- /packages/generator-botkit/generators/app/templates/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "botkit-<%= safe_name %>", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "bot.js", 6 | "scripts": { 7 | "start": "node bot.js", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "dependencies": { 11 | "botkit": "^4.15.0", 12 | "botkit-plugin-cms": "^1.0.3", 13 | "botbuilder-storage-mongodb":"^0.9.5", 14 | "dotenv": "^7.0.0" 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /packages/generator-botkit/generators/app/templates/readme.md: -------------------------------------------------------------------------------- 1 | # Botkit Starter Kit 2 | 3 | This is a Botkit starter kit for <%= platform %>, created with the [Yeoman generator](https://github.com/howdyai/botkit/tree/master/packages/generator-botkit#readme). 4 | 5 | To complete the configuration of this bot, make sure to update the included `.env` file with your platform tokens and credentials. 6 | 7 | [Botkit Docs](https://github.com/howdyai/botkit/blob/main/packages/docs/index.md) 8 | 9 | This bot is powered by [a folder full of modules](https://github.com/howdyai/botkit/blob/main/packages/docs/core.md#organize-your-bot-code). 10 | Edit the samples, and add your own in the [features/](features/) folder. 11 | -------------------------------------------------------------------------------- /packages/generator-botkit/generators/botframework/index.js: -------------------------------------------------------------------------------- 1 | var Generator = require('yeoman-generator'); 2 | 3 | module.exports = class extends Generator { 4 | async prompting() { 5 | 6 | this.platform = await this.prompt([ 7 | { 8 | type: "input", 9 | name: "appId", 10 | message: "App ID", 11 | }, 12 | { 13 | type: "input", 14 | name: "appPassword", 15 | message: "App Password", 16 | } 17 | ]); 18 | 19 | } 20 | writing() { 21 | 22 | this.fs.copy( 23 | this.templatePath('features'), 24 | this.destinationPath('features') 25 | ); 26 | 27 | this.fs.copyTpl( 28 | this.templatePath('.env'), 29 | this.destinationPath('.env'), 30 | { 31 | platform: this.platform, 32 | options: this.options, 33 | }, 34 | ); 35 | 36 | } 37 | 38 | install() { 39 | // noop 40 | } 41 | 42 | }; -------------------------------------------------------------------------------- /packages/generator-botkit/generators/botframework/templates/.env: -------------------------------------------------------------------------------- 1 | # Microsoft Azure Bot Service credentials 2 | APP_ID=<%= platform.appId %> 3 | APP_PASSWORD=<%= platform.appPassword %> 4 | 5 | MONGO_URI=<%= options.mongo_uri %> 6 | -------------------------------------------------------------------------------- /packages/generator-botkit/generators/botframework/templates/features/botframework_features.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. 4 | */ 5 | 6 | module.exports = function(controller) { 7 | 8 | // send welcome 9 | controller.on('conversationUpdate', async(bot, message) => { 10 | 11 | 12 | }); 13 | 14 | } -------------------------------------------------------------------------------- /packages/generator-botkit/generators/facebook/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. 4 | */ 5 | 6 | var Generator = require('yeoman-generator'); 7 | var _ = require('underscore'); 8 | _.extend(Generator.prototype, require('yeoman-generator/lib/actions/install')); 9 | 10 | module.exports = class extends Generator { 11 | async prompting() { 12 | 13 | this.platform = await this.prompt([ 14 | { 15 | type: "input", 16 | name: "appId", 17 | message: "App ID", 18 | }, 19 | { 20 | type: "input", 21 | name: "appSecret", 22 | message: "App Secret", 23 | }, 24 | { 25 | type: "input", 26 | name: "access_token", 27 | message: "Page Access Token", 28 | }, 29 | { 30 | type: "input", 31 | name: "verify_token", 32 | message: "Webhook Verify Token", 33 | }, 34 | ]); 35 | 36 | } 37 | writing() { 38 | 39 | this.fs.copy( 40 | this.templatePath('features'), 41 | this.destinationPath('features') 42 | ); 43 | 44 | this.fs.copyTpl( 45 | this.templatePath('.env'), 46 | this.destinationPath('.env'), 47 | { 48 | platform: this.platform, 49 | options: this.options, 50 | }, 51 | ); 52 | 53 | } 54 | 55 | install() { 56 | this.npmInstall(['botbuilder-adapter-facebook@latest']); 57 | } 58 | 59 | }; -------------------------------------------------------------------------------- /packages/generator-botkit/generators/facebook/templates/.env: -------------------------------------------------------------------------------- 1 | FACEBOOK_APPID=<%= platform.appId %> 2 | FACEBOOK_APP_SECRET=<%= platform.appSecret %> 3 | FACEBOOK_ACCESS_TOKEN=<%= platform.access_token %> 4 | FACEBOOK_VERIFY_TOKEN=<%= platform.verify_token %> 5 | 6 | 7 | MONGO_URI=<%= options.mongo_uri %> -------------------------------------------------------------------------------- /packages/generator-botkit/generators/facebook/templates/features/facebook_features.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. 4 | */ 5 | 6 | module.exports = function(controller) { 7 | 8 | /** 9 | * Detect when a message has a sticker attached 10 | */ 11 | controller.hears(async(message) => message.sticker_id, 'message', async(bot, message) => { 12 | await bot.reply(message,'Cool sticker.'); 13 | }); 14 | 15 | controller.on('facebook_postback', async(bot, message) => { 16 | await bot.reply(message,`I heard you posting back a post_back about ${ message.text }`); 17 | }); 18 | 19 | 20 | } -------------------------------------------------------------------------------- /packages/generator-botkit/generators/hangouts/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. 4 | */ 5 | 6 | var Generator = require('yeoman-generator'); 7 | var _ = require('underscore'); 8 | _.extend(Generator.prototype, require('yeoman-generator/lib/actions/install')); 9 | 10 | module.exports = class extends Generator { 11 | 12 | async prompting() { 13 | 14 | this.platform = await this.prompt([ 15 | { 16 | type: "input", 17 | name: "creds", 18 | message: "JSON credentials", 19 | }, 20 | { 21 | type: "input", 22 | name: "token", 23 | message: "Token", 24 | }, 25 | ]); 26 | 27 | } 28 | 29 | writing() { 30 | 31 | this.fs.copy( 32 | this.templatePath('features'), 33 | this.destinationPath('features') 34 | ); 35 | 36 | 37 | this.fs.copyTpl( 38 | this.templatePath('.env'), 39 | this.destinationPath('.env'), 40 | { 41 | platform: this.platform, 42 | options: this.options, 43 | }, 44 | ); 45 | 46 | } 47 | 48 | install() { 49 | this.npmInstall(['botbuilder-adapter-hangouts@latest']); 50 | } 51 | 52 | }; -------------------------------------------------------------------------------- /packages/generator-botkit/generators/hangouts/templates/.env: -------------------------------------------------------------------------------- 1 | GOOGLE_CREDS=<%- platform.creds %> 2 | GOOGLE_TOKEN=<%= platform.token %> 3 | 4 | MONGO_URI=<%= options.mongo_uri %> -------------------------------------------------------------------------------- /packages/generator-botkit/generators/slack/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. 4 | */ 5 | var Generator = require('yeoman-generator'); 6 | var _ = require('underscore'); 7 | _.extend(Generator.prototype, require('yeoman-generator/lib/actions/install')); 8 | 9 | module.exports = class extends Generator { 10 | 11 | async prompting() { 12 | 13 | var type = await this.prompt([ 14 | { 15 | type: "input", 16 | name: "clientSigningSecret", 17 | message: "Client signing secret (from api.slack.com)", 18 | }, 19 | { 20 | type: "list", 21 | name: "type", 22 | choices: ['single','multi'], 23 | message: "Configure for single-team or multi-team?", 24 | } 25 | ]); 26 | 27 | if (type.type == 'single') { 28 | this.platform = await this.prompt([ 29 | { 30 | type: "input", 31 | name: "botToken", 32 | message: "Bot Token", 33 | }, 34 | ]); 35 | } else { 36 | this.platform = await this.prompt([ 37 | { 38 | type: "input", 39 | name: "clientId", 40 | message: "Client ID", 41 | }, 42 | { 43 | type: "input", 44 | name: "clientSecret", 45 | message: "Client Secret", 46 | }, 47 | { 48 | type: "input", 49 | name: "redirectUri", 50 | message: "OAuth Redirect URI (in the form https:///install/auth)", 51 | }, 52 | ]); 53 | } 54 | 55 | this.platform.type = type.type; 56 | this.platform.clientSigningSecret = type.clientSigningSecret; 57 | } 58 | 59 | writing() { 60 | 61 | this.fs.copy( 62 | this.templatePath('features'), 63 | this.destinationPath('features') 64 | ); 65 | 66 | this.fs.copyTpl( 67 | this.templatePath('.env'), 68 | this.destinationPath('.env'), 69 | { 70 | platform: this.platform, 71 | options: this.options, 72 | }, 73 | ); 74 | 75 | } 76 | 77 | install() { 78 | this.npmInstall(['botbuilder-adapter-slack@latest']); 79 | } 80 | 81 | }; -------------------------------------------------------------------------------- /packages/generator-botkit/generators/slack/templates/.env: -------------------------------------------------------------------------------- 1 | # Slack security config 2 | CLIENT_SIGNING_SECRET=<%= platform.clientSigningSecret %> 3 | 4 | <% if (platform.type === 'single') { %> 5 | # Single-team Slack config 6 | BOT_TOKEN=<%= platform.botToken %> 7 | <% } else { %> 8 | # Multi-team Slack config 9 | CLIENT_ID=<%= platform.clientId %> 10 | CLIENT_SECRET=<%= platform.clientSecret %> 11 | REDIRECT_URI=<%= platform.redirectUri %> 12 | <% } %> 13 | 14 | MONGO_URI=<%= options.mongo_uri %> 15 | -------------------------------------------------------------------------------- /packages/generator-botkit/generators/slack/templates/features/routes_oauth.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. 4 | */ 5 | /** 6 | * This module implements the oauth routes needed to install an app 7 | */ 8 | module.exports = function(controller) { 9 | // controller.webserver.get('/install', (req, res) => { 10 | // // getInstallLink points to slack's oauth endpoint and includes clientId and scopes 11 | // res.redirect(controller.adapter.getInstallLink()); 12 | // }); 13 | 14 | // controller.webserver.get('/install/auth', async (req, res) => { 15 | // try { 16 | // const results = await controller.adapter.validateOauthCode(req.query.code); 17 | 18 | // console.log('FULL OAUTH DETAILS', results); 19 | 20 | // // Store token by team in bot state. 21 | // tokenCache[results.team_id] = results.bot.bot_access_token; 22 | 23 | // // Capture team to bot id 24 | // userCache[results.team_id] = results.bot.bot_user_id; 25 | 26 | // res.json('Success! Bot installed.'); 27 | 28 | // } catch (err) { 29 | // console.error('OAUTH ERROR:', err); 30 | // res.status(401); 31 | // res.send(err.message); 32 | // } 33 | // }); 34 | }; 35 | 36 | /** 37 | * This is a placeholder implementation for getTokenForTeam and getBotUserByTeam 38 | * TODO: how to expose these to botkit tho? 39 | */ 40 | let tokenCache = {}; 41 | let userCache = {}; 42 | 43 | if (process.env.TOKENS) { 44 | tokenCache = JSON.parse(process.env.TOKENS); 45 | } 46 | 47 | if (process.env.USERS) { 48 | userCache = JSON.parse(process.env.USERS); 49 | } 50 | 51 | async function getTokenForTeam(teamId) { 52 | if (tokenCache[teamId]) { 53 | return new Promise((resolve) => { 54 | setTimeout(function() { 55 | resolve(tokenCache[teamId]); 56 | }, 150); 57 | }); 58 | } else { 59 | console.error('Team not found in tokenCache: ', teamId); 60 | } 61 | } 62 | 63 | async function getBotUserByTeam(teamId) { 64 | if (userCache[teamId]) { 65 | return new Promise((resolve) => { 66 | setTimeout(function() { 67 | resolve(userCache[teamId]); 68 | }, 150); 69 | }); 70 | } else { 71 | console.error('Team not found in userCache: ', teamId); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /packages/generator-botkit/generators/twilio-sms/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. 4 | */ 5 | var Generator = require('yeoman-generator'); 6 | var _ = require('underscore'); 7 | _.extend(Generator.prototype, require('yeoman-generator/lib/actions/install')); 8 | 9 | module.exports = class extends Generator { 10 | async prompting() { 11 | 12 | this.platform = await this.prompt([ 13 | { 14 | type: "input", 15 | name: "number", 16 | message: "Phone Number", 17 | }, 18 | { 19 | type: "input", 20 | name: "account_sid", 21 | message: "Account SID", 22 | }, 23 | { 24 | type: "input", 25 | name: "auth_token", 26 | message: "Auth Token", 27 | }, 28 | ]); 29 | 30 | } 31 | 32 | writing() { 33 | 34 | this.fs.copy( 35 | this.templatePath('features'), 36 | this.destinationPath('features') 37 | ); 38 | 39 | 40 | this.fs.copyTpl( 41 | this.templatePath('.env'), 42 | this.destinationPath('.env'), 43 | { 44 | platform: this.platform, 45 | options: this.options, 46 | }, 47 | ); 48 | } 49 | 50 | install() { 51 | this.npmInstall(['botbuilder-adapter-twilio-sms@latest']); 52 | this.npmInstall(['twilio']); 53 | } 54 | 55 | }; -------------------------------------------------------------------------------- /packages/generator-botkit/generators/twilio-sms/templates/.env: -------------------------------------------------------------------------------- 1 | TWILIO_NUMBER=<%= platform.number %> 2 | TWILIO_ACCOUNT_SID=<%= platform.account_sid %> 3 | TWILIO_AUTH_TOKEN=<%= platform.auth_token %> 4 | 5 | MONGO_URI=<%= options.mongo_uri %> -------------------------------------------------------------------------------- /packages/generator-botkit/generators/twilio-sms/templates/features/twilio_features.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. 4 | */ 5 | const Twilio = require('twilio'); 6 | 7 | module.exports = function(controller) { 8 | 9 | controller.on('picture_message', async(bot, message) => { 10 | bot.reply(message, 'Nice pic!'); 11 | }); 12 | 13 | controller.hears('twiml','message', async(bot, message) => { 14 | 15 | let twiml = new Twilio.twiml.MessagingResponse(); 16 | twiml.message('This is a message sent using the HTTP response and TWIML'); 17 | bot.httpBody(twiml.toString()); 18 | 19 | }); 20 | 21 | } -------------------------------------------------------------------------------- /packages/generator-botkit/generators/web/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. 4 | */ 5 | 6 | var Generator = require('yeoman-generator'); 7 | var _ = require('underscore'); 8 | _.extend(Generator.prototype, require('yeoman-generator/lib/actions/install')); 9 | 10 | module.exports = class extends Generator { 11 | 12 | async prompting() { 13 | 14 | this.platform = await this.prompt([ 15 | ]); 16 | 17 | } 18 | 19 | writing() { 20 | 21 | this.fs.copy( 22 | this.templatePath('features'), 23 | this.destinationPath('features') 24 | ); 25 | 26 | this.fs.copy( 27 | this.templatePath('public'), 28 | this.destinationPath('public') 29 | ); 30 | 31 | this.fs.copy( 32 | this.templatePath('sass'), 33 | this.destinationPath('sass') 34 | ); 35 | 36 | this.fs.copyTpl( 37 | this.templatePath('.env'), 38 | this.destinationPath('.env'), 39 | { 40 | platform: this.platform, 41 | options: this.options, 42 | }, 43 | ); 44 | } 45 | 46 | install() { 47 | this.npmInstall(['botbuilder-adapter-web@latest']); 48 | 49 | // TODO: Install sass? 50 | // TODO: Add build step to package.json 51 | // TODO: Add public folder definition in bot.js and/or in a skill somewhere 52 | 53 | } 54 | 55 | }; 56 | -------------------------------------------------------------------------------- /packages/generator-botkit/generators/web/templates/.env: -------------------------------------------------------------------------------- 1 | 2 | MONGO_URI=<%= options.mongo_uri %> -------------------------------------------------------------------------------- /packages/generator-botkit/generators/web/templates/features/chat.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. 4 | */ 5 | const express = require('express'); 6 | const path = require('path'); 7 | 8 | module.exports = function(controller) { 9 | 10 | // make public/index.html available as localhost/index.html 11 | // by making the /public folder a static/public asset 12 | controller.publicFolder('/', path.join(__dirname,'..','public')); 13 | 14 | console.log('Chat with me: http://localhost:' + (process.env.PORT || 3000)); 15 | } -------------------------------------------------------------------------------- /packages/generator-botkit/generators/web/templates/features/typing.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This module demonstrates the use of the typing indicator in a conversation, and when using bot.reply 3 | * Tell your bot "typing dialog" or "typing reply" to see this in action. 4 | */ 5 | const { BotkitConversation } = require("botkit"); 6 | 7 | module.exports = function(controller) { 8 | 9 | let typing = new BotkitConversation('typing', controller); 10 | 11 | typing.say('I am going to type for a while now...'); 12 | typing.addAction('typing'); 13 | 14 | // start the typing indicator 15 | typing.addMessage({type: 'typing'}, 'typing'); 16 | // trigger a gotoThread, which gives us an opportunity to delay the next message 17 | typing.addAction('next_thread','typing'); 18 | 19 | typing.addMessage('typed!','next_thread'); 20 | 21 | // use the before handler to delay the next message 22 | typing.before('next_thread', async () => { 23 | return new Promise((resolve) => { 24 | // simulate some long running process 25 | setTimeout(resolve, 3000); 26 | }); 27 | }); 28 | 29 | controller.addDialog(typing); 30 | 31 | controller.hears('typing dialog', 'message', async (bot, message) => { 32 | await bot.beginDialog('typing'); 33 | }); 34 | 35 | controller.hears('typing reply', 'message', async (bot, message) => { 36 | 37 | await bot.reply(message, {type: 'typing'}); 38 | setTimeout(async () => { 39 | // will have to reset context because turn has now ended. 40 | await bot.changeContext(message.reference); 41 | await bot.reply(message, 'Typed!'); 42 | }, 1000); 43 | }); 44 | }; -------------------------------------------------------------------------------- /packages/generator-botkit/generators/web/templates/features/websocket_features.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. 4 | */ 5 | module.exports = function(controller) { 6 | 7 | if (controller.adapter.name === 'Web Adapter') { 8 | 9 | console.log('Loading sample web features...'); 10 | 11 | controller.hears(new RegExp('quick'), 'message', async (bot, message) => { 12 | 13 | await bot.reply(message,{ 14 | text: 'Here are some quick replies', 15 | quick_replies: [ 16 | { 17 | title: 'Foo', 18 | payload: 'foo', 19 | }, 20 | { 21 | title: 'Bar', 22 | payload: 'bar', 23 | } 24 | ] 25 | }); 26 | }); 27 | 28 | 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /packages/generator-botkit/generators/web/templates/public/css/embed.css: -------------------------------------------------------------------------------- 1 | #embedded_messenger { 2 | position: fixed; 3 | z-index: 1000; 4 | bottom: -400px; 5 | right: 2rem; 6 | height: 434px; 7 | transition: 0.5s ease-in-out bottom; 8 | } 9 | #embedded_messenger.active { 10 | bottom: 0; 11 | } 12 | #embedded_messenger iframe { 13 | height: 400px; 14 | width: 100%; 15 | border: 0; 16 | } 17 | #embedded_messenger #message_header { 18 | background: #000; 19 | padding: 0.5rem 1rem; 20 | color: #FFF; 21 | } 22 | 23 | /*# sourceMappingURL=embed.css.map */ 24 | -------------------------------------------------------------------------------- /packages/generator-botkit/generators/web/templates/public/css/embed.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sourceRoot":"","sources":["../../sass/embed.scss"],"names":[],"mappings":"AAEA;EAEE;EACA;EAEA;EACA;EAEA;EACA;;AAEA;EACE;;AAGF;EACE,QAlBK;EAmBL;EACA;;AAGF;EACE;EACA;EACA","file":"embed.css"} -------------------------------------------------------------------------------- /packages/generator-botkit/generators/web/templates/public/css/styles.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sourceRoot":"","sources":["../../sass/styles.scss","../../sass/_botkit.scss","../../sass/_chat.scss","../../sass/_home.scss"],"names":[],"mappings":"AAAA;ACSA;EACI;;;AAGJ;AAAA;EAEI;EACA;EACA;EACA;EACA;;;AAGJ;EAEI;EACA;EACA;;AAxBA;EACI;EACA;EACA;;;AAwBR;EAEI;EACA;EACA;;AA/BA;EACI;EACA;EACA;;AA8BJ;AAAA;AAAA;EAGI;;;AAIR;EACI;;;AAGJ;EACI;EACA;;AAEA;EACI;EACA;;;AAKR;EACI,OA1DY;;;AA6DhB;EACI;EACA;;;AAIA;EACI;EACA;;;AAIR;EACI;EACA;EACA;EACA;EACA;;AAEA;AAAA;EAEI;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAGJ;EACI;EACA,OArGI;;;AA0GhB;EACI;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;;AAEA;EAEI;;;AD/HR;AEIA;EACI,YAPS;EAQT;EACA;AAEA;AAAA;EAEA;EACA;AACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAEJ;EACI;;AAEJ;EACI;;AAIF;EACE;;AAEF;EACE;EACA;EACA;EACA;;AAIJ;EACE;EACA;EAEA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAIL;EACG;EACA;EACA;EACA;;AAED;EACG;EACA;;AAIN;EACI;EACA;;AACA;EACI;EACA;EACA;EACA;;AAEJ;EACG;EACA;EACA;EACA;EACA;EACA;;AAIP;EACI;EACA;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA,YA1GmB;EA2GnB,OA1Ga;EA2Gb;EACA;EACA;EACA;;AAIJ;EAEE,YArHqB;EAsHrB,OArHe;EAsHf;EACA;EACA;;AAEA;EACE;EACA;;AAKF;EACE;EACA;EACA,cAvIS;EAwIT;EACA,OAzIS;EA0IT;EACA;EACA;EACA;EACA;EACA;;AAIJ;EACI;EACA;;AAGJ;EACI;;AAGJ;EACI;EAEA,YD/JU;ECgKV,OA3Je;;AA+JnB;EACI;EACA;EACA;EACA;AAAmC;;AAEnC;EACI;EACA;EACA;;AACA;EACI;EACA;EACA;;AAIR;EACG;EACA;EACA;EACA,ODzLO;EC0LP;EACA;EACA;EACA;;AAEA;EACE,YDhMK;ECiML;;;AAQX;AACA;EACE;EACA;EACA;;AACA;EACE;EACA;EACA;EACA;EACA,kBAhNe;EAiNf;EACA;EACA;;AAEE;EACE;;AADF;EACE;;AADF;EACE;;;AAMR;EACE;IACE;;;AF3NJ;AGNA;EAEI;EACA;EACA;;AFFA;EACI;EACA;EACA;;;AEER;EACI;EACA;EACA;EACA;EAOA;;AALA;EACI;EACA;EACA;;;AAKR;EACI","file":"styles.css"} -------------------------------------------------------------------------------- /packages/generator-botkit/generators/web/templates/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Botkit Anywhere 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 |
13 |
14 | Disconnected... reconnecting! 15 |
16 |
17 | Offline! Reload to reconnect. 18 |
19 |
20 | Powered by Botkit Logo Botkit 21 |
22 |
23 |
24 |
25 |
26 | {{#if message.isTyping}} 27 |
28 | 29 | 30 | 31 |
32 | {{/if}} 33 | {{{message.html}}} 34 | 35 | {{#if message.open_link}} 36 | {{#if message.link_title}}{{message.link_title}}{{else}}{{message.open_link}}{{/if}} 37 | {{/if}} 38 |
39 | {{#message.files}} 40 |
41 | {{#if image}} 42 | {{{url}}} 43 | {{else}} 44 | {{{url}}} 45 | {{/if}} 46 |
47 | {{/message.files}} 48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | 56 | 57 |
58 |
59 |
60 |
61 | 62 | 63 | -------------------------------------------------------------------------------- /packages/generator-botkit/generators/web/templates/sass/_botkit.scss: -------------------------------------------------------------------------------- 1 | $botkit_purple: #a795ef; 2 | @mixin clearfix { 3 | &:after { 4 | content: ""; 5 | display: table; 6 | clear: both; 7 | } 8 | } 9 | 10 | * { 11 | box-sizing: border-box; 12 | } 13 | 14 | body, 15 | html { 16 | margin: 0; 17 | padding: 0; 18 | font-size: 18px; 19 | background-color: #FFF; 20 | font-family: 'helvetica', sans-serif; 21 | } 22 | 23 | .wrapper { 24 | @include clearfix; 25 | position: relative; 26 | max-width: 1000px; 27 | margin: 0 auto; 28 | } 29 | 30 | .box { 31 | @include clearfix; 32 | border: 2px solid #CCC; 33 | padding: 1rem calc(1rem - 2px); 34 | margin-bottom: 1rem; 35 | 36 | h1, 37 | h2, 38 | h3 { 39 | margin-top: 0; 40 | } 41 | } 42 | 43 | footer { 44 | text-align: center; 45 | } 46 | 47 | .hero { 48 | text-align: center; 49 | padding: 2rem; 50 | 51 | h1 { 52 | font-size: 4rem; 53 | margin: 0; 54 | 55 | } 56 | } 57 | 58 | a { 59 | color: $botkit_purple; 60 | } 61 | 62 | .copyurl { 63 | width: 100%; 64 | font-size: 1.25rem; 65 | } 66 | 67 | div.input { 68 | label { 69 | font-weight: bold; 70 | font-size: smaller; 71 | } 72 | } 73 | 74 | .addon { 75 | display: flex; 76 | border: 1px solid #999; 77 | border-radius: 6px; 78 | padding: 5px; 79 | background: #F0F0F0; 80 | 81 | input, 82 | textarea { 83 | flex-grow: 1; 84 | border: 0; 85 | background: transparent; 86 | } 87 | 88 | button { 89 | flex-grow: 0; 90 | background: transparent; 91 | border: 1px solid #999; 92 | border-radius: 6px; 93 | font-weight: bold; 94 | 95 | &.textarea { 96 | align-self: flex-start; 97 | padding: 0.5rem; 98 | } 99 | 100 | &:hover { 101 | background: #FFF; 102 | color: $botkit_purple; 103 | } 104 | } 105 | } 106 | 107 | div.hr { 108 | border: 1px dashed #ccc; 109 | width: 10%; 110 | margin: 4rem auto; 111 | height: 1px; 112 | } 113 | 114 | a.button { 115 | border: 2px solid $botkit_purple; 116 | font-weight: bold; 117 | // font-size: 4rem; 118 | margin: 0; 119 | border-radius: 3px; 120 | display: inline-block; 121 | padding: 0.5rem 2rem; 122 | text-align: center; 123 | text-decoration: none; 124 | // color: #FFF; 125 | box-shadow: 5px 5px 5px rgba(0,0,0,0.2); 126 | background-color: #FFF; 127 | transition: box-shadow 0.1s linear; 128 | 129 | &:hover { 130 | // background-color: rgba($botkit_purple, 0.1); 131 | box-shadow: 1px 1px 5px rgba(0,0,0,0.1); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /packages/generator-botkit/generators/web/templates/sass/_home.scss: -------------------------------------------------------------------------------- 1 | #home { 2 | @include clearfix; 3 | position: relative; 4 | max-width: 650px; 5 | margin: auto; 6 | } 7 | 8 | #homepage_bot { 9 | width: 400px; 10 | height: 450px; 11 | float: left; 12 | border: 5px solid #333; 13 | 14 | iframe { 15 | border: 0; 16 | height: 100%; 17 | width: 100%; 18 | } 19 | box-shadow: 5px 5px 5px rgba(0,0,0,0.5); 20 | } 21 | 22 | #welcome { 23 | margin-left: 440px; 24 | } 25 | -------------------------------------------------------------------------------- /packages/generator-botkit/generators/web/templates/sass/embed.scss: -------------------------------------------------------------------------------- 1 | $height: 400px; 2 | 3 | #embedded_messenger { 4 | 5 | position: fixed; 6 | z-index: 1000; 7 | 8 | bottom: -$height; 9 | right: 2rem; 10 | 11 | height: $height + 34; 12 | transition: 0.5s ease-in-out bottom; 13 | 14 | &.active { 15 | bottom: 0; 16 | } 17 | 18 | iframe { 19 | height: $height; 20 | width: 100%; 21 | border: 0; 22 | } 23 | 24 | #message_header { 25 | background: #000; 26 | padding: 0.5rem 1rem; 27 | color: #FFF; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /packages/generator-botkit/generators/web/templates/sass/styles.scss: -------------------------------------------------------------------------------- 1 | /* shared botkit ui styles */ 2 | @import "_botkit"; 3 | 4 | /* chat client */ 5 | @import "_chat"; 6 | 7 | /* special styles for homepage */ 8 | @import "_home"; 9 | -------------------------------------------------------------------------------- /packages/generator-botkit/generators/webex/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. 4 | */ 5 | var Generator = require('yeoman-generator'); 6 | var _ = require('underscore'); 7 | _.extend(Generator.prototype, require('yeoman-generator/lib/actions/install')); 8 | 9 | module.exports = class extends Generator { 10 | async prompting() { 11 | 12 | this.platform = await this.prompt([ 13 | { 14 | type: "input", 15 | name: "access_token", 16 | message: "Access Token", 17 | }, 18 | { 19 | type: "input", 20 | name: "public_address", 21 | message: "Public Address (in the form of https:// 2 | PUBLIC_ADDRESS=<%= platform.public_address %> 3 | 4 | MONGO_URI=<%= options.mongo_uri %> -------------------------------------------------------------------------------- /packages/generator-botkit/generators/webex/templates/features/webex_features.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. 4 | */ 5 | 6 | const { BotkitConversation } = require('botkit'); 7 | 8 | module.exports = function(controller) { 9 | 10 | const NEW_ROOM_DIALOG = 'new_room_dialog'; 11 | const dialog = new BotkitConversation(NEW_ROOM_DIALOG, controller); 12 | dialog.say('I created this room so we could continue our conversation in private...'); 13 | dialog.ask('How does that sound?', async(response, convo, bot) => { 14 | 15 | }, {key: 'how_it_sounds'}); 16 | dialog.say('Ah, {{vars.how_it_sounds}}, eh?'); 17 | dialog.say('I guess that is that.') 18 | 19 | controller.addDialog(dialog); 20 | 21 | controller.hears('delete','message,direct_message', async(bot, message) => { 22 | 23 | let reply = await bot.reply(message,'This message will be deleted in a few seconds.'); 24 | setTimeout(async () => { 25 | let res = await bot.deleteMessage(reply); 26 | }, 5000); 27 | 28 | }); 29 | 30 | 31 | controller.hears('create a room','message,direct_message', async(bot, message) => { 32 | 33 | // create a room 34 | let room = await bot.api.rooms.create({title: 'botkit test room'}); 35 | 36 | // add user as member (bot is automatically added) 37 | let membership2 = await bot.api.memberships.create({ 38 | roomId: room.id, 39 | personId: message.user, 40 | }); 41 | 42 | await bot.startConversationInRoom(room.id, message.user); 43 | await bot.beginDialog(NEW_ROOM_DIALOG); 44 | 45 | }); 46 | 47 | controller.on('memberships.created', async(bot, message) => { 48 | console.log('memberships created', message); 49 | }); 50 | 51 | 52 | } -------------------------------------------------------------------------------- /packages/generator-botkit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "generator-botkit", 3 | "version": "4.15.0", 4 | "description": "Automatically generate a Botkit application template for any supported platform", 5 | "scripts": { 6 | "pack": "npm pack" 7 | }, 8 | "files": [ 9 | "generators" 10 | ], 11 | "keywords": [ 12 | "yeoman-generator", 13 | "botkit", 14 | "bots", 15 | "chatbots" 16 | ], 17 | "author": "Microsoft Corp.", 18 | "license": "MIT", 19 | "homepage": "https://github.com/howdyai/botkit/blob/master/packages/generator-botkit#readme", 20 | "bugs": { 21 | "url": "https://github.com/howdyai/botkit/issues" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "https://github.com/howdyai/botkit.git" 26 | }, 27 | "dependencies": { 28 | "yeoman-generator": "5.6.1", 29 | "underscore": "1.13.1" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/generator-botkit/readme.md: -------------------------------------------------------------------------------- 1 | # generator-botkit 2 | **A [Yeoman](https://yeoman.io) template for generating [Botkit](https://npmjs.org/package/botkit) applications** 3 | 4 | ## Get Started 5 | 6 | Install Yeoman and this template: 7 | 8 | ```bash 9 | npm install -g yo generator-botkit 10 | ``` 11 | 12 | Create a new folder for your project: 13 | 14 | ```bash 15 | mkdir mybot 16 | cd mybot 17 | ``` 18 | 19 | From inside your project folder, generate the project: 20 | 21 | ```bash 22 | yo botkit 23 | ``` 24 | 25 | The generator will walk you through the process of configuring and installing your Botkit application. For each platform, a different set of API credentials and options will be collected. [Platform specific provisioning guides can be found in the Botkit docs site →](https://github.com/howdyai/botkit/blob/main/packages/docs/provisioning/index.md) 26 | 27 | Once the generator has completed its work, you will be left with a fully operational bot ready to be connected to the messaging platform. To start the application, run `npm start`. [Learn more about the anatomy of a Botkit application →](https://github.com/howdyai/botkit/blob/main/packages/docs/advanced.md#anatomy-of-a-botkit-app) 28 | 29 | The entire process is shown below: 30 | 31 | ![Botkit Yeoman generator in action](yeoman-generator.gif) 32 | 33 | ## Community & Support 34 | 35 | Join our thriving community of Botkit developers and bot enthusiasts at large. 36 | Over 10,000 members strong, [our Github site](https://github.com/howdyai/botkit) is 37 | _the place_ for people interested in the art and science of making bots. 38 | Come to ask questions, share your progress, and commune with your peers! 39 | 40 | You can also find help from members of the Botkit team [in our dedicated Cisco Spark room](https://eurl.io/#SyNZuomKx)! 41 | 42 | ## About Botkit 43 | 44 | Botkit is a part of the [Microsoft Bot Framework](https://dev.botframework.com). 45 | 46 | Want to contribute? [Read the contributor guide](https://github.com/howdyai/botkit/blob/master/CONTRIBUTING.md) 47 | 48 | Botkit is released under the [MIT Open Source license](https://github.com/howdyai/botkit/blob/master/LICENSE.md) -------------------------------------------------------------------------------- /packages/generator-botkit/yeoman-generator.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howdyai/botkit/b8f0e3e7fd9238a585ffdcec4a691acb23d0adcf/packages/generator-botkit/yeoman-generator.gif -------------------------------------------------------------------------------- /packages/testbot/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .DS_Store 3 | .vscode 4 | .env -------------------------------------------------------------------------------- /packages/testbot/botframework.js: -------------------------------------------------------------------------------- 1 | // const { FacebookAdapter } = require('botbuilder-adapter-facebook'); 2 | // const { SlackAdapter, SlackMessageTypeMiddleware, SlackIdentifyBotsMiddleware, SlackEventMiddleware } = require('botbuilder-adapter-slack'); 3 | // const { WebexAdapter } = require('botbuilder-adapter-webex'); 4 | // const { HangoutsAdapter } = require('botbuilder-adapter-hangouts'); 5 | // const { TwilioAdapter } = require('botbuilder-adapter-twilio-sms'); 6 | 7 | const { BotFrameworkAdapter } = require('botbuilder'); 8 | 9 | const restify = require('restify'); 10 | 11 | // Load process.env values from .env file 12 | require('dotenv').config(); 13 | 14 | const adapter = new BotFrameworkAdapter({ 15 | appId: process.env.APP_ID, 16 | appPassword: process.env.APP_SECRET 17 | }) 18 | 19 | // const adapter = new FacebookAdapter({ 20 | // verify_token: process.env.FACEBOOK_VERIFY_TOKEN, 21 | // app_secret: process.env.FACEBOOK_APP_SECRET, 22 | // access_token: process.env.FACEBOOK_ACCESS_TOKEN 23 | // }); 24 | 25 | // const adapter = new SlackAdapter({ 26 | // verificationToken: process.env.verificationToken, 27 | // clientSigningSecret: process.env.clientSigningSecret, 28 | // botToken: process.env.botToken, 29 | // }); 30 | 31 | // const adapter = new WebexAdapter({ 32 | // access_token: process.env.WEBEX_ACCESS_TOKEN, 33 | // public_address: process.env.WEBEX_PUBLIC_ADDRESS, 34 | // secret: 'random-secret-1234', 35 | // }) 36 | 37 | // const adapter = new HangoutsAdapter({ 38 | // token: process.env.GOOGLE_TOKEN, 39 | // google_auth_params: { 40 | // credentials: JSON.parse(process.env['GOOGLE_CREDS']) 41 | // } 42 | // }); 43 | 44 | // const adapter = new TwilioAdapter({ 45 | // twilio_number: process.env.TWILIO_NUMBER, 46 | // account_sid: process.env.TWILIO_ACCOUNT_SID, 47 | // auth_token: process.env.TWILIO_AUTH_TOKEN, 48 | // }); 49 | 50 | 51 | const server = restify.createServer(); 52 | server.use(restify.plugins.bodyParser()); 53 | 54 | // adapter.registerWebhookSubscription('/api/messages'); 55 | 56 | server.get('/api/messages', (req, res) => { 57 | console.log('QUERY', req.query); 58 | 59 | adapter.processActivity(req, res, async(context) => { 60 | // do your bot logic here! 61 | 62 | 63 | console.log('GOT INCOMING ACTIVITY', context.activity); 64 | if (context.activity.type === 'message') { 65 | await context.sendActivity('Received an message: ' + context.activity.text); 66 | } 67 | 68 | let api = await adapter.getAPI(context.activity); 69 | let id = await api.callAPI('/me','GET', {}); 70 | console.log('ID FROM API', id); 71 | }); 72 | }); 73 | 74 | server.listen(3000); -------------------------------------------------------------------------------- /packages/testbot/custom_express.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This file demonstrates how to use your own instance of Express 4 | along with Botkit and one or more adapters. 5 | 6 | This is also a good starting point for using multiple adapters. 7 | */ 8 | const { Botkit } = require('botkit'); 9 | const http = require('http'); 10 | const express = require('express'); 11 | const bodyParser = require('body-parser'); 12 | 13 | // Configure an Express app 14 | const app = express(); 15 | 16 | // Configure Botkit WITHOUT a webserver. 17 | // disable_webserver turns off the internal Express. 18 | // This means we need to configure our own webhook endpoint. 19 | // In this instance, we are configuring a Bot Framework adapter. 20 | const controller = new Botkit({ 21 | disable_webserver: true, 22 | adapterConfig: { 23 | appId: process.env.APP_ID, 24 | appPassword: process.env.APP_PASSWORD, 25 | } 26 | }); 27 | 28 | 29 | // some options for express 30 | // this setup is identical to the way Botkit configures itself 31 | const _config = 32 | { 33 | jsonLimit: '100kb', 34 | urlEncodedLimit: '100kb', 35 | webhook_uri: '/api/messages', 36 | }; 37 | 38 | // capture raw body in addition to the parsed content 39 | app.use((req, res, next) => { 40 | req.rawBody = ''; 41 | req.on('data', function(chunk) { 42 | req.rawBody += chunk; 43 | }); 44 | next(); 45 | }); 46 | 47 | app.use(bodyParser.json({ limit: _config.jsonLimit })); 48 | app.use(bodyParser.urlencoded({ limit: _config.urlEncodedLimit, extended: true })); 49 | 50 | app.post(_config.webhook_uri, (req, res) => { 51 | // Allow the Botbuilder middleware to fire. 52 | // this middleware is responsible for turning the incoming payload into a BotBuilder Activity 53 | // which we can then use to turn into a BotkitMessage 54 | controller.adapter.processActivity(req, res, controller.handleTurn.bind(controller)).catch((err) => { 55 | console.error('Experienced an error inside the turn handler', err); 56 | throw err; 57 | }); 58 | }); 59 | 60 | // Define your bot handlers... 61 | controller.on('message', async(bot, message) => { 62 | await bot.reply(message, 'Received.'); 63 | }) 64 | 65 | 66 | // fire up the webserver... 67 | const server = http.createServer(app); 68 | server.listen(process.env.port || process.env.PORT || 3000, () => { 69 | console.log(`Webhook endpoint online: http://localhost:${ process.env.PORT || 3000 }${ _config.webhook_uri }`); 70 | }); 71 | -------------------------------------------------------------------------------- /packages/testbot/features/bot_inspector_mode.js: -------------------------------------------------------------------------------- 1 | /** 2 | * this module if installed into a botkit v4+ app will enable "Bot Inspector" mode in Bot Framework Emulator 3 | * This allows you to connect to the bot app running locally with emulator to inspect messages 4 | * as they come and go to the messaging platform. 5 | * Read more here: 6 | * https://github.com/Microsoft/botframework/blob/master/README.md#bot-inspector-new---preview 7 | */ 8 | // import botbuilder 4.4 library 9 | const { InspectionMiddleware, InspectionState, BotFrameworkAdapter } = require('botbuilder'); 10 | 11 | module.exports = function(controller) { 12 | 13 | // Bot Framework inspection middleware allows you to debug from the emulator 14 | let inspectionState = new InspectionState(controller.storage); 15 | let inspector = new InspectionMiddleware(inspectionState, undefined, controller.conversationState); 16 | controller.adapter.use(inspector); 17 | 18 | controller.ready(function() { 19 | // create an alternate adapter 20 | const sidecar = new BotFrameworkAdapter(); 21 | // use the same middleware instance! 22 | sidecar.use(inspector) 23 | 24 | // set up an alternate route for the emulator to connect to 25 | console.log(`Use the Bot Framework Emulator in Inspect mode: http://localhost:${ process.env.PORT || 3000 }/api/sidecar`); 26 | controller.webserver.post('/api/sidecar', (req, res) => { 27 | sidecar.processActivity(req, res, async(turnContext) => { 28 | // noop 29 | }); 30 | }); 31 | }); 32 | 33 | } -------------------------------------------------------------------------------- /packages/testbot/features/convo_test.js: -------------------------------------------------------------------------------- 1 | const { BotkitConversation } = require('botkit'); 2 | 3 | module.exports = function(controller) { 4 | 5 | 6 | // yes runs normally before it starts 7 | // yes runs when using an action 8 | // yes calls when looping itself 9 | // yes runs when a handler is passed in as a function and inside it calls convo.gotothread 10 | // runs when an onchange handler calls gotothread 11 | // yes runs in an onbefore 12 | 13 | let convo = new BotkitConversation('test_convo', controller); 14 | controller.addDialog(convo); 15 | 16 | convo.before('default', async(convo, bot) => { 17 | await bot.say('BEFORE DEFAULT!'); 18 | convo.setVar('count', 0); 19 | }); 20 | 21 | convo.say('This is the default thread.'); 22 | convo.addAction('second'); 23 | 24 | convo.before('second', async(convo, bot) => { 25 | await bot.say('BEFORE SECOND'); 26 | convo.setVar('count', convo.vars.count + 1); 27 | if (convo.vars.count > 2) { 28 | await convo.gotoThread('third'); 29 | } 30 | }); 31 | convo.addMessage('This is the second thread round {{vars.count}}', 'second'); 32 | convo.addAction('second','second'); 33 | 34 | convo.before('third', async(convo, bot) => { 35 | await bot.say('BEFORE THIRD'); 36 | }); 37 | 38 | convo.addMessage('This is third','third'); 39 | convo.addQuestion('What do you think', async(response, convo, bot) => { 40 | await convo.gotoThread('fourth'); 41 | }, 'think', 'third'); 42 | 43 | convo.before('fourth', async(convo, bot) => { 44 | await bot.say('BEFORE FOURTH!!!'); 45 | }); 46 | convo.addMessage('this is the fourth thread', 'fourth'); 47 | convo.addQuestion('Will this work?', [], 'work', 'fourth'); 48 | 49 | convo.onChange('work', async(response, convo, bot) => { 50 | await convo.gotoThread('fifth'); 51 | }); 52 | 53 | convo.before('fifth', async(convo, bot) => { 54 | await bot.say('BEFORE FIFTH!!!'); 55 | }); 56 | convo.addMessage('this is the fifth thread','fifth'); 57 | convo.addAction('default', 'fifth'); 58 | 59 | 60 | 61 | 62 | controller.hears('convo_test', 'direct_message,message', async(bot, message) => { 63 | await bot.beginDialog('test_convo'); 64 | }); 65 | 66 | } -------------------------------------------------------------------------------- /packages/testbot/features/dynamic_attachments.js: -------------------------------------------------------------------------------- 1 | const { BotkitConversation } = require('botkit'); 2 | 3 | module.exports = function(controller) { 4 | 5 | let dialog = new BotkitConversation('dynamic_attachments', controller); 6 | dialog.ask({ 7 | text: 'What is your name?', 8 | quick_replies: [ 9 | { 10 | title: '{{vars.default_name}}', 11 | payload: '{{vars.default_name}}', 12 | } 13 | ] 14 | }, [], 'name'); 15 | 16 | dialog.ask({ 17 | text: 'Your name is:', 18 | quick_replies: async(line, vars) => { 19 | return [ 20 | { 21 | title: 'Foo', 22 | payload: 'foo', 23 | }, 24 | { 25 | title: 'Bar', 26 | payload: 'bar', 27 | }, 28 | { 29 | title: vars.name, 30 | payload: vars.name 31 | } 32 | ] 33 | } 34 | }, [], 'menu'); 35 | 36 | dialog.say({ 37 | text: 'Does this sound right?', 38 | attachments: async(line, vars) => { 39 | return [ 40 | { 41 | title: `Your name is ${vars.name} and you chose ${vars.menu}` 42 | } 43 | ]; 44 | } 45 | }); 46 | controller.addDialog(dialog); 47 | 48 | controller.hears('dynamic', 'message,direct_message,direct_mention', async(bot, message) => { 49 | await bot.beginDialog('dynamic_attachments', {default_name: 'BEN'}); 50 | }); 51 | 52 | } -------------------------------------------------------------------------------- /packages/testbot/features/flip_table.js: -------------------------------------------------------------------------------- 1 | const request = require('request'); 2 | module.exports = function(controller) { 3 | 4 | controller.hears(['flip'], 'message', async (bot, message) => { 5 | request.get('http://www.tableflipper.com/json', (e, r, json) => { 6 | const url = JSON.parse(json); 7 | bot.reply(message,url.gif); 8 | }); 9 | }); 10 | } -------------------------------------------------------------------------------- /packages/testbot/features/get_reference.js: -------------------------------------------------------------------------------- 1 | const { TurnContext } = require('botbuilder'); 2 | 3 | module.exports = function(controller) { 4 | 5 | controller.hears('reference','message', async(bot, message)=> { 6 | 7 | const reference = TurnContext.getConversationReference(message.incoming_message); 8 | await bot.reply(message, JSON.stringify(reference, null, 2)); 9 | 10 | }); 11 | 12 | controller.hears('thread me', 'message', async (bot, message) => { 13 | 14 | await bot.startConversationInThread(message.channel, message.user, message.incoming_message.channelData.ts); 15 | await bot.beginDialog('waterfall_sample'); 16 | 17 | }); 18 | 19 | 20 | controller.hears('thread it', 'message', async (bot, message) => { 21 | await bot.replyInThread(message,'THREADED'); 22 | }); 23 | 24 | controller.hears('im me', 'message', async(bot, message) => { 25 | 26 | await bot.startPrivateConversation(message.user); 27 | await bot.beginDialog('waterfall_sample') 28 | 29 | }); 30 | 31 | 32 | controller.hears('webex me', 'message', async(bot, message) => { 33 | // switch to a 1:1 34 | delete message.incoming_message.conversation; 35 | const response = await bot.reply(message, ''); 36 | console.log('GOT REPLY RESPONSE', response); 37 | }); 38 | controller.hears('\<\#.*?\>', 'message', async(bot, message) => { 39 | 40 | const channel = message.text.replace(/.*?\<\#(.*?)\|.*?\>.*/,"$1"); 41 | 42 | await bot.startConversationInChannel(channel, message.user); 43 | await bot.beginDialog('waterfall_sample') 44 | 45 | }); 46 | 47 | // async function foo() { 48 | // let bot = await controller.spawn(); 49 | // await bot.startPrivateConversation('U024F7C89'); 50 | // bot.say('I BOOTED'); 51 | // } 52 | 53 | // foo(); 54 | 55 | } -------------------------------------------------------------------------------- /packages/testbot/features/hear_patterns.js: -------------------------------------------------------------------------------- 1 | module.exports = function(controller) { 2 | 3 | // use a function to match a condition in the message 4 | controller.hears(async(message) => message.text && message.text.toLowerCase() === 'foo', ['message'], async (bot, message) => { 5 | await bot.reply(message, 'I heard foo via a function test'); 6 | }); 7 | 8 | // use a regular expression to match the text of the message 9 | controller.hears(new RegExp(/^\d+$/), ['message','direct_message'], async function(bot, message) { 10 | await bot.reply(message,{ text: 'I HEARD A NUMBER' }); 11 | }); 12 | 13 | // match any one of set of mixed patterns like a string, a regular expression 14 | controller.hears(['allcaps', new RegExp(/^[A-Z\s]+$/)], ['message','direct_message'], async function(bot, message) { 15 | await bot.reply(message,{ text: 'I HEARD ALL CAPS' }); 16 | }); 17 | 18 | } -------------------------------------------------------------------------------- /packages/testbot/features/interruptions.js: -------------------------------------------------------------------------------- 1 | const { BotkitConversation} = require('botkit'); 2 | 3 | module.exports = function(controller) { 4 | 5 | const dialog = new BotkitConversation('HELPDIALOG', controller); 6 | 7 | dialog.ask('What can I help with?', [], 'subject'); 8 | dialog.say('HRRM! What do I know about {{vars.subject}}?'); 9 | dialog.addAction('display_results'); 10 | 11 | dialog.before('display_results', async(convo, bot) => { 12 | convo.setVar('results', 'KNOWLEDGE BASE EMPTY'); 13 | }); 14 | 15 | dialog.addMessage('Here is what I know: {{vars.results}}', 'display_results'); 16 | 17 | controller.addDialog(dialog); 18 | 19 | // hear the word help, and interrupt whatever is happening to handle it first. 20 | controller.interrupts(async(message) => { return message.intent==='help' }, 'message', async(bot, message) => { 21 | await bot.reply(message,'I heard you need help more than anything else!'); 22 | await bot.beginDialog('HELPDIALOG'); 23 | }); 24 | 25 | 26 | controller.interrupts(['quit','cancel'], 'message', async (bot, message) => { 27 | 28 | await bot.reply(message,'LETS QUIT THIS JUNK!'); 29 | await bot.cancelAllDialogs(); 30 | }); 31 | 32 | 33 | } -------------------------------------------------------------------------------- /packages/testbot/features/looping_dialog.js: -------------------------------------------------------------------------------- 1 | const { BotkitConversation } = require('botkit'); 2 | 3 | module.exports = function(controller) { 4 | 5 | let dialog = new BotkitConversation('looping', controller); 6 | 7 | // define the questions in a variable 8 | dialog.before('default', async(convo, bot) => { 9 | // set list of questions 10 | convo.setVar('questions', ['What is your name?','What is your quest?', 'What is the airspeed of an unladen swallow?']); 11 | convo.setVar('question_index', 0); 12 | }); 13 | 14 | // start off with an intro message 15 | dialog.say('I have some questions for you...'); 16 | // start the loop 17 | dialog.addAction('question-loop'); 18 | 19 | dialog.before('question-loop', async(convo, bot) => { 20 | 21 | if (convo.vars.question_index < convo.vars.questions.length) { 22 | convo.setVar('question', convo.vars.questions[convo.vars.question_index]); 23 | } else { 24 | await convo.gotoThread('end'); 25 | } 26 | 27 | }); 28 | 29 | // use a variable for the question text: 30 | dialog.addQuestion('{{vars.question}}', async(response, convo, bot) => { 31 | 32 | // capture in answer_x 33 | let key = 'answer_' + convo.vars.question_index; 34 | convo.setVar(key, response); 35 | convo.setVar('question_index', convo.vars.question_index + 1); 36 | 37 | }, 'answer','question-loop'); 38 | dialog.addAction('question-loop', 'question-loop'); 39 | 40 | dialog.addMessage('ALL DONE!', 'end'); 41 | 42 | dialog.after(async(results, bot) => { 43 | console.log('RESULTS OF LOOPING DIALOG', results); 44 | }); 45 | 46 | controller.addDialog(dialog); 47 | 48 | controller.hears('loop', 'message,direct_message', async(bot, message) => { 49 | await bot.beginDialog('looping'); 50 | }); 51 | 52 | 53 | } -------------------------------------------------------------------------------- /packages/testbot/features/luis_recognizer.js: -------------------------------------------------------------------------------- 1 | const { LuisRecognizer } = require('botbuilder-ai'); 2 | 3 | module.exports = function(controller) { 4 | 5 | if (process.env.LUIS_APPLICATIONID) { 6 | 7 | const recognizer = new LuisRecognizer({ 8 | applicationId: process.env.LUIS_APPLICATIONID, 9 | endpointKey: process.env.LUIS_ENDPOINTKEY, 10 | }); 11 | 12 | 13 | controller.middleware.ingest.use(async (bot, message, next) => { 14 | if (message.incoming_message.type === 'message') { 15 | const results = await recognizer.recognize(message.context); 16 | message.intent = LuisRecognizer.topIntent(results, 'None', process.env.LUIS_THRESHOLD || 0.7); 17 | console.log('recognized',message.intent); 18 | } 19 | 20 | next(); 21 | }); 22 | 23 | controller.hears(async(message) => { return (message.intent && message.intent==='fart') }, 'message', async(bot, message) => { 24 | bot.reply(message,':dash: ew') 25 | }); 26 | 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /packages/testbot/features/middlewares.js: -------------------------------------------------------------------------------- 1 | module.exports = function(controller) { 2 | 3 | controller.middleware.receive.use((bot, message, next) => { 4 | console.log('IN > ', message.text, message.type); 5 | next(); 6 | }); 7 | 8 | controller.middleware.send.use((bot, message, next) => { 9 | console.log('OUT > ', message.text, message.channelData && message.channelData.quick_replies ? message.channelData.quick_replies : null, message.channelData && message.channelData.attachments ? message.channelData.attachments : null); 10 | next(); 11 | }); 12 | 13 | controller.middleware.ingest.use(async (bot, message, next) => { 14 | message.touchedbyMiddleware = true; 15 | next(); 16 | }); 17 | 18 | } -------------------------------------------------------------------------------- /packages/testbot/features/random_text_middleware.js: -------------------------------------------------------------------------------- 1 | module.exports = function(controller) { 2 | 3 | 4 | controller.middleware.send.use((bot, message, next) => { 5 | 6 | if (Array.isArray(message.text)) { 7 | message.text = message.text[Math.floor(Math.random() * message.text.length)]; 8 | } 9 | next(); 10 | 11 | }); 12 | 13 | controller.hears('random','message', async(bot, message) => { 14 | 15 | bot.reply(message,{ 16 | text: [ 17 | 'Random response 1', 18 | 'Random response 2', 19 | 'Random response 3' 20 | ] 21 | }); 22 | 23 | }); 24 | 25 | } -------------------------------------------------------------------------------- /packages/testbot/features/shutdown.js: -------------------------------------------------------------------------------- 1 | module.exports = function(controller) { 2 | controller.hears('shutdown', 'message', async(bot, message) => { 3 | controller.shutdown(); 4 | }); 5 | 6 | controller.on('shutdown', async() => { 7 | console.log('SHUTTING DOWN APP!'); 8 | }); 9 | } -------------------------------------------------------------------------------- /packages/testbot/features/test_convo.js: -------------------------------------------------------------------------------- 1 | module.exports = function(controller) { 2 | // controller.cms.before('tests','default', async function (bot, convo) { 3 | // convo.vars.bar = 'foo'; 4 | // convo.vars.foo = 'bar'; 5 | 6 | // await bot.say('A'); 7 | // }); 8 | 9 | // controller.cms.before('tests','default', async function (bot, convo) { 10 | // convo.vars.handler1 = true; 11 | // convo.gotoThread('new thread'); 12 | 13 | // await bot.say('B'); 14 | 15 | // }); 16 | 17 | // controller.cms.before('tests','new thread', async function (bot, convo) { 18 | // convo.vars.handler2 = 'true'; 19 | // convo.gotoThread('new thread 2'); 20 | 21 | // await bot.say('C'); 22 | 23 | // }); 24 | 25 | // controller.cms.onChange('tests', 'question_1', async function (bot, convo, value) { 26 | // console.log('CHANGED QUESTION_1 VALUE', value); 27 | // convo.vars.question_1 = 'OVERRIDDEN'; 28 | // convo.gotoThread('final'); 29 | 30 | // await bot.say('D'); 31 | 32 | // }); 33 | 34 | // controller.cms.after('tests', async function (bot, results) { 35 | // // make sure all vars are set 36 | // if (!(results.bar && results.foo && results.handler1 && results.handler2)) { 37 | // throw new Error('FAILED TO AGGREGATE VARS THROUGH STEPS'); 38 | // } 39 | // console.log('TESTS SCRIPT IS DONE!', results); 40 | 41 | // await bot.say('E'); 42 | 43 | // }); 44 | 45 | } -------------------------------------------------------------------------------- /packages/testbot/features/twilio_features.js: -------------------------------------------------------------------------------- 1 | const Twilio = require('twilio'); 2 | 3 | module.exports = function(controller) { 4 | 5 | if (controller.adapter.name === 'Twilio SMS Adapter') { 6 | controller.on('picture_message', async(bot, message) => { 7 | bot.reply(message, 'Nice pic!'); 8 | }); 9 | 10 | controller.hears('twiml','message', async(bot, message) => { 11 | 12 | let twiml = new Twilio.twiml.MessagingResponse(); 13 | twiml.message('This is a message sent using the HTTP response and TWIML'); 14 | bot.httpBody(twiml.toString()); 15 | 16 | }); 17 | } 18 | } -------------------------------------------------------------------------------- /packages/testbot/features/typescript.ts: -------------------------------------------------------------------------------- 1 | import { Botkit } from 'botkit'; 2 | import { SlackBotWorker } from 'botbuilder-slack'; 3 | 4 | module.exports = function(controller: Botkit) { 5 | 6 | controller.on('direct_message', async(bot: SlackBotWorker, message: any): Promise => { 7 | 8 | // intellisene! 9 | bot.reply(message, { text: 'foo' }); 10 | 11 | // stop processing this message once received here. 12 | return false; 13 | }); 14 | 15 | 16 | } -------------------------------------------------------------------------------- /packages/testbot/features/waterfall_dialog.js: -------------------------------------------------------------------------------- 1 | /* This is a sample feature module that uses Bot Builder Waterfall dialogs */ 2 | 3 | const { WaterfallDialog, TextPrompt } = require('botbuilder-dialogs'); 4 | 5 | const DIALOG_ID = 'waterfall_sample'; 6 | const PROMPT_ID = 'waterfall_prompt'; 7 | const sample_waterfall = new WaterfallDialog(DIALOG_ID, [ 8 | 9 | async (step) => { 10 | await step.context.sendActivity('This is the first step of a waterfall dialog'); 11 | return await step.next(); 12 | }, 13 | async (step) => { 14 | return await step.prompt(PROMPT_ID,'Say something! I will receive your input.'); 15 | }, 16 | async (step) => { 17 | const result = step.result; 18 | step.values.something = result; 19 | await step.context.sendActivity('You said ' + result); 20 | return await step.next(); 21 | }, 22 | async (step) => { 23 | await step.context.sendActivity('Done'); 24 | return await step.endDialog(step.values); 25 | } 26 | ]); 27 | 28 | module.exports = function(controller) { 29 | 30 | controller.addDialog(new TextPrompt(PROMPT_ID)); 31 | controller.addDialog(sample_waterfall); 32 | 33 | controller.afterDialog(sample_waterfall, async(bot, results) => { 34 | 35 | console.log('WATERFALL DIALOG HAS COMPLETED WITH RESULTS', results); 36 | 37 | }); 38 | 39 | controller.hears(['waterfall'], 'message, direct_message', async(bot) => { 40 | await bot.beginDialog(DIALOG_ID, {}); 41 | }); 42 | 43 | } -------------------------------------------------------------------------------- /packages/testbot/features/z_fallback.js: -------------------------------------------------------------------------------- 1 | const { BotkitConversation } = require('botkit'); 2 | module.exports = function(controller) { 3 | 4 | controller.on('message', async (bot, message) => { 5 | await bot.reply(message, { text: 'Echo: ' + message.text}); 6 | }); 7 | } -------------------------------------------------------------------------------- /packages/testbot/multiadapter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a sample implementation of a multi-adapter bot 3 | * This demonstrates using the built-in Bot Framework adapter along side the Botkti webchat AND Facebook adapters. 4 | */ 5 | 6 | const { Botkit } = require('botkit'); 7 | 8 | const { WebAdapter } = require('botbuilder-adapter-web'); 9 | const { FacebookAdapter, FacebookEventTypeMiddleware } = require('botbuilder-adapter-facebook'); 10 | 11 | // Load process.env values from .env file 12 | require('dotenv').config(); 13 | 14 | 15 | // set up Web Adapter 16 | const web_adapter = new WebAdapter({}); 17 | 18 | // Set up Facebook Adapter 19 | const facebook_adapter = new FacebookAdapter({ 20 | enable_incomplete: true, 21 | verify_token: process.env.FACEBOOK_VERIFY_TOKEN, 22 | access_token: process.env.FACEBOOK_ACCESS_TOKEN, 23 | app_secret: process.env.FACEBOOK_APP_SECRET, 24 | app_id: process.env.FACEBOOK_APP_ID, 25 | }) 26 | 27 | // emit events based on the type of facebook event being received 28 | facebook_adapter.use(new FacebookEventTypeMiddleware()); 29 | 30 | 31 | // boot controller with the built-in bot framework adapter that works with emulator and Azure bot service 32 | // you could also pass in one of the above adapters as the "default" adapter and bind secondary as below... 33 | const controller = new Botkit({ 34 | debug: true, 35 | webhook_uri: '/api/messages', 36 | webserver_middlewares: [(req, res, next) => { console.log('REQ > ', req.url); next(); }], 37 | }); 38 | 39 | controller.ready(() => { 40 | 41 | // Make the web chat work 42 | // make the web chat available at http://localhost:3000 43 | controller.publicFolder('/',__dirname + '/public'); 44 | // bind websocket to the webserver 45 | web_adapter.createSocketServer(controller.http, {}, controller.handleTurn.bind(controller)); 46 | 47 | 48 | // Make the Facebook adapter work 49 | // we do this by creating a SECOND webhook endpoint 50 | // and calling the facebook_adapter directly as below. 51 | // this is what Botkit does internally, see: 52 | // https://github.com/howdyai/botkit/blob/master/packages/botkit/src/core.ts#L675 53 | controller.webserver.post('/api/facebook', (req, res) => { 54 | facebook_adapter.processActivity(req, res, controller.handleTurn.bind(controller)).catch((err) => { 55 | console.error('Experienced an error inside the turn handler', err); 56 | throw err; 57 | }); 58 | }); 59 | 60 | controller.on('message', async (bot, message) => { 61 | const adapter_type = bot.getConfig('context').adapter.name; 62 | await bot.reply(message,`I heard ya on my ${ adapter_type } adapter`); 63 | }); 64 | 65 | }); -------------------------------------------------------------------------------- /packages/testbot/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "testbot", 3 | "version": "1.0.0", 4 | "description": "a test harness for testing in-progress changes to botkit", 5 | "main": "bot.js", 6 | "scripts": { 7 | "start": "node bot.js" 8 | }, 9 | "author": "benbrown@gmail.com", 10 | "license": "MIT", 11 | "dependencies": { 12 | "botbuilder": "^4.15.0", 13 | "botbuilder-ai": "^4.15.0", 14 | "botbuilder-dialogs": "^4.15.0", 15 | "botbuilder-adapter-facebook": "^1.0.0", 16 | "botbuilder-adapter-hangouts": "^1.0.0", 17 | "botbuilder-adapter-slack": "^1.0.0", 18 | "botbuilder-adapter-twilio-sms": "^1.0.0", 19 | "botbuilder-adapter-web": "^1.0.0", 20 | "botbuilder-adapter-webex": "^1.0.0", 21 | "botbuilder-dialogs-botkit-cms": "0.0.1", 22 | "botbuilder-storage-mongodb": "^0.9.5", 23 | "botkit": "^4.15.0", 24 | "botkit-plugin-cms": "^1.0.3", 25 | "dotenv": "^6.2.0", 26 | "express-basic-auth": "^1.1.6", 27 | "restify": "^8.4.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/testbot/plugins/verbose/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function(botkit) { 2 | 3 | return { 4 | name: 'Verbose Console Logger', 5 | init: function(botkit) { 6 | // Log requests to console using an Express middleware 7 | if (botkit.webserver) { 8 | botkit.webserver.use(function(req, res, next) { 9 | console.log('> ', req.url); 10 | next(); 11 | }); 12 | } 13 | 14 | }, 15 | middlewares: { 16 | receive: [ 17 | function(bot, message, next) { 18 | console.log(`RCVD > ${ message.type } >`, message.text); 19 | next(); 20 | } 21 | ], 22 | send: [ 23 | function(bot, message, next) { 24 | console.log('SENT > ', message.text); 25 | next(); 26 | } 27 | ] 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /packages/testbot/plugins/verbose/public/test.txt: -------------------------------------------------------------------------------- 1 | this is a test!!! DOT TEXT. -------------------------------------------------------------------------------- /packages/testbot/plugins/verbose/views/layout.hbs: -------------------------------------------------------------------------------- 1 | 2 | TEST 3 | 4 | 5 | 6 |
header
7 | {{body}} 8 |
footer
9 | 10 | -------------------------------------------------------------------------------- /packages/testbot/plugins/verbose/views/template.hbs: -------------------------------------------------------------------------------- 1 |

this is the homepage tempalte

> -------------------------------------------------------------------------------- /packages/testbot/public/css/embed.css: -------------------------------------------------------------------------------- 1 | #embedded_messenger { 2 | position: fixed; 3 | z-index: 1000; 4 | bottom: -400px; 5 | right: 2rem; 6 | height: 434px; 7 | transition: 0.5s ease-in-out bottom; 8 | } 9 | #embedded_messenger.active { 10 | bottom: 0; 11 | } 12 | #embedded_messenger iframe { 13 | height: 400px; 14 | width: 100%; 15 | border: 0; 16 | } 17 | #embedded_messenger #message_header { 18 | background: #000; 19 | padding: 0.5rem 1rem; 20 | color: #FFF; 21 | } 22 | 23 | /*# sourceMappingURL=embed.css.map */ 24 | -------------------------------------------------------------------------------- /packages/testbot/public/css/embed.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sourceRoot":"","sources":["../../sass/embed.scss"],"names":[],"mappings":"AAEA;EAEE;EACA;EAEA;EACA;EAEA;EACA;;AAEA;EACE;;AAGF;EACE,QAlBK;EAmBL;EACA;;AAGF;EACE;EACA;EACA","file":"embed.css"} -------------------------------------------------------------------------------- /packages/testbot/public/css/styles.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sourceRoot":"","sources":["../../sass/styles.scss","../../sass/_botkit.scss","../../sass/_chat.scss","../../sass/_home.scss"],"names":[],"mappings":"AAAA;ACSA;EACI;;;AAGJ;AAAA;EAEI;EACA;EACA;EACA;EACA;;;AAGJ;EAEI;EACA;EACA;;AAxBA;EACI;EACA;EACA;;;AAwBR;EAEI;EACA;EACA;;AA/BA;EACI;EACA;EACA;;AA8BJ;AAAA;AAAA;EAGI;;;AAIR;EACI;;;AAGJ;EACI;EACA;;AAEA;EACI;EACA;;;AAKR;EACI,OA1DY;;;AA6DhB;EACI;EACA;;;AAIA;EACI;EACA;;;AAIR;EACI;EACA;EACA;EACA;EACA;;AAEA;AAAA;EAEI;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAGJ;EACI;EACA,OArGI;;;AA0GhB;EACI;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;;AAEA;EAEI;;;AD/HR;AEIA;EACI,YAPS;EAQT;EACA;AAEA;AAAA;EAEA;EACA;AACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAEJ;EACI;;AAEJ;EACI;;AAIF;EACE;;AAEF;EACE;EACA;EACA;EACA;;AAIJ;EACE;EACA;EAEA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAIL;EACG;EACA;EACA;EACA;;AAED;EACG;EACA;;AAIN;EACI;EACA;;AACA;EACI;EACA;EACA;EACA;;AAEJ;EACG;EACA;EACA;EACA;EACA;EACA;;AAIP;EACI;EACA;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA,YA1GmB;EA2GnB,OA1Ga;EA2Gb;EACA;EACA;EACA;;AAIJ;EAEE,YArHqB;EAsHrB,OArHe;EAsHf;EACA;EACA;;AAEA;EACE;EACA;;AAKF;EACE;EACA;EACA,cAvIS;EAwIT;EACA,OAzIS;EA0IT;EACA;EACA;EACA;EACA;EACA;;AAIJ;EACI;EACA;;AAGJ;EACI;;AAGJ;EACI;EAEA,YD/JU;ECgKV,OA3Je;;AA+JnB;EACI;EACA;EACA;EACA;AAAmC;;AAEnC;EACI;EACA;EACA;;AACA;EACI;EACA;EACA;;AAIR;EACG;EACA;EACA;EACA,ODzLO;EC0LP;EACA;EACA;EACA;;AAEA;EACE,YDhMK;ECiML;;;AAQX;AACA;EACE;EACA;EACA;;AACA;EACE;EACA;EACA;EACA;EACA,kBAhNe;EAiNf;EACA;EACA;;AAEE;EACE;;AADF;EACE;;AADF;EACE;;;AAMR;EACE;IACE;;;AF3NJ;AGNA;EAEI;EACA;EACA;;AFFA;EACI;EACA;EACA;;;AEER;EACI;EACA;EACA;EACA;EAOA;;AALA;EACI;EACA;EACA;;;AAKR;EACI","file":"styles.css"} -------------------------------------------------------------------------------- /packages/testbot/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Botkit Anywhere 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 |
13 |
14 | Disconnected... reconnecting! 15 |
16 |
17 | Offline! Reload to reconnect. 18 |
19 |
20 | Powered by Botkit Logo Botkit 21 |
22 |
23 |
24 |
25 |
26 | {{#if message.isTyping}} 27 |
28 | 29 | 30 | 31 |
32 | {{/if}} 33 | {{{message.html}}} 34 | 35 | {{#if message.open_link}} 36 | {{#if message.link_title}}{{message.link_title}}{{else}}{{message.open_link}}{{/if}} 37 | {{/if}} 38 |
39 | {{#message.files}} 40 |
41 | {{#if image}} 42 | {{{url}}} 43 | {{else}} 44 | {{{url}}} 45 | {{/if}} 46 |
47 | {{/message.files}} 48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | 56 | 57 |
58 |
59 |
60 |
61 | 62 | 63 | -------------------------------------------------------------------------------- /packages/testbot/testbot.bot: -------------------------------------------------------------------------------- 1 | { 2 | "name": "testbot.bot", 3 | "description": "", 4 | "services": [ 5 | { 6 | "type": "endpoint", 7 | "appId": "", 8 | "appPassword": "", 9 | "endpoint": "http://localhost:3000/api/messages", 10 | "id": "b9a54960-1f51-11e9-8939-03499153c69d", 11 | "name": "http://localhost:3000/api/messages" 12 | } 13 | ], 14 | "padlock": "", 15 | "version": "2.0", 16 | "overrides": null 17 | } 18 | -------------------------------------------------------------------------------- /todo.md: -------------------------------------------------------------------------------- 1 | # packages 2 | 3 | * move/remove/ignore testbot 4 | 5 | # core 6 | # docs 7 | 8 | # advanced topics 9 | * anatomy 10 | * upgrade guide 11 | 12 | * every adapter doc should link to main client API doc 13 | * link to provisioning guides 14 | 15 | # github 16 | 17 | * tag new v4 branch 18 | 19 | # starter kits / yeoman 20 | 21 | * move over more useful skills 22 | 23 | # Teams 24 | 25 | * direct_message qualifications 26 | * update/remove message in botworker? 27 | 28 | * -> https://github.com/howdyai/botkit/blob/master/lib/TeamsAPI.js 29 | * getchannels <-- can be achieved but is different/ and not compatible with getconversations 30 | * getuserbyid <-- predicated on getconvo members 31 | * getuserbyupn <-- see above 32 | * getconversationmembers <-- works but awkward 33 | * getteamroster <-- works but awkward 34 | * gettoken? <-- works but awkard> 35 | 36 | 37 | # Tests! 38 | 39 | # POST LAUNCH 40 | 41 | * update cms "options" page to reflect use with botkit-plugin-cms 42 | * botbuilder card builders? 43 | * ears? check for intent, others? 44 | * how to determine what is active dialog / do contextual help --------------------------------------------------------------------------------