From 93c0af613f97cd70dddd454150d8174c1dee3577 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 8 Nov 2017 14:58:48 +0900 Subject: Improve performance --- src/api/bot/core.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/api/bot/core.ts') diff --git a/src/api/bot/core.ts b/src/api/bot/core.ts index 53fb18119e..8324390880 100644 --- a/src/api/bot/core.ts +++ b/src/api/bot/core.ts @@ -232,7 +232,7 @@ class SigninContext extends Context { } } else { // Compare password - const same = bcrypt.compareSync(query, this.temporaryUser.password); + const same = await bcrypt.compare(query, this.temporaryUser.password); if (same) { this.bot.signin(this.temporaryUser); -- cgit v1.2.3-freya From 3f0f307104300e148b02f05fd51ac833f9b75b01 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 11 Nov 2017 00:27:02 +0900 Subject: [LINE] 通知の表示に対応 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/bot/core.ts | 24 ++++++++++++++++++++- src/api/models/notification.ts | 39 ++++++++++++++++++++++++++++++++++ src/common/get-notification-summary.ts | 28 ++++++++++++++++++++++++ src/common/get-reaction-emoji.ts | 14 ++++++++++++ 4 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 src/common/get-notification-summary.ts create mode 100644 src/common/get-reaction-emoji.ts (limited to 'src/api/bot/core.ts') diff --git a/src/api/bot/core.ts b/src/api/bot/core.ts index 8324390880..ff3f681804 100644 --- a/src/api/bot/core.ts +++ b/src/api/bot/core.ts @@ -5,6 +5,7 @@ import User, { IUser, init as initUser } from '../models/user'; import getPostSummary from '../../common/get-post-summary'; import getUserSummary from '../../common/get-user-summary'; +import getNotificationSummary from '../../common/get-notification-summary'; import Othello, { ai as othelloAi } from '../../common/othello'; @@ -84,6 +85,7 @@ export default class BotCore extends EventEmitter { 'logout, signout: サインアウトします\n' + 'post: 投稿します\n' + 'tl: タイムラインを見ます\n' + + 'no: 通知を見ます\n' + '@<ユーザー名>: ユーザーを表示します'; case 'me': @@ -115,6 +117,11 @@ export default class BotCore extends EventEmitter { case 'タイムライン': return await this.tlCommand(); + case 'no': + case 'notifications': + case '通知': + return await this.notificationsCommand(); + case 'guessing-game': case '数当てゲーム': this.setContext(new GuessingGameContext(this)); @@ -155,6 +162,7 @@ export default class BotCore extends EventEmitter { this.emit('updated'); } + // TODO: if (this.user == null) return 'まずサインインしてください。'; を @signinRequired みたいなデコレータでいい感じにする public async tlCommand(): Promise { if (this.user == null) return 'まずサインインしてください。'; @@ -163,7 +171,21 @@ export default class BotCore extends EventEmitter { }, this.user); const text = tl - .map(post => getPostSummary(post)) + .map(post => post.user.name + ': ' + getPostSummary(post)) + .join('\n-----\n'); + + return text; + } + + public async notificationsCommand(): Promise { + if (this.user == null) return 'まずサインインしてください。'; + + const notifications = await require('../endpoints/i/notifications')({ + limit: 5 + }, this.user); + + const text = notifications + .map(notification => getNotificationSummary(notification)) .join('\n-----\n'); return text; diff --git a/src/api/models/notification.ts b/src/api/models/notification.ts index 1065e8baaa..ecd1c25e10 100644 --- a/src/api/models/notification.ts +++ b/src/api/models/notification.ts @@ -1,8 +1,47 @@ import * as mongo from 'mongodb'; import db from '../../db/mongodb'; +import { IUser } from './user'; export default db.get('notifications') as any; // fuck type definition export interface INotification { _id: mongo.ObjectID; + created_at: Date; + + /** + * 通知の受信者 + */ + notifiee?: IUser; + + /** + * 通知の受信者 + */ + notifiee_id: mongo.ObjectID; + + /** + * イニシエータ(initiator)。通知を行う原因となったユーザー + */ + notifier?: IUser; + + /** + * イニシエータ(initiator)。通知を行う原因となったユーザー + */ + notifier_id: mongo.ObjectID; + + /** + * 通知の種類。 + * follow - フォローされた + * mention - 投稿で自分が言及された + * reply - (自分または自分がWatchしている)投稿が返信された + * repost - (自分または自分がWatchしている)投稿がRepostされた + * quote - (自分または自分がWatchしている)投稿が引用Repostされた + * reaction - (自分または自分がWatchしている)投稿にリアクションされた + * poll_vote - (自分または自分がWatchしている)投稿の投票に投票された + */ + type: 'follow' | 'mention' | 'reply' | 'repost' | 'quote' | 'reaction' | 'poll_vote'; + + /** + * 通知が読まれたかどうか + */ + is_read: Boolean; } diff --git a/src/common/get-notification-summary.ts b/src/common/get-notification-summary.ts new file mode 100644 index 0000000000..bf8610599c --- /dev/null +++ b/src/common/get-notification-summary.ts @@ -0,0 +1,28 @@ +import { INotification } from '../api/models/notification'; +import getPostSummary from './get-post-summary'; +import getReactionEmoji from './get-reaction-emoji'; + +/** + * 通知を表す文字列を取得します。 + * @param notification 通知 + */ +export default function(notification: INotification & any): string { + switch (notification.type) { + case 'follow': + return `${notification.notifier.name}にフォローされました`; + case 'mention': + return `言及されました: ${notification.notifier.name}「${getPostSummary(notification.post)}」`; + case 'reply': + return `返信されました: ${notification.notifier.name}「${getPostSummary(notification.post)}」`; + case 'repost': + return `Repostされました: ${notification.notifier.name}「${getPostSummary(notification.post)}」`; + case 'quote': + return `引用されました: ${notification.notifier.name}「${getPostSummary(notification.post)}」`; + case 'reaction': + return `リアクションされました: ${notification.notifier.name} <${getReactionEmoji(notification.reaction)}>「${getPostSummary(notification.post)}」`; + case 'poll_vote': + return `投票されました: ${notification.notifier.name}「${getPostSummary(notification.post)}」`; + default: + return `<不明な通知タイプ: ${notification.type}>`; + } +} diff --git a/src/common/get-reaction-emoji.ts b/src/common/get-reaction-emoji.ts new file mode 100644 index 0000000000..c661205379 --- /dev/null +++ b/src/common/get-reaction-emoji.ts @@ -0,0 +1,14 @@ +export default function(reaction: string): string { + switch (reaction) { + case 'like': return '👍'; + case 'love': return '❤️'; + case 'laugh': return '😆'; + case 'hmm': return '🤔'; + case 'surprise': return '😮'; + case 'congrats': return '🎉'; + case 'angry': return '💢'; + case 'confused': return '😥'; + case 'pudding': return '🍮'; + default: return ''; + } +} -- cgit v1.2.3-freya From f75f4b47190d90da2acb7de32777302d3d632793 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 11 Nov 2017 00:49:19 +0900 Subject: [Bot] タイムラインや通知を遡れるように MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/bot/core.ts | 151 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 117 insertions(+), 34 deletions(-) (limited to 'src/api/bot/core.ts') diff --git a/src/api/bot/core.ts b/src/api/bot/core.ts index ff3f681804..4b8d244471 100644 --- a/src/api/bot/core.ts +++ b/src/api/bot/core.ts @@ -63,7 +63,7 @@ export default class BotCore extends EventEmitter { return bot; } - public async q(query: string): Promise { + public async q(query: string): Promise { if (this.context != null) { return await this.context.q(query); } @@ -86,7 +86,9 @@ export default class BotCore extends EventEmitter { 'post: 投稿します\n' + 'tl: タイムラインを見ます\n' + 'no: 通知を見ます\n' + - '@<ユーザー名>: ユーザーを表示します'; + '@<ユーザー名>: ユーザーを表示します\n' + + '\n' + + 'タイムラインや通知を見た後、「次」というとさらに遡ることができます。'; case 'me': return this.user ? `${this.user.name}としてサインインしています。\n\n${getUserSummary(this.user)}` : 'サインインしていません'; @@ -115,12 +117,16 @@ export default class BotCore extends EventEmitter { case 'tl': case 'タイムライン': - return await this.tlCommand(); + if (this.user == null) return 'まずサインインしてください。'; + this.setContext(new TlContext(this)); + return await this.context.greet(); case 'no': case 'notifications': case '通知': - return await this.notificationsCommand(); + if (this.user == null) return 'まずサインインしてください。'; + this.setContext(new NotificationsContext(this)); + return await this.context.greet(); case 'guessing-game': case '数当てゲーム': @@ -162,36 +168,7 @@ export default class BotCore extends EventEmitter { this.emit('updated'); } - // TODO: if (this.user == null) return 'まずサインインしてください。'; を @signinRequired みたいなデコレータでいい感じにする - public async tlCommand(): Promise { - if (this.user == null) return 'まずサインインしてください。'; - - const tl = await require('../endpoints/posts/timeline')({ - limit: 5 - }, this.user); - - const text = tl - .map(post => post.user.name + ': ' + getPostSummary(post)) - .join('\n-----\n'); - - return text; - } - - public async notificationsCommand(): Promise { - if (this.user == null) return 'まずサインインしてください。'; - - const notifications = await require('../endpoints/i/notifications')({ - limit: 5 - }, this.user); - - const text = notifications - .map(notification => getNotificationSummary(notification)) - .join('\n-----\n'); - - return text; - } - - public async showUserCommand(q: string): Promise { + public async showUserCommand(q: string): Promise { try { const user = await require('../endpoints/users/show')({ username: q.substr(1) @@ -222,6 +199,8 @@ abstract class Context extends EventEmitter { if (data.type == 'guessing-game') return GuessingGameContext.import(bot, data.content); if (data.type == 'othello') return OthelloContext.import(bot, data.content); if (data.type == 'post') return PostContext.import(bot, data.content); + if (data.type == 'tl') return TlContext.import(bot, data.content); + if (data.type == 'notifications') return NotificationsContext.import(bot, data.content); if (data.type == 'signin') return SigninContext.import(bot, data.content); return null; } @@ -307,6 +286,110 @@ class PostContext extends Context { } } +class TlContext extends Context { + private next: string = null; + + public async greet(): Promise { + return await this.getTl(); + } + + public async q(query: string): Promise { + if (query == '次') { + return await this.getTl(); + } else { + this.bot.clearContext(); + return await this.bot.q(query); + } + } + + private async getTl() { + const tl = await require('../endpoints/posts/timeline')({ + limit: 5, + max_id: this.next ? this.next : undefined + }, this.bot.user); + + if (tl.length > 0) { + this.next = tl[tl.length - 1].id; + this.emit('updated'); + + const text = tl + .map(post => post.user.name + ': ' + getPostSummary(post)) + .join('\n-----\n'); + + return text; + } else { + return 'タイムラインに表示するものがありません...'; + } + } + + public export() { + return { + type: 'tl', + content: { + next: this.next, + } + }; + } + + public static import(bot: BotCore, data: any) { + const context = new TlContext(bot); + context.next = data.next; + return context; + } +} + +class NotificationsContext extends Context { + private next: string = null; + + public async greet(): Promise { + return await this.getNotifications(); + } + + public async q(query: string): Promise { + if (query == '次') { + return await this.getNotifications(); + } else { + this.bot.clearContext(); + return await this.bot.q(query); + } + } + + private async getNotifications() { + const notifications = await require('../endpoints/i/notifications')({ + limit: 5, + max_id: this.next ? this.next : undefined + }, this.bot.user); + + if (notifications.length > 0) { + this.next = notifications[notifications.length - 1].id; + this.emit('updated'); + + const text = notifications + .map(notification => getNotificationSummary(notification)) + .join('\n-----\n'); + + return text; + } else { + return '通知はありません'; + } + } + + public export() { + return { + type: 'notifications', + content: { + next: this.next, + } + }; + } + + public static import(bot: BotCore, data: any) { + const context = new NotificationsContext(bot); + context.next = data.next; + return context; + } +} + class GuessingGameContext extends Context { private secret: number; private history: number[] = []; -- cgit v1.2.3-freya From f3dd5da931fb4cb946d9243b6735b68927ca8a61 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 11 Nov 2017 01:15:11 +0900 Subject: Improve readability --- src/api/bot/core.ts | 2 +- src/common/get-notification-summary.ts | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/api/bot/core.ts') diff --git a/src/api/bot/core.ts b/src/api/bot/core.ts index 4b8d244471..ddae6405f5 100644 --- a/src/api/bot/core.ts +++ b/src/api/bot/core.ts @@ -313,7 +313,7 @@ class TlContext extends Context { this.emit('updated'); const text = tl - .map(post => post.user.name + ': ' + getPostSummary(post)) + .map(post => `${post.user.name}\n「${getPostSummary(post)}」`) .join('\n-----\n'); return text; diff --git a/src/common/get-notification-summary.ts b/src/common/get-notification-summary.ts index b49a170b65..03db722c84 100644 --- a/src/common/get-notification-summary.ts +++ b/src/common/get-notification-summary.ts @@ -10,17 +10,17 @@ export default function(notification: any): string { case 'follow': return `${notification.user.name}にフォローされました`; case 'mention': - return `言及されました: ${notification.user.name}「${getPostSummary(notification.post)}」`; + return `言及されました:\n${notification.user.name}「${getPostSummary(notification.post)}」`; case 'reply': - return `返信されました: ${notification.user.name}「${getPostSummary(notification.post)}」`; + return `返信されました:\n${notification.user.name}「${getPostSummary(notification.post)}」`; case 'repost': - return `Repostされました: ${notification.user.name}「${getPostSummary(notification.post)}」`; + return `Repostされました:\n${notification.user.name}「${getPostSummary(notification.post)}」`; case 'quote': - return `引用されました: ${notification.user.name}「${getPostSummary(notification.post)}」`; + return `引用されました:\n${notification.user.name}「${getPostSummary(notification.post)}」`; case 'reaction': - return `リアクションされました: ${notification.user.name} <${getReactionEmoji(notification.reaction)}>「${getPostSummary(notification.post)}」`; + return `リアクションされました:\n${notification.user.name} <${getReactionEmoji(notification.reaction)}>「${getPostSummary(notification.post)}」`; case 'poll_vote': - return `投票されました: ${notification.user.name}「${getPostSummary(notification.post)}」`; + return `投票されました:\n${notification.user.name}「${getPostSummary(notification.post)}」`; default: return `<不明な通知タイプ: ${notification.type}>`; } -- cgit v1.2.3-freya