diff --git a/src/api/bot/core.ts b/src/api/bot/core.ts index 002ac1b06..47989dbaa 100644 --- a/src/api/bot/core.ts +++ b/src/api/bot/core.ts @@ -4,11 +4,11 @@ import * as bcrypt from 'bcryptjs'; import User, { IUser } from '../models/user'; export default class BotCore extends EventEmitter { - public user: IUser; + public user: IUser = null; private context: Context = null; - constructor(user: IUser) { + constructor(user?: IUser) { super(); this.user = user; diff --git a/src/api/bot/interfaces/line.ts b/src/api/bot/interfaces/line.ts index 4bee844c1..8c7d6acfd 100644 --- a/src/api/bot/interfaces/line.ts +++ b/src/api/bot/interfaces/line.ts @@ -1,34 +1,77 @@ import * as EventEmitter from 'events'; import * as express from 'express'; +import * as request from 'request'; import * as crypto from 'crypto'; //import User from '../../models/user'; import config from '../../../conf'; -/*import BotCore from '../core'; +import BotCore from '../core'; -const sessions: { - userId: string; +const sessions: Array<{ + sourceId: string; session: BotCore; -}[] = []; -*/ +}> = []; + module.exports = async (app: express.Application) => { if (config.line_bot == null) return; const handler = new EventEmitter(); - app.post('/hooks/line', (req, res, next) => { - // req.headers['X-Line-Signature'] は常に string ですが、型定義の都合上 - // string | string[] になっているので string を明示しています - const sig1 = req.headers['X-Line-Signature'] as string; + handler.on('message', async (ev) => { + // テキスト以外(スタンプなど)は無視 + if (ev.message.type !== 'text') return; - const hash = crypto.createHmac('sha256', config.line_bot.channel_secret) - .update(JSON.stringify(req.body)); + const sourceId = ev.source.userId; + let session = sessions.find(s => { + return s.sourceId === sourceId; + }); + + if (!session) { + session = { + sourceId: sourceId, + session: new BotCore() + }; + + sessions.push(session); + } + + const res = await session.session.q(ev.message.text); + + request({ + url: 'https://api.line.me/v2/bot/message/reply', + headers: { + 'Authorization': `Bearer ${config.line_bot.channel_access_token}` + }, + json: { + replyToken: ev.replyToken, + messages: [{ + type: 'text', + text: res + }] + } + }, (err, res, body) => { + if (err) { + console.error(err); + return; + } + }); + }); + + app.post('/hooks/line', (req, res, next) => { + // req.headers['x-line-signature'] は常に string ですが、型定義の都合上 + // string | string[] になっているので string を明示しています + const sig1 = req.headers['x-line-signature'] as string; + + const hash = crypto.createHmac('SHA256', config.line_bot.channel_secret) + .update((req as any).rawBody); const sig2 = hash.digest('base64'); // シグネチャ比較 if (sig1 === sig2) { - console.log(req.body); - handler.emit(req.body.type); + req.body.events.forEach(ev => { + handler.emit(ev.type, ev); + }); + res.sendStatus(200); } else { res.sendStatus(400); diff --git a/src/api/server.ts b/src/api/server.ts index fdff0c754..3de32d9ea 100644 --- a/src/api/server.ts +++ b/src/api/server.ts @@ -19,7 +19,12 @@ app.disable('x-powered-by'); app.set('etag', false); app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json({ - type: ['application/json', 'text/plain'] + type: ['application/json', 'text/plain'], + verify: (req, res, buf, encoding) => { + if (buf && buf.length) { + (req as any).rawBody = buf.toString(encoding || 'utf8'); + } + } })); app.use(cors({ origin: true diff --git a/src/config.ts b/src/config.ts index 0ea332f67..46a93f5fe 100644 --- a/src/config.ts +++ b/src/config.ts @@ -70,6 +70,7 @@ type Source = { }; line_bot?: { channel_secret: string; + channel_access_token: string; }; analysis?: { mecab_command?: string; diff --git a/tslint.json b/tslint.json index 33704ca43..1c4457951 100644 --- a/tslint.json +++ b/tslint.json @@ -16,6 +16,7 @@ "ordered-imports": [false], "arrow-parens": false, "object-literal-shorthand": false, + "object-literal-key-quotes": false, "triple-equals": [false], "no-shadowed-variable": false, "no-string-literal": false,