This commit is contained in:
syuilo 2019-01-15 18:47:22 +09:00
parent cac1badb98
commit 2f916de51c
No known key found for this signature in database
GPG key ID: BDC4C49D06AB9D69
12 changed files with 83 additions and 81 deletions

View file

@ -4,17 +4,19 @@ import autobind from 'autobind-decorator';
import * as loki from 'lokijs'; import * as loki from 'lokijs';
import * as request from 'request-promise-native'; import * as request from 'request-promise-native';
import chalk from 'chalk'; import chalk from 'chalk';
const delay = require('timeout-as-promise');
import config from './config'; import config from './config';
import Module from './module'; import Module from './module';
import MessageLike from './message-like'; import Message from './message';
import { FriendDoc } from './friend'; import { FriendDoc } from './friend';
import { User } from './misskey/user'; import { User } from './misskey/user';
import getCollection from './utils/get-collection'; import getCollection from './utils/get-collection';
import Stream from './stream'; import Stream from './stream';
import log from './log'; import log from './log';
type MentionHook = (msg: MessageLike) => boolean | HandlerResult; type MentionHook = (msg: Message) => boolean | HandlerResult;
type ContextHook = (msg: MessageLike, data?: any) => void | HandlerResult; type ContextHook = (msg: Message, data?: any) => void | HandlerResult;
export type HandlerResult = { export type HandlerResult = {
reaction: string; reaction: string;
@ -37,7 +39,7 @@ export default class 藍 {
public db: loki; public db: loki;
private contexts: loki.Collection<{ private contexts: loki.Collection<{
isMessage: boolean; isDm: boolean;
noteId?: string; noteId?: string;
userId?: string; userId?: string;
module: string; module: string;
@ -94,20 +96,20 @@ export default class 藍 {
mainStream.on('mention', data => { mainStream.on('mention', data => {
if (data.userId == this.account.id) return; // 自分は弾く if (data.userId == this.account.id) return; // 自分は弾く
if (data.text && data.text.startsWith('@' + this.account.username)) { if (data.text && data.text.startsWith('@' + this.account.username)) {
this.onMention(new MessageLike(this, data, false)); this.onReceiveMessage(new Message(this, data, false));
} }
}); });
// 返信されたとき // 返信されたとき
mainStream.on('reply', data => { mainStream.on('reply', data => {
if (data.userId == this.account.id) return; // 自分は弾く if (data.userId == this.account.id) return; // 自分は弾く
this.onMention(new MessageLike(this, data, false)); this.onReceiveMessage(new Message(this, data, false));
}); });
// メッセージ // メッセージ
mainStream.on('messagingMessage', data => { mainStream.on('messagingMessage', data => {
if (data.userId == this.account.id) return; // 自分は弾く if (data.userId == this.account.id) return; // 自分は弾く
this.onMention(new MessageLike(this, data, true)); this.onReceiveMessage(new Message(this, data, true));
}); });
//#endregion //#endregion
@ -125,17 +127,17 @@ export default class 藍 {
} }
@autobind @autobind
private onMention(msg: MessageLike) { private async onReceiveMessage(msg: Message): Promise<void> {
this.log(chalk.gray(`<<< An message received: ${chalk.underline(msg.id)}`)); this.log(chalk.gray(`<<< An message received: ${chalk.underline(msg.id)}`));
const isNoContext = !msg.isMessage && msg.replyId == null; const isNoContext = !msg.isDm && msg.replyId == null;
// Look up the context // Look up the context
const context = isNoContext ? null : this.contexts.findOne(msg.isMessage ? { const context = isNoContext ? null : this.contexts.findOne(msg.isDm ? {
isMessage: true, isDm: true,
userId: msg.userId userId: msg.userId
} : { } : {
isMessage: false, isDm: false,
noteId: msg.replyId noteId: msg.replyId
}); });
@ -161,22 +163,22 @@ export default class 藍 {
} }
} }
setTimeout(() => { await delay(1000);
if (msg.isMessage) {
// 既読にする if (msg.isDm) {
this.api('messaging/messages/read', { // 既読にする
messageId: msg.id, this.api('messaging/messages/read', {
messageId: msg.id,
});
} else {
// リアクションする
if (reaction) {
this.api('notes/reactions/create', {
noteId: msg.id,
reaction: reaction
}); });
} else {
// リアクションする
if (reaction) {
this.api('notes/reactions/create', {
noteId: msg.id,
reaction: reaction
});
}
} }
}, 1000); }
} }
@autobind @autobind
@ -202,15 +204,15 @@ export default class 藍 {
}; };
@autobind @autobind
public subscribeReply(module: Module, key: string, isMessage: boolean, id: string, data?: any) { public subscribeReply(module: Module, key: string, isDm: boolean, id: string, data?: any) {
this.contexts.insertOne(isMessage ? { this.contexts.insertOne(isDm ? {
isMessage: true, isDm: true,
userId: id, userId: id,
module: module.name, module: module.name,
key: key, key: key,
data: data data: data
} : { } : {
isMessage: false, isDm: false,
noteId: id, noteId: id,
module: module.name, module: module.name,
key: key, key: key,

View file

@ -7,10 +7,10 @@ import or from './utils/or';
import chalk from 'chalk'; import chalk from 'chalk';
const delay = require('timeout-as-promise'); const delay = require('timeout-as-promise');
export default class MessageLike { export default class Message {
private ai: ; private ai: ;
private messageOrNote: any; private messageOrNote: any;
public isMessage: boolean; public isDm: boolean;
public get id(): string { public get id(): string {
return this.messageOrNote.id; return this.messageOrNote.id;
@ -34,10 +34,10 @@ export default class MessageLike {
public friend: Friend; public friend: Friend;
constructor(ai: , messageOrNote: any, isMessage: boolean) { constructor(ai: , messageOrNote: any, isDm: boolean) {
this.ai = ai; this.ai = ai;
this.messageOrNote = messageOrNote; this.messageOrNote = messageOrNote;
this.isMessage = isMessage; this.isDm = isDm;
this.friend = new Friend(ai, { user: this.user }); this.friend = new Friend(ai, { user: this.user });
@ -57,7 +57,7 @@ export default class MessageLike {
await delay(2000); await delay(2000);
if (this.isMessage) { if (this.isDm) {
return await this.ai.sendMessage(this.messageOrNote.userId, { return await this.ai.sendMessage(this.messageOrNote.userId, {
text: text text: text
}); });

View file

@ -19,8 +19,8 @@ export default abstract class Module {
} }
@autobind @autobind
protected subscribeReply(key: string, isMessage: boolean, id: string, data?: any) { protected subscribeReply(key: string, isDm: boolean, id: string, data?: any) {
this.ai.subscribeReply(this, key, isMessage, id, data); this.ai.subscribeReply(this, key, isDm, id, data);
} }
@autobind @autobind

View file

@ -1,7 +1,7 @@
import autobind from 'autobind-decorator'; import autobind from 'autobind-decorator';
import { HandlerResult } from '../../ai'; import { HandlerResult } from '../../ai';
import Module from '../../module'; import Module from '../../module';
import MessageLike from '../../message-like'; import Message from '../../message';
import serifs, { getSerif } from '../../serifs'; import serifs, { getSerif } from '../../serifs';
import getDate from '../../utils/get-date'; import getDate from '../../utils/get-date';
@ -21,7 +21,7 @@ export default class CoreModule extends Module {
} }
@autobind @autobind
private mentionHook(msg: MessageLike) { private mentionHook(msg: Message) {
if (!msg.text) return false; if (!msg.text) return false;
return ( return (
@ -40,13 +40,13 @@ export default class CoreModule extends Module {
} }
@autobind @autobind
private setName(msg: MessageLike): boolean { private setName(msg: Message): boolean {
if (!msg.text) return false; if (!msg.text) return false;
if (!msg.text.includes('って呼んで')) return false; if (!msg.text.includes('って呼んで')) return false;
if (msg.text.startsWith('って呼んで')) return false; if (msg.text.startsWith('って呼んで')) return false;
// メッセージのみ // メッセージのみ
if (!msg.isMessage) return true; if (!msg.isDm) return true;
if (msg.friend.love < 5) { if (msg.friend.love < 5) {
msg.reply(serifs.core.requireMoreLove); msg.reply(serifs.core.requireMoreLove);
@ -72,7 +72,7 @@ export default class CoreModule extends Module {
msg.reply(serifs.core.setNameOk(name)); msg.reply(serifs.core.setNameOk(name));
} else { } else {
msg.reply(serifs.core.san).then(reply => { msg.reply(serifs.core.san).then(reply => {
this.subscribeReply(msg.userId, msg.isMessage, msg.isMessage ? msg.userId : reply.id, { this.subscribeReply(msg.userId, msg.isDm, msg.isDm ? msg.userId : reply.id, {
name: name name: name
}); });
}); });
@ -82,7 +82,7 @@ export default class CoreModule extends Module {
} }
@autobind @autobind
private greet(msg: MessageLike): boolean { private greet(msg: Message): boolean {
if (msg.text == null) return false; if (msg.text == null) return false;
const incLove = () => { const incLove = () => {
@ -151,11 +151,11 @@ export default class CoreModule extends Module {
} }
@autobind @autobind
private nadenade(msg: MessageLike): boolean { private nadenade(msg: Message): boolean {
if (!msg.includes(['なでなで'])) return false; if (!msg.includes(['なでなで'])) return false;
// メッセージのみ // メッセージのみ
if (!msg.isMessage) return true; if (!msg.isDm) return true;
//#region 1日に1回だけ親愛度を上げる(嫌われてない場合のみ) //#region 1日に1回だけ親愛度を上げる(嫌われてない場合のみ)
if (msg.friend.love >= 0) { if (msg.friend.love >= 0) {
@ -186,11 +186,11 @@ export default class CoreModule extends Module {
} }
@autobind @autobind
private kawaii(msg: MessageLike): boolean { private kawaii(msg: Message): boolean {
if (!msg.includes(['かわいい', '可愛い'])) return false; if (!msg.includes(['かわいい', '可愛い'])) return false;
// メッセージのみ // メッセージのみ
if (!msg.isMessage) return true; if (!msg.isDm) return true;
msg.reply( msg.reply(
msg.friend.love >= 5 ? serifs.core.kawaii.love : msg.friend.love >= 5 ? serifs.core.kawaii.love :
@ -201,11 +201,11 @@ export default class CoreModule extends Module {
} }
@autobind @autobind
private suki(msg: MessageLike): boolean { private suki(msg: Message): boolean {
if (!msg.or(['好き', 'すき'])) return false; if (!msg.or(['好き', 'すき'])) return false;
// メッセージのみ // メッセージのみ
if (!msg.isMessage) return true; if (!msg.isDm) return true;
msg.reply( msg.reply(
msg.friend.love >= 5 ? (msg.friend.name ? serifs.core.suki.love(msg.friend.name) : serifs.core.suki.normal) : msg.friend.love >= 5 ? (msg.friend.name ? serifs.core.suki.love(msg.friend.name) : serifs.core.suki.normal) :
@ -216,11 +216,11 @@ export default class CoreModule extends Module {
} }
@autobind @autobind
private hug(msg: MessageLike): boolean { private hug(msg: Message): boolean {
if (!msg.or(['ぎゅ', 'むぎゅ', /^はぐ(し(て|よ|よう)?)?$/])) return false; if (!msg.or(['ぎゅ', 'むぎゅ', /^はぐ(し(て|よ|よう)?)?$/])) return false;
// メッセージのみ // メッセージのみ
if (!msg.isMessage) return true; if (!msg.isDm) return true;
//#region 前のハグから1分経ってない場合は返信しない //#region 前のハグから1分経ってない場合は返信しない
// これは、「ハグ」と言って「ぎゅー」と返信したとき、相手が // これは、「ハグ」と言って「ぎゅー」と返信したとき、相手が
@ -250,11 +250,11 @@ export default class CoreModule extends Module {
} }
@autobind @autobind
private humu(msg: MessageLike): boolean { private humu(msg: Message): boolean {
if (!msg.includes(['踏んで'])) return false; if (!msg.includes(['踏んで'])) return false;
// メッセージのみ // メッセージのみ
if (!msg.isMessage) return true; if (!msg.isDm) return true;
msg.reply( msg.reply(
msg.friend.love >= 5 ? serifs.core.humu.love : msg.friend.love >= 5 ? serifs.core.humu.love :
@ -265,11 +265,11 @@ export default class CoreModule extends Module {
} }
@autobind @autobind
private batou(msg: MessageLike): boolean { private batou(msg: Message): boolean {
if (!msg.includes(['罵倒して', '罵って'])) return false; if (!msg.includes(['罵倒して', '罵って'])) return false;
// メッセージのみ // メッセージのみ
if (!msg.isMessage) return true; if (!msg.isDm) return true;
msg.reply( msg.reply(
msg.friend.love >= 5 ? serifs.core.batou.love : msg.friend.love >= 5 ? serifs.core.batou.love :
@ -280,7 +280,7 @@ export default class CoreModule extends Module {
} }
@autobind @autobind
private ponkotu(msg: MessageLike): boolean | HandlerResult { private ponkotu(msg: Message): boolean | HandlerResult {
if (!msg.includes(['ぽんこつ'])) return false; if (!msg.includes(['ぽんこつ'])) return false;
msg.friend.decLove(); msg.friend.decLove();
@ -291,7 +291,7 @@ export default class CoreModule extends Module {
} }
@autobind @autobind
private rmrf(msg: MessageLike): boolean | HandlerResult { private rmrf(msg: Message): boolean | HandlerResult {
if (!msg.includes(['rm -rf'])) return false; if (!msg.includes(['rm -rf'])) return false;
msg.friend.decLove(); msg.friend.decLove();
@ -302,7 +302,7 @@ export default class CoreModule extends Module {
} }
@autobind @autobind
private shutdown(msg: MessageLike): boolean | HandlerResult { private shutdown(msg: Message): boolean | HandlerResult {
if (!msg.includes(['shutdown'])) return false; if (!msg.includes(['shutdown'])) return false;
msg.reply(serifs.core.shutdown); msg.reply(serifs.core.shutdown);
@ -313,7 +313,7 @@ export default class CoreModule extends Module {
} }
@autobind @autobind
private contextHook(msg: MessageLike, data: any) { private contextHook(msg: Message, data: any) {
if (msg.text == null) return; if (msg.text == null) return;
const done = () => { const done = () => {
@ -329,7 +329,7 @@ export default class CoreModule extends Module {
done(); done();
} else { } else {
msg.reply(serifs.core.yesOrNo).then(reply => { msg.reply(serifs.core.yesOrNo).then(reply => {
this.subscribeReply(msg.userId, msg.isMessage, reply.id, data); this.subscribeReply(msg.userId, msg.isDm, reply.id, data);
}); });
} }
} }

View file

@ -1,6 +1,6 @@
import autobind from 'autobind-decorator'; import autobind from 'autobind-decorator';
import Module from '../../module'; import Module from '../../module';
import MessageLike from '../../message-like'; import Message from '../../message';
import serifs from '../../serifs'; import serifs from '../../serifs';
export default class DiceModule extends Module { export default class DiceModule extends Module {
@ -14,7 +14,7 @@ export default class DiceModule extends Module {
} }
@autobind @autobind
private mentionHook(msg: MessageLike) { private mentionHook(msg: Message) {
if (msg.text == null) return false; if (msg.text == null) return false;
const query = msg.text.match(/([0-9]+)[dD]([0-9]+)/); const query = msg.text.match(/([0-9]+)[dD]([0-9]+)/);

View file

@ -1,6 +1,6 @@
import autobind from 'autobind-decorator'; import autobind from 'autobind-decorator';
import Module from '../../module'; import Module from '../../module';
import MessageLike from '../../message-like'; import Message from '../../message';
import serifs from '../../serifs'; import serifs from '../../serifs';
const hands = [ const hands = [
@ -137,7 +137,7 @@ export default class EmojiModule extends Module {
} }
@autobind @autobind
private mentionHook(msg: MessageLike) { private mentionHook(msg: Message) {
if (msg.includes(['顔文字', '絵文字', 'emoji', '福笑い'])) { if (msg.includes(['顔文字', '絵文字', 'emoji', '福笑い'])) {
const hand = hands[Math.floor(Math.random() * hands.length)]; const hand = hands[Math.floor(Math.random() * hands.length)];
const face = faces[Math.floor(Math.random() * faces.length)]; const face = faces[Math.floor(Math.random() * faces.length)];

View file

@ -1,6 +1,6 @@
import autobind from 'autobind-decorator'; import autobind from 'autobind-decorator';
import Module from '../../module'; import Module from '../../module';
import MessageLike from '../../message-like'; import Message from '../../message';
export default class FollowModule extends Module { export default class FollowModule extends Module {
public readonly name = 'follow'; public readonly name = 'follow';
@ -13,7 +13,7 @@ export default class FollowModule extends Module {
} }
@autobind @autobind
private mentionHook(msg: MessageLike) { private mentionHook(msg: Message) {
if (msg.text && msg.includes(['フォロー', 'フォロバ', 'follow me'])) { if (msg.text && msg.includes(['フォロー', 'フォロバ', 'follow me'])) {
if (!msg.user.isFollowing) { if (!msg.user.isFollowing) {
this.ai.api('following/create', { this.ai.api('following/create', {

View file

@ -1,6 +1,6 @@
import autobind from 'autobind-decorator'; import autobind from 'autobind-decorator';
import Module from '../../module'; import Module from '../../module';
import MessageLike from '../../message-like'; import Message from '../../message';
import serifs from '../../serifs'; import serifs from '../../serifs';
import * as seedrandom from 'seedrandom'; import * as seedrandom from 'seedrandom';
import { blessing, itemPrefixes, items } from './vocabulary'; import { blessing, itemPrefixes, items } from './vocabulary';
@ -16,7 +16,7 @@ export default class FortuneModule extends Module {
} }
@autobind @autobind
private mentionHook(msg: MessageLike) { private mentionHook(msg: Message) {
if (msg.includes(['占', 'うらな', '運勢', 'おみくじ'])) { if (msg.includes(['占', 'うらな', '運勢', 'おみくじ'])) {
const date = new Date(); const date = new Date();
const seed = `${date.getFullYear()}/${date.getMonth()}/${date.getDate()}@${msg.userId}`; const seed = `${date.getFullYear()}/${date.getMonth()}/${date.getDate()}@${msg.userId}`;

View file

@ -1,7 +1,7 @@
import autobind from 'autobind-decorator'; import autobind from 'autobind-decorator';
import * as loki from 'lokijs'; import * as loki from 'lokijs';
import Module from '../../module'; import Module from '../../module';
import MessageLike from '../../message-like'; import Message from '../../message';
import serifs from '../../serifs'; import serifs from '../../serifs';
import getCollection from '../../utils/get-collection'; import getCollection from '../../utils/get-collection';
@ -32,7 +32,7 @@ export default class GuessingGameModule extends Module {
} }
@autobind @autobind
private mentionHook(msg: MessageLike) { private mentionHook(msg: Message) {
if (!msg.includes(['数当て', '数あて'])) return false; if (!msg.includes(['数当て', '数あて'])) return false;
const exist = this.guesses.findOne({ const exist = this.guesses.findOne({
@ -40,7 +40,7 @@ export default class GuessingGameModule extends Module {
isEnded: false isEnded: false
}); });
if (!msg.isMessage) { if (!msg.isDm) {
if (exist != null) { if (exist != null) {
msg.reply(serifs.guessingGame.arleadyStarted); msg.reply(serifs.guessingGame.arleadyStarted);
} else { } else {
@ -62,14 +62,14 @@ export default class GuessingGameModule extends Module {
}); });
msg.reply(serifs.guessingGame.started).then(reply => { msg.reply(serifs.guessingGame.started).then(reply => {
this.subscribeReply(msg.userId, msg.isMessage, msg.isMessage ? msg.userId : reply.id); this.subscribeReply(msg.userId, msg.isDm, msg.isDm ? msg.userId : reply.id);
}); });
return true; return true;
} }
@autobind @autobind
private contextHook(msg: MessageLike) { private contextHook(msg: Message) {
if (msg.text == null) return; if (msg.text == null) return;
const exist = this.guesses.findOne({ const exist = this.guesses.findOne({
@ -90,7 +90,7 @@ export default class GuessingGameModule extends Module {
if (guess == null) { if (guess == null) {
msg.reply(serifs.guessingGame.nan).then(reply => { msg.reply(serifs.guessingGame.nan).then(reply => {
this.subscribeReply(msg.userId, msg.isMessage, reply.id); this.subscribeReply(msg.userId, msg.isDm, reply.id);
}); });
return; return;
} }
@ -128,7 +128,7 @@ export default class GuessingGameModule extends Module {
msg.reply(text).then(reply => { msg.reply(text).then(reply => {
if (!end) { if (!end) {
this.subscribeReply(msg.userId, msg.isMessage, reply.id); this.subscribeReply(msg.userId, msg.isDm, reply.id);
} }
}); });
} }

View file

@ -1,6 +1,6 @@
import autobind from 'autobind-decorator'; import autobind from 'autobind-decorator';
import Module from '../../module'; import Module from '../../module';
import MessageLike from '../../message-like'; import Message from '../../message';
export default class PingModule extends Module { export default class PingModule extends Module {
public readonly name = 'ping'; public readonly name = 'ping';
@ -13,7 +13,7 @@ export default class PingModule extends Module {
} }
@autobind @autobind
private mentionHook(msg: MessageLike) { private mentionHook(msg: Message) {
if (msg.text && msg.text.includes('ping')) { if (msg.text && msg.text.includes('ping')) {
msg.reply('PONG!'); msg.reply('PONG!');
return true; return true;

View file

@ -3,7 +3,7 @@ import autobind from 'autobind-decorator';
import Module from '../../module'; import Module from '../../module';
import serifs from '../../serifs'; import serifs from '../../serifs';
import config from '../../config'; import config from '../../config';
import MessageLike from '../../message-like'; import Message from '../../message';
import Friend from '../../friend'; import Friend from '../../friend';
import getDate from '../../utils/get-date'; import getDate from '../../utils/get-date';
@ -33,7 +33,7 @@ export default class ReversiModule extends Module {
} }
@autobind @autobind
private mentionHook(msg: MessageLike) { private mentionHook(msg: Message) {
if (msg.includes(['リバーシ', 'オセロ', 'reversi', 'othello'])) { if (msg.includes(['リバーシ', 'オセロ', 'reversi', 'othello'])) {
if (config.reversiEnabled) { if (config.reversiEnabled) {
msg.reply(serifs.reversi.ok); msg.reply(serifs.reversi.ok);

View file

@ -1,6 +1,6 @@
import autobind from 'autobind-decorator'; import autobind from 'autobind-decorator';
import Module from '../../module'; import Module from '../../module';
import MessageLike from '../../message-like'; import Message from '../../message';
import serifs from '../../serifs'; import serifs from '../../serifs';
export default class TimerModule extends Module { export default class TimerModule extends Module {
@ -14,7 +14,7 @@ export default class TimerModule extends Module {
} }
@autobind @autobind
private mentionHook(msg: MessageLike) { private mentionHook(msg: Message) {
const secondsQuery = (msg.text || '').match(/([0-9]+)秒/); const secondsQuery = (msg.text || '').match(/([0-9]+)秒/);
const minutesQuery = (msg.text || '').match(/([0-9]+)分/); const minutesQuery = (msg.text || '').match(/([0-9]+)分/);
const hoursQuery = (msg.text || '').match(/([0-9]+)時間/); const hoursQuery = (msg.text || '').match(/([0-9]+)時間/);