Repository: Yoctol/bottender
Pull request #36 (2017-11-22 08:47:16)

messenger-deep-nested-menu example
It shows how to extend nested persistent menu to have 3 levels and total 75 call to actions.



Patch:
diff --git a/examples/messenger-deep-nested-menu/README.md b/examples/messenger-deep-nested-menu/README.md
new file mode 100644
index 00000000..cd863500
--- /dev/null
+++ b/examples/messenger-deep-nested-menu/README.md
@@ -0,0 +1,34 @@
+# Messenger deep nested menu
+
+## Install and Run
+
+Download this example or clone [bottender](https://github.com/Yoctol/bottender).
+
+```
+curl https://codeload.github.com/Yoctol/bottender/tar.gz/master | tar -xz --strip=2 bottender-master/examples/messenger-deep-nested-menu
+cd messenger-deep-nested-menu
+npm install
+```
+
+You should fill your access token and set messenger profile before run your bot.
+
+```
+bottender messenger profile set
+```
+
+> Note: You must have global installed `bottender`.
+
+Then, you can run it:
+
+```
+npm run dev
+```
+
+## Idea of this example
+
+It shows how to extend nested persistent menu to have 3 levels and total 75 call to actions.
+
+## Related examples
+
+* [messenger-hello-world](../messenger-hello-world)
+* [with-config](../with-config)
diff --git a/examples/messenger-deep-nested-menu/bottender.config.js b/examples/messenger-deep-nested-menu/bottender.config.js
new file mode 100644
index 00000000..a682b5f6
--- /dev/null
+++ b/examples/messenger-deep-nested-menu/bottender.config.js
@@ -0,0 +1,504 @@
+module.exports = {
+  messenger: {
+    accessToken: '__PUT_YOUR_ACCESS_TOKEN_HERE__',
+    verifyToken: '__PUT_YOUR_VERITY_TOKEN_HERE__',
+    appId: '__PUT_YOUR_APP_ID_HERE__',
+    appSecret: '__PUT_YOUR_APP_SECRET_HERE__',
+    profile: {
+      get_started: {
+        payload: 'GET_STARTED',
+      },
+      persistent_menu: [
+        {
+          locale: 'default',
+          composer_input_disabled: false,
+          call_to_actions: [
+            {
+              type: 'nested',
+              title: 'Nested.1',
+              call_to_actions: [
+                {
+                  type: 'nested',
+                  title: 'Nested.1.1',
+                  call_to_actions: [
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.1.1',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.1.2',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.1.3',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.1.4',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.1.5',
+                      url: 'http://bottender.js.org',
+                    },
+                  ],
+                },
+                {
+                  type: 'nested',
+                  title: 'Nested.1.2',
+                  call_to_actions: [
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.2.1',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.2.2',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.2.3',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.2.4',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.2.5',
+                      url: 'http://bottender.js.org',
+                    },
+                  ],
+                },
+                {
+                  type: 'nested',
+                  title: 'Nested.1.3',
+                  call_to_actions: [
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.3.1',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.3.2',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.3.3',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.3.4',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.3.5',
+                      url: 'http://bottender.js.org',
+                    },
+                  ],
+                },
+                {
+                  type: 'nested',
+                  title: 'Nested.1.4',
+                  call_to_actions: [
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.4.1',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.4.2',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.4.3',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.4.4',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.4.5',
+                      url: 'http://bottender.js.org',
+                    },
+                  ],
+                },
+                {
+                  type: 'nested',
+                  title: 'Nested.1.5',
+                  call_to_actions: [
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.5.1',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.5.2',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.5.3',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.5.4',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.1.5.5',
+                      url: 'http://bottender.js.org',
+                    },
+                  ],
+                },
+              ],
+            },
+            {
+              type: 'nested',
+              title: 'Nested.2',
+              call_to_actions: [
+                {
+                  type: 'nested',
+                  title: 'Nested.2.1',
+                  call_to_actions: [
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.1.1',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.1.2',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.1.3',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.1.4',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.1.5',
+                      url: 'http://bottender.js.org',
+                    },
+                  ],
+                },
+                {
+                  type: 'nested',
+                  title: 'Nested.2.2',
+                  call_to_actions: [
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.2.1',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.2.2',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.2.3',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.2.4',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.2.5',
+                      url: 'http://bottender.js.org',
+                    },
+                  ],
+                },
+                {
+                  type: 'nested',
+                  title: 'Nested.2.3',
+                  call_to_actions: [
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.3.1',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.3.2',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.3.3',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.3.4',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.3.5',
+                      url: 'http://bottender.js.org',
+                    },
+                  ],
+                },
+                {
+                  type: 'nested',
+                  title: 'Nested.2.4',
+                  call_to_actions: [
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.4.1',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.4.2',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.4.3',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.4.4',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.4.5',
+                      url: 'http://bottender.js.org',
+                    },
+                  ],
+                },
+                {
+                  type: 'nested',
+                  title: 'Nested.2.5',
+                  call_to_actions: [
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.5.1',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.5.2',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.5.3',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.5.4',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.2.5.5',
+                      url: 'http://bottender.js.org',
+                    },
+                  ],
+                },
+              ],
+            },
+            {
+              type: 'nested',
+              title: 'Nested.3',
+              call_to_actions: [
+                {
+                  type: 'nested',
+                  title: 'Nested.3.1',
+                  call_to_actions: [
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.1.1',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.1.2',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.1.3',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.1.4',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.1.5',
+                      url: 'http://bottender.js.org',
+                    },
+                  ],
+                },
+                {
+                  type: 'nested',
+                  title: 'Nested.3.2',
+                  call_to_actions: [
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.2.1',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.2.2',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.2.3',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.2.4',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.2.5',
+                      url: 'http://bottender.js.org',
+                    },
+                  ],
+                },
+                {
+                  type: 'nested',
+                  title: 'Nested.3.3',
+                  call_to_actions: [
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.3.1',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.3.2',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.3.3',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.3.4',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.3.5',
+                      url: 'http://bottender.js.org',
+                    },
+                  ],
+                },
+                {
+                  type: 'nested',
+                  title: 'Nested.3.4',
+                  call_to_actions: [
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.4.1',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.4.2',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.4.3',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.4.4',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.4.5',
+                      url: 'http://bottender.js.org',
+                    },
+                  ],
+                },
+                {
+                  type: 'nested',
+                  title: 'Nested.3.5',
+                  call_to_actions: [
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.5.1',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.5.2',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.5.3',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.5.4',
+                      url: 'http://bottender.js.org',
+                    },
+                    {
+                      type: 'web_url',
+                      title: 'URL.3.5.5',
+                      url: 'http://bottender.js.org',
+                    },
+                  ],
+                },
+              ],
+            },
+          ],
+        },
+      ],
+    },
+  },
+};
diff --git a/examples/messenger-deep-nested-menu/index.js b/examples/messenger-deep-nested-menu/index.js
new file mode 100644
index 00000000..eed1577c
--- /dev/null
+++ b/examples/messenger-deep-nested-menu/index.js
@@ -0,0 +1,16 @@
+const { MessengerBot } = require('bottender');
+const { createServer } = require('bottender/express');
+
+const config = require('./bottender.config');
+
+const bot = new MessengerBot(config.messenger);
+
+bot.onEvent(async context => {
+  await context.sendText('Hello World');
+});
+
+const server = createServer(bot, config);
+
+server.listen(5000, () => {
+  console.log('server is running on 5000 port...');
+});
diff --git a/examples/messenger-deep-nested-menu/package.json b/examples/messenger-deep-nested-menu/package.json
new file mode 100644
index 00000000..7c0b0e15
--- /dev/null
+++ b/examples/messenger-deep-nested-menu/package.json
@@ -0,0 +1,12 @@
+{
+  "dependencies": {
+    "bottender": "latest"
+  },
+  "devDependencies": {
+    "nodemon": "^1.11.0"
+  },
+  "scripts": {
+    "dev": "nodemon index.js",
+    "start": "node index.js"
+  }
+}
diff --git a/src/cli/shared/getConfig.js b/src/cli/shared/getConfig.js
index 5f9f1e1c..8c652a36 100644
--- a/src/cli/shared/getConfig.js
+++ b/src/cli/shared/getConfig.js
@@ -7,17 +7,23 @@ import Joi from 'joi';
 import minimist from 'minimist';
 
 import schema from './schema';
