Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions examples/wechat-hello-world/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Wecaht hello world

## 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/wechat-hello-world
cd wechat-hello-world
```

Install dependencies:

```
npm install
```

You must put `accessToken`, `appSecret` and `verifyToken` into `bottender.config.js`.

After that, you can run the bot with this npm script:

```
npm run dev
```

This command will start server for bot developing at `http://localhost:5000`.

## Set webhook

While the server running, you can run following command with global `bottender` to set up the webhook:

```
bottender messenger webhook set -w <YOUR_WEBHOOK_URL>
```

If you want to expose the server on your local development machine and get a secure URL, [ngrok](https://ngrok.com/) or [localtunnel](https://localtunnel.github.io/www/) may be good tools for you.

> Note: You must put `appId` and `appSecret` into `bottender.config.js` before running this command.

## Idea of this example

This example is a simple bot running on [Messenger](https://www.messenger.com/).
For more information, check our [Messenger guides](https://bottender.js.org/docs/Platforms-Messenger).

## Related examples

- [messenger-hello-world](../messenger-hello-world)
- [console-hello-world](../console-hello-world)
- [line-hello-world](../line-hello-world)
- [slack-hello-world](../slack-hello-world)
- [telegram-hello-world](../telegram-hello-world)
- [viber-hello-world](../viber-hello-world)
7 changes: 7 additions & 0 deletions examples/wechat-hello-world/bottender.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
wechat: {
appId: '__PUT_YOUR_APP_ID_HERE__',
appSecret: '__PUT_YOUR_APP_SECRET_HERE__',
verifyToken: '__PUT_YOUR_VERITY_TOKEN_HERE__',
},
};
20 changes: 20 additions & 0 deletions examples/wechat-hello-world/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const { WechatBot } = require('../../lib');
const { createServer } = require('../../lib/express');

const config = require('./bottender.config').wechat;

const bot = new WechatBot({
accessToken: config.accessToken,
appSecret: config.appSecret,
verifyToken: config.verifyToken,
});

bot.onEvent(async context => {
await context.replyText('Hello World');
});

const server = createServer(bot);

server.listen(5000, () => {
console.log('server is running on 5000 port...');
});
12 changes: 12 additions & 0 deletions examples/wechat-hello-world/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"dependencies": {
"bottender": "latest"
},
"devDependencies": {
"nodemon": "^1.11.0"
},
"scripts": {
"dev": "nodemon index.js",
"start": "node index.js"
}
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"deep-object-diff": "^1.1.0",
"delay": "^4.1.0",
"express": "^4.16.4",
"express-xml-bodyparser": "^0.3.0",
"figures": "^2.0.0",
"file-type": "^10.4.0",
"fs-extra": "^7.0.1",
Expand All @@ -75,6 +76,7 @@
"messaging-api-slack": "^0.7.11",
"messaging-api-telegram": "^0.7.11",
"messaging-api-viber": "^0.7.11",
"messaging-api-wechat": "^0.7.11",
"messenger-batch": "^0.3.0",
"micro": "^9.3.3",
"minimist": "^1.2.0",
Expand Down
21 changes: 21 additions & 0 deletions src/bot/WechatBot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* @flow */

import { type SessionStore } from '../session/SessionStore';

import Bot from './Bot';
import WechatConnector from './WechatConnector';

export default class WechatBot extends Bot {
constructor({
sessionStore,
verifyToken,
origin,
}: {
sessionStore: SessionStore,
verifyToken?: string,
origin?: string,
}) {
const connector = new WechatConnector({ verifyToken, origin });
super({ connector, sessionStore, sync: true });
}
}
92 changes: 92 additions & 0 deletions src/bot/WechatConnector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/* @flow */
import { WechatClient } from 'messaging-api-wechat';

import WechatContext from '../context/WechatContext';
import WechatEvent, { type WechatRawEvent } from '../context/WechatEvent';
import { type Session } from '../session/Session';

import { type Connector } from './Connector';

export type WechatRequestBody = WechatRawEvent;

type ConstructorOptions = {|
client?: WechatClient,
origin?: string,
|};

export default class WechatConnector implements Connector<WechatRequestBody> {
_client: WechatClient;

_verifyToken: ?string;

constructor({ client, verifyToken, origin }: ConstructorOptions) {
this._client =
client ||
WechatClient.connect({
origin,
});

this._verifyToken = verifyToken;
}

_getRawEventFromRequest(body: WechatRequestBody): WechatRawEvent {
return body.xml;
}

get platform(): string {
return 'wechat';
}

get client(): WechatClient {
return this._client;
}

get verifyToken(): ?string {
return this._verifyToken;
}

getUniqueSessionKey(body: WechatRequestBody): string {
return body.openid;
}

async updateSession(
session: Session,
body: WechatRequestBody
): Promise<void> {
console.log('updateSession', { body });
if (!session.user) {
session.user = {
id: body.openid,
_updatedAt: new Date().toISOString(),
};
}

Object.freeze(session.user);
Object.defineProperty(session, 'user', {
configurable: false,
enumerable: true,
writable: false,
value: session.user,
});
}

mapRequestToEvents(body: WechatRequestBody): Array<WechatEvent> {
const rawEvent = this._getRawEventFromRequest(body);

console.log('mapRequestToEvents', { rawEvent });

return [new WechatEvent(rawEvent)];
}

createContext(params: {
event: WechatEvent,
session: ?Session,
initialState: ?Object,
requestContext: ?Object,
}): WechatContext {
return new WechatContext({
...params,
client: this._client,
});
}
}
11 changes: 11 additions & 0 deletions src/bot/__tests__/WechatBot.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import WechatBot from '../WechatBot';
import WechatConnector from '../WechatConnector';

it('should construct bot with WechatConnector', () => {
const bot = new WechatBot();
expect(bot).toBeDefined();
expect(bot.onEvent).toBeDefined();
expect(bot.createRequestHandler).toBeDefined();
expect(bot.connector).toBeDefined();
expect(bot.connector).toBeInstanceOf(WechatConnector);
});
Empty file.
Loading