diff --git a/website/i18n/en.json b/website/i18n/en.json index 405cb45d0..a622f3d1a 100644 --- a/website/i18n/en.json +++ b/website/i18n/en.json @@ -5,6 +5,9 @@ "previous": "Previous", "tagline": "A framework for building conversational user interfaces.", "docs": { + "advanced-guides-custom-server": { + "title": "Running Bottender with Custom Servers" + }, "advanced-guides-deployment": { "title": "Deployment" }, @@ -65,6 +68,9 @@ "channel-line-handling-events": { "title": "Handling LINE Events" }, + "channel-line-liff": { + "title": "LINE Front-end Framework (LIFF)" + }, "channel-line-migrating-from-sdk": { "title": "Migrating from LINE SDK for Node.js" }, @@ -452,9 +458,15 @@ "version-1.1.0/version-1.1.0-the-basics-routing": { "title": "Routing" }, + "version-1.2.0/version-1.2.0-advanced-guides-custom-server": { + "title": "Running Bottender with Custom Servers" + }, "version-1.2.0/version-1.2.0-advanced-guides-nlu": { "title": "Natural Language Understanding" }, + "version-1.2.0/version-1.2.0-channel-line-liff": { + "title": "LINE Front-end Framework (LIFF)" + }, "version-1.2.0/version-1.2.0-channel-line-sending-messages": { "title": "Sending LINE Messages" }, diff --git a/website/versioned_docs/version-1.2.0/advanced-guides-custom-server.md b/website/versioned_docs/version-1.2.0/advanced-guides-custom-server.md new file mode 100644 index 000000000..a9504ae00 --- /dev/null +++ b/website/versioned_docs/version-1.2.0/advanced-guides-custom-server.md @@ -0,0 +1,261 @@ +--- +id: version-1.2.0-advanced-guides-custom-server +title: Running Bottender with Custom Servers +original_id: advanced-guides-custom-server +--- + +## The Concept + +`bottender dev` and `bottender start` are the default npm scripts generated by [create-bottender-app](getting-started#create-a-new-bottender-app). + +Thus, You can find those lines in your generated `package.json`: + +```json +{ + ... + "scripts": { + "dev": "bottender dev", + "start": "bottender start", + ... + }, + ... +} +``` + +When executing one of `bottender dev` or `bottender start` command, under the hood, it setups a default express server for Bottender and load `index.js` from the project root directory as the root action of the chatbot. + +To run Bottender with the custom HTTP server, we need to prepare an HTTP server, delegate the webhook routes to Bottender, and modify the setting of `package.json`. + +## Express + +### Creating A New Project with Custom Express Server + +If you want to have a clean project with the custom express, you could start from [this example](https://github.com/Yoctol/bottender/tree/master/examples/custom-server-express) to develop your project. There are four steps you could follow to create your project: + +1. Download the code from [this example](https://github.com/Yoctol/bottender/tree/master/examples/custom-server-express). +2. Run `yarn` or `npm install` command to install all dependencies. +3. Fill the `.env` file with correct value. +4. Run `yarn dev` or `npm run dev` to start the dev server. + +If you want to have the folder structure we recommended, you could start with [create-bottender-app](getting-started#create-a-new-bottender-app) command and migrate it to the custom express server by following the migration instructions below. + +### Migrating An Existing Project to Custom Express Server + +Suppose that you already have a project built from [create-bottender-app](getting-started#create-a-new-bottender-app), and you want to develop some additional APIs using express server. In this case, you need to write a custom express server and delegate all chatbot's webhook requests to the Bottender app. + +To achieve that, you could follow the instructions, as shown below: + +1. Run `yarn add express body-parser nodemon` or `npm install express body-parser nodemon` command to install dependencies we need. +2. Create a `server.js` file in the root directory of the project and copy the following code into it. + +```js +const bodyParser = require('body-parser'); +const express = require('express'); +const { bottender } = require('bottender'); + +const app = bottender({ + dev: process.env.NODE_ENV !== 'production', +}); + +const port = Number(process.env.PORT) || 5000; + +// the request handler of the bottender app +const handle = app.getRequestHandler(); + +app.prepare().then(() => { + const server = express(); + + server.use( + bodyParser.json({ + verify: (req, _, buf) => { + req.rawBody = buf.toString(); + }, + }) + ); + + // your custom route + server.get('/api', (req, res) => { + res.json({ ok: true }); + }); + + // route for webhook request + server.all('*', (req, res) => { + return handle(req, res); + }); + + server.listen(port, err => { + if (err) throw err; + console.log(`> Ready on http://localhost:${port}`); + }); +}); +``` + +3. Modify scripts in the `package.json` to `nodemon server.js` and `node server.js` instead: + +```json +{ + ... + "scripts": { + "dev": "nodemon server.js", + "start": "node server.js", + ... + }, + ... +} +``` + +That's all you need to do, and you can have you bot hosting on the custom express server! + +## Koa + +### Creating A New Project with Custom Koa Server + +If you want to have a clean project with the custom koa, you could start from [this example](https://github.com/Yoctol/bottender/tree/master/examples/custom-server-koa) to develop your project. There are four steps you could follow to create your project: + +1. Download the code from [this example](https://github.com/Yoctol/bottender/tree/master/examples/custom-server-koa). +2. Run `yarn install` command to install dependencies. +3. Fill the `.env` file with correct value. +4. Run `yarn dev` to start server. + +If you want to have the folder structure we recommended, you could start with [create-bottender-app](getting-started#create-a-new-bottender-app) command and migrate it to the custom koa server by following the migration instructions below. + +### Migrating An Existing Project to Custom Koa Server + +Suppose that you already have a project built from [create-bottender-app](getting-started#create-a-new-bottender-app), and you want to develop some additional APIs using koa server. In this case, you need to write a custom koa server and delegate all chatbot's webhook requests to the Bottender app. + +To achieve that, you could follow the instructions, as shown below: + +1. Run `yarn add koa koa-router koa-bodyparser nodemon` or `npm install koa koa-router koa-bodyparser nodemon` command to install dependencies we need. +2. Create a `server.js` file in the root directory of the project and copy the following code into it. + +```js +const Koa = require('koa'); +const Router = require('koa-router'); +const bodyParser = require('koa-bodyparser'); +const { bottender } = require('bottender'); + +const app = bottender({ + dev: process.env.NODE_ENV !== 'production', +}); + +const port = Number(process.env.PORT) || 5000; + +const handle = app.getRequestHandler(); + +app.prepare().then(() => { + const server = new Koa(); + const router = new Router(); + + router.get('/api', ctx => { + ctx.response.body = { ok: true }; + }); + + router.all('*', async ctx => { + await handle(ctx.req, ctx.res); + ctx.respond = false; + }); + + server.use(bodyParser()); + server.use((ctx, next) => { + ctx.req.body = ctx.request.body; + ctx.req.rawBody = ctx.request.rawBody; + return next(); + }); + server.use(router.routes()); + + server.listen(port, err => { + if (err) throw err; + console.log(`> Ready on http://localhost:${port}`); + }); +}); +``` + +3. Modify scripts in the `package.json` to `nodemon server.js` and `node server.js` instead: + +```json +{ + ... + "scripts": { + "dev": "nodemon server.js", + "start": "node server.js", + ... + }, + ... +} +``` + +That's all you need to do, and you can have you bot hosting on the custom koa server! + +## Restify + +### Creating A New Project with Custom Restify Server + +If you want to have a clean project with the custom restify, you could start from [this example](https://github.com/Yoctol/bottender/tree/master/examples/custom-server-restify) to develop your project. There are four steps you could follow to create your project: + +1. Download the code from [this example](https://github.com/Yoctol/bottender/tree/master/examples/custom-server-restify). +2. Run `yarn install` command to install dependencies. +3. Fill the `.env` file with correct value. +4. Run `yarn dev` to start server. + +If you want to have the folder structure we recommended, you could start with [create-bottender-app](getting-started#create-a-new-bottender-app) command and migrate it to the custom restify server by following the migration instructions below. + +### Migrating An Existing Project to Custom Restify Server + +Suppose that you already have a project built from [create-bottender-app](getting-started#create-a-new-bottender-app), and you want to develop some additional APIs using restify server. In this case, you need to write a custom restify server and delegate all chatbot's webhook requests to the Bottender app. + +To achieve that, you could follow the instructions, as shown below: + +1. Run `yarn add restify nodemon` or `npm install restify nodemon` command to install dependencies we need. +2. Create a `server.js` file in the root directory of the project and copy the following code into it. + +```js +const restify = require('restify'); +const { bottender } = require('bottender'); + +const app = bottender({ + dev: process.env.NODE_ENV !== 'production', +}); + +const port = Number(process.env.PORT) || 5000; + +const handle = app.getRequestHandler(); + +app.prepare().then(() => { + const server = restify.createServer(); + + server.use(restify.plugins.queryParser()); + server.use(restify.plugins.bodyParser()); + + server.get('/api', (req, res) => { + res.send({ ok: true }); + }); + + server.get('*', (req, res) => { + return handle(req, res); + }); + server.post('*', (req, res) => { + return handle(req, res); + }); + + server.listen(port, err => { + if (err) throw err; + console.log(`> Ready on http://localhost:${port}`); + }); +}); +``` + +3. Modify scripts in the `package.json` to `nodemon server.js` and `node server.js` instead: + +```json +{ + ... + "scripts": { + "dev": "nodemon server.js", + "start": "node server.js", + ... + }, + ... +} +``` + +That's all you need to do, and you can have you bot hosting on the custom restify server! diff --git a/website/versioned_docs/version-1.2.0/channel-line-liff.md b/website/versioned_docs/version-1.2.0/channel-line-liff.md new file mode 100644 index 000000000..f3d791645 --- /dev/null +++ b/website/versioned_docs/version-1.2.0/channel-line-liff.md @@ -0,0 +1,225 @@ +--- +id: version-1.2.0-channel-line-liff +title: LINE Front-end Framework (LIFF) +original_id: channel-line-liff +--- + +## LINE Front-end Framework (LIFF), the Webview Solution in LINE App + +There are three different sizes of embedded webviews provided by LIFF. You may use those sizes to enrich your users' experience. + +![different sizes of liff](https://user-images.githubusercontent.com/563929/73712876-6a01b100-4746-11ea-8f85-22b8026882d5.png) + +Besides, LIFF gives you more chances to improve interactions between users and the chatbot. One of the common scenarios is submitting a form in LINE Bots. + +### Features in LIFF + +LIFF lets you access a lot of different APIs on your web pages. Before getting started, you may want to grab some basic knowledge from LINE official docs: + +- [Getting user profile](https://developers.line.biz/en/reference/liff/#get-profile) +- [Sending messages to LINE](https://developers.line.biz/en/reference/liff/#send-messages) +- [Opening link in external browser](https://developers.line.biz/en/reference/liff/#open-window) +- [Scanning QR Code](https://developers.line.biz/en/reference/liff/#scan-code) +- [Connecting to Bluetooth devices](https://developers.line.biz/en/reference/liff/#bluetooth-request-device) +- Others features in [LIFF playground](https://playground-for-liff.linecorp.com/) + +## LIFF V2 + +LIFF v2 introduces some new features to developers, e.g., scanning QR codes, allowing users to open LIFF pages on the Desktop version of the LINE app. + +For catching up quickly, this is a minimal implementation - [Bottender example with LIFF v2](https://github.com/Yoctol/bottender/tree/master/examples/line-liff-v2). + +The following sections are step by step tutorials about how to send messages with LIFF in a Bottender project created by [Create Bottender App](https://bottender.js.org/docs/getting-started#create-a-new-bottender-app). + +> **Note:** LIFF v1 is not recommended anymore. If you're using it, you should migrate to LIFF v2. However, you could still find an example for [LIFF v1 here](https://github.com/Yoctol/bottender/tree/master/examples/line-liff-v1). + +## Workflow + +For making your LIFF pages work, your typical workflow should look like this: + +- Creating a LINE Login channel in [LINE Developers console](https://developers.line.biz/console/) +- Adding a LIFF app in the LINE Login channel +- Developing the LIFF page + +### Creating LINE Login Channel + +First of all, you need to open [LINE Developers Console](https://developers.line.biz/console/) to create a LINE Login channel. + +For more details about creating a LINE Login channel, please checkout [Creating A Provider and Channel](https://developers.line.biz/en/docs/liff/getting-started/#creating-a-provider-and-channel). + +### Adding LIFF in the LINE Login Channel + +- Click the "LIFF" tab in the LINE Login Channel you just created. +- Click the "Add" button +- Fill in the "Endpoint URL" in this format: `https://{your domain}.ngrok.io/liff` +- Fill in other values + +For more details about registering a LIFF app, please checkout [Registering LIFF App](https://developers.line.biz/en/docs/liff/registering-liff-apps/#registering-liff-app). + +> **Note:** [Ngrok](https://ngrok.com/) is a well-known service that provides public HTTPs URLs for your local server using the tunnel. It's handy when you develop your bot locally. You may want to use it when developing. + +### Environment Variables Setting + +If you are familiar with any official Bottender example, you may already know about how to use `.env` file to manage your environment variables in your local project. + +In this case, you need to add another `LINE_LIFF_ID` env to `.env` file, so your file will have at least those three LINE related environment variables: + +``` +LINE_ACCESS_TOKEN={your LINE access token from LINE Messaging API channel} +LINE_CHANNEL_SECRET={your LINE channel secret from LINE Messaging API channel} +LINE_LIFF_ID={your LIFF id from LINE Login channel} +``` + +You could find your LIFF ID in the LIFF URL. The format of LIFF URL looks like `line://app/{your LIFF ID}`. + +For more details about LIFF ID, please checkout [Registering LIFF App (in step 4)](https://developers.line.biz/en/docs/liff/registering-liff-apps/#registering-liff-app). + +### Adding Custom Routes to HTTP Server for LIFF Pages + +To serve LIFF webpages, we need to add additional routes to the server. Fortunately, [custom server](advanced-guides-custom-server#the-concept) come to the rescue! + +You could use express, koa, restify, or whatever you like, but we are going to use express in this guide. Before going down, make sure that you set up correctly according to [this guide](advanced-guides-custom-server#express). + +After having a custom server, you could add the following two routes into `server.js` to handle requests from LIFF. + +```js +server.get('/send-id', (req, res) => { + res.json({ id: process.env.LINE_LIFF_ID }); +}); + +server.get('/liff', (req, res) => { + const filename = path.join(`${__dirname}/liff.html`); + res.sendFile(filename); +}); +``` + +### Initializing the LIFF Page + +Before starting using any feature provided by LIFF, you need to create a `liff.html` file in the root directory of the project and copy the following code into it for LIFF initialization: + +```html + + + + + + BOTTENDER LINE LIFF V2 DEMO + + + + + + + +``` + +It is worth mentioning that `liff.init()` and some other `liff` methods return `Promise` as results, so you should handle those asynchronous code carefully. + +### Sending Messages from LIFF page + +After initializing the LIFF page, we can call `liff.sendMessages` to send messages in the thread imperatively. For example: + +```js +liff.sendMessages([ + { + type: 'text', + text: 'Hello, LIFF!', + }, +]); +``` + +Up to five text, image, video, audio, location, template (only a URI action can be set as an action), and flex messages are acceptable. + +Let's add a click event listener to send messages on click. You could replace the body tag in `liff.html` with the following implementation: + +```html + + + + + +``` + +### Sending LIFF LINK to the User + +To test the LIFF page, you could replace the code in `index.js` to send the LIFF URL to the user: + +```js +module.exports = async function App(context) { + const liffUrl = `https://liff.line.me/${process.env.LINE_LIFF_ID}`; + await context.sendText(liffUrl); +}; +``` + +Now, you could execute `yarn dev` or `npm run dev` to start the server, and you will have a LINE Bot with a simple LIFF page. diff --git a/website/versioned_sidebars/version-1.2.0-sidebars.json b/website/versioned_sidebars/version-1.2.0-sidebars.json new file mode 100644 index 000000000..a610f4489 --- /dev/null +++ b/website/versioned_sidebars/version-1.2.0-sidebars.json @@ -0,0 +1,93 @@ +{ + "version-1.2.0-docs": { + "Getting Started": [ + "version-1.2.0-getting-started", + "version-1.2.0-migrating-v1" + ], + "The Basics": [ + "version-1.2.0-the-basics-console-mode", + "version-1.2.0-the-basics-actions", + "version-1.2.0-the-basics-routing", + "version-1.2.0-the-basics-chain", + "version-1.2.0-the-basics-session", + "version-1.2.0-the-basics-errors" + ], + "Advanced Guides": [ + "version-1.2.0-advanced-guides-custom-server", + "version-1.2.0-advanced-guides-deployment", + "version-1.2.0-advanced-guides-nlu", + "version-1.2.0-advanced-guides-multi-channel" + ], + "Guides (Messenger)": [ + "version-1.2.0-channel-messenger-setup", + "version-1.2.0-channel-messenger-handling-events", + "version-1.2.0-channel-messenger-sending-messages", + "version-1.2.0-channel-messenger-routing", + "version-1.2.0-channel-messenger-profile", + "version-1.2.0-channel-messenger-handover-protocol", + "version-1.2.0-channel-messenger-persona", + "version-1.2.0-channel-messenger-multi-page" + ], + "Guides (LINE)": [ + "version-1.2.0-channel-line-setup", + "version-1.2.0-channel-line-handling-events", + "version-1.2.0-channel-line-sending-messages", + "version-1.2.0-channel-line-routing", + "version-1.2.0-channel-line-flex", + "version-1.2.0-channel-line-rich-menu", + "version-1.2.0-channel-line-liff", + "version-1.2.0-channel-line-errors", + "version-1.2.0-channel-line-migrating-from-sdk" + ], + "Guides (Slack)": [ + "version-1.2.0-channel-slack-setup", + "version-1.2.0-channel-slack-handling-events", + "version-1.2.0-channel-slack-sending-messages", + "version-1.2.0-channel-slack-routing", + "version-1.2.0-channel-slack-block-kit" + ], + "Guides (Telegram)": [ + "version-1.2.0-channel-telegram-setup", + "version-1.2.0-channel-telegram-handling-events", + "version-1.2.0-channel-telegram-sending-messages", + "version-1.2.0-channel-telegram-routing" + ], + "Guides (Viber)": [ + "version-1.2.0-channel-viber-setup", + "version-1.2.0-channel-viber-handling-events", + "version-1.2.0-channel-viber-sending-messages", + "version-1.2.0-channel-viber-routing" + ], + "FAQ": [] + }, + "version-1.2.0-api": { + "Core": [ + "version-1.2.0-api-context", + "version-1.2.0-api-event" + ], + "Messenger": [ + "version-1.2.0-api-messenger-context", + "version-1.2.0-api-messenger-event" + ], + "LINE": [ + "version-1.2.0-api-line-context", + "version-1.2.0-api-line-event" + ], + "Slack": [ + "version-1.2.0-api-slack-context", + "version-1.2.0-api-slack-event" + ], + "Telegram": [ + "version-1.2.0-api-telegram-context", + "version-1.2.0-api-telegram-event" + ], + "Viber": [ + "version-1.2.0-api-viber-context", + "version-1.2.0-api-viber-event" + ], + "Console": [ + "version-1.2.0-api-console-context", + "version-1.2.0-api-console-event" + ] + } +}