+import { bold } from './log';
 
 const getConfig = (configPath, platform) => {
   const argv = minimist(process.argv);
   const config = importFresh(path.resolve(configPath));
   if (!argv['skip-validate']) {
     const validateResult = Joi.validate(config, schema, { allowUnknown: true });
-    invariant(
-      !validateResult.error,
-      validateResult.error &&
-        `The config format is not valid. ${validateResult.error.message}`
-    );
+
+    if (validateResult.error) {
+      const { message, type } = validateResult.error.details[0];
+      const errorPath = validateResult.error.details[0].path.join('.');
+      throw new Error(
+        `The config format is not valid.\nmessage: ${message}\npath: ${bold(
+          errorPath
+        )}\ntype: ${type}`
+      );
+    }
   }
   const result = get(config, platform, undefined);
   invariant(
diff --git a/src/context/SlackContext.js b/src/context/SlackContext.js
index 99222eb0..cc9dfa1b 100644
--- a/src/context/SlackContext.js
+++ b/src/context/SlackContext.js
@@ -58,7 +58,6 @@ export default class SlackContext extends Context implements PlatformContext {
     this._isHandled = true;
 
     return this._client.postMessage(channelId, text, {
-      as_user: true,
       ...options,
     });
   }


Test patch:
diff --git a/src/context/__tests__/SlackContext.spec.js b/src/context/__tests__/SlackContext.spec.js
index 24e4ceb5..6868e4d3 100644
--- a/src/context/__tests__/SlackContext.spec.js
+++ b/src/context/__tests__/SlackContext.spec.js
@@ -91,9 +91,7 @@ describe('#postMessage', () => {
 
     await context.postMessage('xxx.com');
 
-    expect(client.postMessage).toBeCalledWith('C6A9RJJ3F', 'xxx.com', {
-      as_user: true,
-    });
+    expect(client.postMessage).toBeCalledWith('C6A9RJJ3F', 'xxx.com', {});
   });
 
   it('should support overwrite options', async () => {
@@ -130,9 +128,7 @@ describe('#postMessage', () => {
 
     await context.postMessage('xxx.com');
 
-    expect(client.postMessage).toBeCalledWith(id, 'xxx.com', {
-      as_user: true,
-    });
+    expect(client.postMessage).toBeCalledWith(id, 'xxx.com', {});
   });
 
   it('should get null channelId and call warning if no session', async () => {