diff --git a/src/api/bot/core.ts b/src/api/bot/core.ts index 47989dbaa..1f624c5f0 100644 --- a/src/api/bot/core.ts +++ b/src/api/bot/core.ts @@ -14,6 +14,31 @@ export default class BotCore extends EventEmitter { this.user = user; } + private setContect(context: Context) { + this.context = context; + this.emit('updated'); + + if (context) { + context.on('updated', () => { + this.emit('updated'); + }); + } + } + + public export() { + return { + user: this.user, + context: this.context ? this.context.export() : null + }; + } + + public static import(data) { + const core = new BotCore(); + core.user = data.user; + core.setContect(data.context ? Context.import(core, data.context) : null); + return core; + } + public async q(query: string): Promise { if (this.context != null) { return await this.context.q(query); @@ -22,9 +47,11 @@ export default class BotCore extends EventEmitter { switch (query) { case 'ping': return 'PONG'; + case 'me': + return this.user ? `${this.user.name}としてサインインしています` : 'サインインしていません'; case 'ログイン': case 'サインイン': - this.context = new SigninContext(this); + this.setContect(new SigninContext(this)); return await this.context.greet(); default: return '?'; @@ -34,18 +61,26 @@ export default class BotCore extends EventEmitter { public setUser(user: IUser) { this.user = user; this.emit('set-user', user); + this.emit('updated'); } } -abstract class Context { +abstract class Context extends EventEmitter { protected core: BotCore; public abstract async greet(): Promise; public abstract async q(query: string): Promise; + public abstract export(): any; constructor(core: BotCore) { + super(); this.core = core; } + + public static import(core: BotCore, data: any) { + if (data.type == 'signin') return SigninContext.import(core, data.content); + return null; + } } class SigninContext extends Context { @@ -71,6 +106,7 @@ class SigninContext extends Context { return `${query}というユーザーは存在しませんでした... もう一度教えてください:`; } else { this.temporaryUser = user; + this.emit('updated'); return `パスワードを教えてください:`; } } else { @@ -85,4 +121,16 @@ class SigninContext extends Context { } } } + + public export() { + return { + temporaryUser: this.temporaryUser + }; + } + + public static import(core: BotCore, data: any) { + const context = new SigninContext(core); + context.temporaryUser = data.temporaryUser; + return context; + } } diff --git a/src/api/bot/interfaces/line.ts b/src/api/bot/interfaces/line.ts index 9e1c81357..61aa72812 100644 --- a/src/api/bot/interfaces/line.ts +++ b/src/api/bot/interfaces/line.ts @@ -5,11 +5,10 @@ import * as crypto from 'crypto'; import User from '../../models/user'; import config from '../../../conf'; import BotCore from '../core'; +import _redis from '../../../db/redis'; +import prominence = require('prominence'); -const sessions: Array<{ - sourceId: string; - core: BotCore; -}> = []; +const redis = prominence(_redis); module.exports = async (app: express.Application) => { if (config.line_bot == null) return; @@ -21,22 +20,23 @@ module.exports = async (app: express.Application) => { if (ev.message.type !== 'text') return; const sourceId = ev.source.userId; - let session = sessions.find(s => s.sourceId === sourceId); + const sessionId = `line-bot-sessions:${sourceId}`; - if (!session) { + const _session = await redis.get(sessionId); + let session: BotCore; + + if (_session == null) { const user = await User.findOne({ line: { user_id: sourceId } }); - let core: BotCore; - if (user) { - core = new BotCore(user); + session = new BotCore(user); } else { - core = new BotCore(); - core.on('set-user', user => { + session = new BotCore(); + session.on('set-user', user => { User.update(user._id, { $set: { line: { @@ -47,16 +47,18 @@ module.exports = async (app: express.Application) => { }); } - session = { - sourceId: sourceId, - core: core - }; - - sessions.push(session); + redis.set(sessionId, JSON.stringify(session.export())); + } else { + session = BotCore.import(JSON.parse(_session)); } - const res = await session.core.q(ev.message.text); + session.on('updated', () => { + redis.set(sessionId, JSON.stringify(session.export())); + }); + const res = await session.q(ev.message.text); + + // 返信 request.post({ url: 'https://api.line.me/v2/bot/message/reply', headers: {