From b18e4fea9851ce0692b3f1a627c1d220d5f16b9c Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 8 Oct 2017 03:24:10 +0900 Subject: :v: --- src/api/bot/core.ts | 51 +++++++++++++++++++ src/api/bot/interfaces/line.ts | 112 ++++++++++++++++++++++++----------------- 2 files changed, 118 insertions(+), 45 deletions(-) (limited to 'src/api') diff --git a/src/api/bot/core.ts b/src/api/bot/core.ts index bc5818d976..6042862d39 100644 --- a/src/api/bot/core.ts +++ b/src/api/bot/core.ts @@ -6,6 +6,8 @@ import User, { IUser, init as initUser } from '../models/user'; import getPostSummary from '../../common/get-post-summary'; import getUserSummary from '../../common/get-user-summary'; +import Othello, { ai as othelloAi } from '../../common/othello'; + /** * Botの頭脳 */ @@ -106,6 +108,11 @@ export default class BotCore extends EventEmitter { case 'タイムライン': return await this.tlCommand(); + case 'othello': + case 'オセロ': + this.setContext(new OthelloContext(this)); + return await this.context.greet(); + default: return '?'; } @@ -124,6 +131,18 @@ export default class BotCore extends EventEmitter { this.emit('updated'); } + public async refreshUser() { + this.user = await User.findOne({ + _id: this.user._id + }, { + fields: { + data: false + } + }); + + this.emit('updated'); + } + public async tlCommand(): Promise { if (this.user == null) return 'まずサインインしてください。'; @@ -166,6 +185,7 @@ abstract class Context extends EventEmitter { } public static import(bot: BotCore, data: any) { + if (data.type == 'othello') return OthelloContext.import(bot, data.content); if (data.type == 'post') return PostContext.import(bot, data.content); if (data.type == 'signin') return SigninContext.import(bot, data.content); return null; @@ -251,3 +271,34 @@ class PostContext extends Context { return context; } } + +class OthelloContext extends Context { + private othello: Othello = null; + + public async greet(): Promise { + this.othello = new Othello(); + return this.othello.toPatternString('black'); + } + + public async q(query: string): Promise { + this.othello.setByNumber('black', parseInt(query, 10)); + othelloAi('white', this.othello); + return this.othello.toPatternString('black'); + } + + public export() { + return { + type: 'othello', + content: { + board: this.othello.board + } + }; + } + + public static import(bot: BotCore, data: any) { + const context = new OthelloContext(bot); + context.othello = new Othello(); + context.othello.board = data.board; + return context; + } +} diff --git a/src/api/bot/interfaces/line.ts b/src/api/bot/interfaces/line.ts index 2bf62c1f6c..0caa71ed2b 100644 --- a/src/api/bot/interfaces/line.ts +++ b/src/api/bot/interfaces/line.ts @@ -50,38 +50,44 @@ class LineBot extends BotCore { public async react(ev: any): Promise { this.replyToken = ev.replyToken; - // メッセージ - if (ev.type == 'message') { - // テキスト - if (ev.message.type == 'text') { - const res = await this.q(ev.message.text); - - if (res == null) return; - - // 返信 - this.reply([{ - type: 'text', - text: res - }]); - // スタンプ - } else if (ev.message.type == 'sticker') { - // スタンプで返信 - this.reply([{ - type: 'sticker', - packageId: '4', - stickerId: stickers[Math.floor(Math.random() * stickers.length)] - }]); - } - // postback - } else if (ev.type == 'postback') { - const data = ev.postback.data; - const cmd = data.split('|')[0]; - const arg = data.split('|')[1]; - switch (cmd) { - case 'showtl': - this.showUserTimelinePostback(arg); - break; - } + switch (ev.type) { + // メッセージ + case 'message': + switch (ev.message.type) { + // テキスト + case 'text': + const res = await this.q(ev.message.text); + if (res == null) return; + // 返信 + this.reply([{ + type: 'text', + text: res + }]); + break; + + // スタンプ + case 'sticker': + // スタンプで返信 + this.reply([{ + type: 'sticker', + packageId: '4', + stickerId: stickers[Math.floor(Math.random() * stickers.length)] + }]); + break; + } + break; + + // postback + case 'postback': + const data = ev.postback.data; + const cmd = data.split('|')[0]; + const arg = data.split('|')[1]; + switch (cmd) { + case 'showtl': + this.showUserTimelinePostback(arg); + break; + } + break; } } @@ -96,6 +102,28 @@ class LineBot extends BotCore { username: q.substr(1) }, this.user); + const actions = []; + + actions.push({ + type: 'postback', + label: 'タイムラインを見る', + data: `showtl|${user.id}` + }); + + if (user.twitter) { + actions.push({ + type: 'uri', + label: 'Twitterアカウントを見る', + uri: `https://twitter.com/${user.twitter.screen_name}` + }); + } + + actions.push({ + type: 'uri', + label: 'Webで見る', + uri: `${config.url}/${user.username}` + }); + this.reply([{ type: 'template', altText: await super.showUserCommand(q), @@ -104,15 +132,7 @@ class LineBot extends BotCore { thumbnailImageUrl: `${user.avatar_url}?thumbnail&size=1024`, title: `${user.name} (@${user.username})`, text: user.description || '(no description)', - actions: [{ - type: 'postback', - label: 'タイムラインを見る', - data: `showtl|${user.id}` - }, { - type: 'uri', - label: 'Webで見る', - uri: `${config.url}/${user.username}` - }] + actions: actions } }]); } @@ -123,7 +143,7 @@ class LineBot extends BotCore { limit: 5 }, this.user); - const text = tl + const text = `${tl[0].user.name}さんのタイムラインはこちらです:\n\n` + tl .map(post => getPostSummary(post)) .join('\n-----\n'); @@ -144,10 +164,10 @@ module.exports = async (app: express.Application) => { const sourceId = ev.source.userId; const sessionId = `line-bot-sessions:${sourceId}`; - const _session = await redis.get(sessionId); + const session = await redis.get(sessionId); let bot: LineBot; - if (_session == null) { + if (session == null) { const user = await User.findOne({ line: { user_id: sourceId @@ -178,13 +198,15 @@ module.exports = async (app: express.Application) => { redis.set(sessionId, JSON.stringify(bot.export())); } else { - bot = LineBot.import(JSON.parse(_session)); + bot = LineBot.import(JSON.parse(session)); } bot.on('updated', () => { redis.set(sessionId, JSON.stringify(bot.export())); }); + if (session != null) bot.refreshUser(); + bot.react(ev); }); -- cgit v1.2.3-freya