This commit is contained in:
syuilo
2017-10-08 03:24:10 +09:00
parent d4d110a5c2
commit b18e4fea98
3 changed files with 391 additions and 43 deletions

View File

@ -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<string | void> {
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<string> {
this.othello = new Othello();
return this.othello.toPatternString('black');
}
public async q(query: string): Promise<string> {
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;
}
}

View File

@ -50,38 +50,44 @@ class LineBot extends BotCore {
public async react(ev: any): Promise<void> {
this.replyToken = ev.replyToken;
// メッセージ
if (ev.type == 'message') {
// テキスト
if (ev.message.type == 'text') {
const res = await this.q(ev.message.text);
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;
if (res == null) return;
// スタンプ
case 'sticker':
// スタンプで返信
this.reply([{
type: 'sticker',
packageId: '4',
stickerId: stickers[Math.floor(Math.random() * stickers.length)]
}]);
break;
}
break;
// 返信
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;
}
// 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);
});