mirror of
https://github.com/syuilo/ai.git
synced 2024-11-12 17:08:00 +00:00
parent
87f6729c98
commit
5bbd348c08
|
@ -3,10 +3,10 @@
|
|||
import * as loki from 'lokijs';
|
||||
import * as WebSocket from 'ws';
|
||||
import * as request from 'request-promise-native';
|
||||
import serifs from './serifs';
|
||||
import config from './config';
|
||||
import IModule from './module';
|
||||
import MessageLike from './message-like';
|
||||
import { FriendDoc } from './friend';
|
||||
const ReconnectingWebSocket = require('../node_modules/reconnecting-websocket/dist/reconnecting-websocket-cjs.js');
|
||||
|
||||
/**
|
||||
|
@ -38,10 +38,7 @@ export default class 藍 {
|
|||
data?: any;
|
||||
}>;
|
||||
|
||||
public friends: loki.Collection<{
|
||||
userId: string;
|
||||
name?: string;
|
||||
}>;
|
||||
public friends: loki.Collection<FriendDoc>;
|
||||
|
||||
constructor(account: any) {
|
||||
this.account = account;
|
||||
|
|
110
src/friend.ts
Normal file
110
src/friend.ts
Normal file
|
@ -0,0 +1,110 @@
|
|||
import 藍 from './ai';
|
||||
import IModule from './module';
|
||||
|
||||
export type FriendDoc = {
|
||||
userId: string;
|
||||
user: any;
|
||||
name?: string;
|
||||
love?: number;
|
||||
lastLoveIncrementedAt?: string;
|
||||
todayLoveIncrements?: number;
|
||||
perModulesData?: any;
|
||||
};
|
||||
|
||||
export default class Friend {
|
||||
private ai: 藍;
|
||||
|
||||
public get userId() {
|
||||
return this.doc.userId;
|
||||
}
|
||||
|
||||
public get name() {
|
||||
return this.doc.name;
|
||||
}
|
||||
|
||||
public get love() {
|
||||
return this.doc.love || 0;
|
||||
}
|
||||
|
||||
public doc: FriendDoc;
|
||||
|
||||
constructor(ai: 藍, opts: { user?: any, doc?: FriendDoc }) {
|
||||
this.ai = ai;
|
||||
|
||||
if (opts.user) {
|
||||
this.doc = this.ai.friends.findOne({
|
||||
userId: opts.user.id
|
||||
});
|
||||
|
||||
if (this.doc == null) {
|
||||
this.doc = this.ai.friends.insertOne({
|
||||
userId: opts.user.id,
|
||||
user: opts.user
|
||||
});
|
||||
} else {
|
||||
this.doc.user = opts.user;
|
||||
this.save();
|
||||
}
|
||||
} else {
|
||||
this.doc = opts.doc;
|
||||
}
|
||||
}
|
||||
|
||||
public updateUser = (user: any) => {
|
||||
this.doc.user = user;
|
||||
this.save();
|
||||
}
|
||||
|
||||
public getPerModulesData = (module: IModule) => {
|
||||
if (this.doc.perModulesData == null) {
|
||||
this.doc.perModulesData = {};
|
||||
this.doc.perModulesData[module.name] = {};
|
||||
this.save();
|
||||
} else if (this.doc.perModulesData[module.name] == null) {
|
||||
this.doc.perModulesData[module.name] = {};
|
||||
this.save();
|
||||
}
|
||||
|
||||
return this.doc.perModulesData[module.name];
|
||||
}
|
||||
|
||||
public setPerModulesData = (module: IModule, data: any) => {
|
||||
if (this.doc.perModulesData == null) {
|
||||
this.doc.perModulesData = {};
|
||||
}
|
||||
|
||||
this.doc.perModulesData[module.name] = data;
|
||||
|
||||
this.save();
|
||||
}
|
||||
|
||||
public incLove = () => {
|
||||
const now = new Date();
|
||||
const y = now.getFullYear();
|
||||
const m = now.getMonth();
|
||||
const d = now.getDate();
|
||||
const today = `${y}/${m + 1}/${d}`;
|
||||
|
||||
if (this.doc.lastLoveIncrementedAt != today) {
|
||||
this.doc.todayLoveIncrements = 0;
|
||||
}
|
||||
|
||||
// 1日に上げられる親愛度は最大3
|
||||
if (this.doc.lastLoveIncrementedAt == today && this.doc.todayLoveIncrements >= 3) return;
|
||||
|
||||
if (this.doc.love == null) this.doc.love = 0;
|
||||
this.doc.love++;
|
||||
this.doc.lastLoveIncrementedAt = today;
|
||||
this.doc.todayLoveIncrements = (this.doc.todayLoveIncrements || 0) + 1;
|
||||
this.save();
|
||||
}
|
||||
|
||||
public updateName = (name: string) => {
|
||||
this.doc.name = name;
|
||||
this.save();
|
||||
}
|
||||
|
||||
public save = () => {
|
||||
this.ai.friends.update(this.doc);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import 藍 from './ai';
|
||||
import Friend from './friend';
|
||||
const delay = require('timeout-as-promise');
|
||||
|
||||
export default class MessageLike {
|
||||
|
@ -26,22 +27,21 @@ export default class MessageLike {
|
|||
return this.messageOrNote.replyId;
|
||||
}
|
||||
|
||||
public friend: ReturnType<藍['friends']['findOne']>;
|
||||
public friend: Friend;
|
||||
|
||||
constructor(ai: 藍, messageOrNote: any, isMessage: boolean) {
|
||||
this.ai = ai;
|
||||
this.messageOrNote = messageOrNote;
|
||||
this.isMessage = isMessage;
|
||||
|
||||
this.friend = this.ai.friends.findOne({
|
||||
userId: this.userId
|
||||
});
|
||||
this.friend = new Friend(ai, { user: this.user });
|
||||
|
||||
if (this.friend == null) {
|
||||
this.friend = this.ai.friends.insertOne({
|
||||
userId: this.userId
|
||||
});
|
||||
}
|
||||
// メッセージなどに付いているユーザー情報は省略されている場合があるので完全なユーザー情報を持ってくる
|
||||
this.ai.api('users/show', {
|
||||
userId: this.userId
|
||||
}).then(user => {
|
||||
this.friend.updateUser(user);
|
||||
});
|
||||
}
|
||||
|
||||
public reply = async (text: string, cw?: string) => {
|
||||
|
|
|
@ -3,6 +3,11 @@ import 藍 from '../../ai';
|
|||
import IModule from '../../module';
|
||||
import MessageLike from '../../message-like';
|
||||
import serifs from '../../serifs';
|
||||
import Friend from '../../friend';
|
||||
|
||||
function zeroPadding(num: number, length: number): string {
|
||||
return ('0000000000' + num).slice(-length);
|
||||
}
|
||||
|
||||
export default class CoreModule implements IModule {
|
||||
public name = 'core';
|
||||
|
@ -10,46 +15,117 @@ export default class CoreModule implements IModule {
|
|||
|
||||
public install = (ai: 藍) => {
|
||||
this.ai = ai;
|
||||
|
||||
this.crawleBirthday();
|
||||
setInterval(this.crawleBirthday, 1000 * 60 * 3);
|
||||
}
|
||||
|
||||
public onMention = (msg: MessageLike) => {
|
||||
if (!msg.text) return false;
|
||||
|
||||
if (msg.text.includes('って呼んで') && !msg.text.startsWith('って呼んで')) {
|
||||
const name = msg.text.match(/^(.+?)って呼んで/)[1];
|
||||
return this.setName(msg) || this.greet(msg);
|
||||
}
|
||||
|
||||
if (name.length > 10) {
|
||||
msg.reply(serifs.core.tooLong);
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* 誕生日のユーザーがいないかチェック(いたら祝う)
|
||||
*/
|
||||
private crawleBirthday = () => {
|
||||
const now = new Date();
|
||||
const y = now.getFullYear();
|
||||
const m = now.getMonth();
|
||||
const d = now.getDate();
|
||||
// Misskeyの誕生日は 2018-06-16 のような形式
|
||||
const today = `${zeroPadding(m + 1, 2)}-${d}`;
|
||||
|
||||
const withSan =
|
||||
name.endsWith('さん') ||
|
||||
name.endsWith('くん') ||
|
||||
name.endsWith('君') ||
|
||||
name.endsWith('ちゃん') ||
|
||||
name.endsWith('様');
|
||||
const birthFriends = this.ai.friends.find({
|
||||
'user.profile.birthday': { '$regex': new RegExp('-' + today + '$') }
|
||||
} as any);
|
||||
|
||||
if (withSan) {
|
||||
msg.friend.name = name;
|
||||
this.ai.friends.update(msg.friend);
|
||||
msg.reply(serifs.core.setNameOk.replace('{name}', name));
|
||||
} else {
|
||||
msg.reply(serifs.core.san).then(reply => {
|
||||
this.ai.subscribeReply(this, msg.userId, msg.isMessage, msg.isMessage ? msg.userId : reply.id, {
|
||||
name: name
|
||||
});
|
||||
});
|
||||
}
|
||||
birthFriends.forEach(f => {
|
||||
const friend = new Friend(this.ai, { doc: f });
|
||||
|
||||
const data = friend.getPerModulesData(this);
|
||||
|
||||
if (data.lastBirthdayChecked == today) return;
|
||||
|
||||
data.lastBirthdayChecked = today;
|
||||
friend.setPerModulesData(this, data);
|
||||
|
||||
const text = friend.name ? serifs.core.happyBirthdayWithName.replace('{name}', friend.name) : serifs.core.happyBirthday;
|
||||
|
||||
this.ai.sendMessage(friend.userId, {
|
||||
text: text
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private setName = (msg: MessageLike): boolean => {
|
||||
if (!msg.text) return false;
|
||||
if (!msg.text.includes('って呼んで')) return false;
|
||||
if (msg.text.startsWith('って呼んで')) return false;
|
||||
|
||||
if (msg.friend.love < 5) {
|
||||
msg.reply(serifs.core.requireMoreLove);
|
||||
return true;
|
||||
} else if (msg.text.includes('おはよう')) {
|
||||
}
|
||||
|
||||
const name = msg.text.match(/^(.+?)って呼んで/)[1];
|
||||
|
||||
if (name.length > 10) {
|
||||
msg.reply(serifs.core.tooLong);
|
||||
return true;
|
||||
}
|
||||
|
||||
const withSan =
|
||||
name.endsWith('さん') ||
|
||||
name.endsWith('くん') ||
|
||||
name.endsWith('君') ||
|
||||
name.endsWith('ちゃん') ||
|
||||
name.endsWith('様');
|
||||
|
||||
if (withSan) {
|
||||
msg.friend.updateName(name);
|
||||
msg.reply(serifs.core.setNameOk.replace('{name}', name));
|
||||
} else {
|
||||
msg.reply(serifs.core.san).then(reply => {
|
||||
this.ai.subscribeReply(this, msg.userId, msg.isMessage, msg.isMessage ? msg.userId : reply.id, {
|
||||
name: name
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private greet = (msg: MessageLike): boolean => {
|
||||
if (!msg.text) return false;
|
||||
|
||||
const incLove = () => {
|
||||
const now = new Date();
|
||||
const y = now.getFullYear();
|
||||
const m = now.getMonth();
|
||||
const d = now.getDate();
|
||||
const date = `${y}/${m + 1}/${d}`;
|
||||
|
||||
const data = msg.friend.getPerModulesData(this);
|
||||
|
||||
if (data.lastGreetedAt == date) return;
|
||||
|
||||
data.lastGreetedAt = date;
|
||||
msg.friend.setPerModulesData(this, data);
|
||||
|
||||
msg.friend.incLove();
|
||||
};
|
||||
|
||||
if (msg.text.includes('おはよう')) {
|
||||
if (msg.friend.name) {
|
||||
msg.reply(serifs.core.goodMorningWithName.replace('{name}', msg.friend.name));
|
||||
} else {
|
||||
msg.reply(serifs.core.goodMorning);
|
||||
}
|
||||
|
||||
incLove();
|
||||
|
||||
return true;
|
||||
} else if (msg.text.includes('おやすみ')) {
|
||||
if (msg.friend.name) {
|
||||
|
@ -58,6 +134,8 @@ export default class CoreModule implements IModule {
|
|||
msg.reply(serifs.core.goodNight);
|
||||
}
|
||||
|
||||
incLove();
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -68,16 +146,15 @@ export default class CoreModule implements IModule {
|
|||
if (msg.text == null) return;
|
||||
|
||||
const done = () => {
|
||||
this.ai.friends.update(msg.friend);
|
||||
msg.reply(serifs.core.setNameOk.replace('{name}', msg.friend.name));
|
||||
this.ai.unsubscribeReply(this, msg.userId);
|
||||
};
|
||||
|
||||
if (msg.text.includes('はい')) {
|
||||
msg.friend.name = data.name + 'さん';
|
||||
msg.friend.updateName(data.name + 'さん');
|
||||
done();
|
||||
} else if (msg.text.includes('いいえ')) {
|
||||
msg.friend.name = data.name;
|
||||
msg.friend.updateName(data.name);
|
||||
done();
|
||||
} else {
|
||||
msg.reply(serifs.core.yesOrNo).then(reply => {
|
||||
|
|
|
@ -7,7 +7,10 @@ export default {
|
|||
goodMorningWithName: 'おはようございます、{name}!',
|
||||
goodNight: 'おやすみなさい!',
|
||||
goodNightWithName: 'おやすみなさい、{name}!',
|
||||
tooLong: '長すぎる気がします...'
|
||||
tooLong: '長すぎる気がします...',
|
||||
requireMoreLove: 'もっと仲良くなったら考えてあげてもいいですよ?',
|
||||
happyBirthday: 'お誕生日おめでとうございます🎉',
|
||||
happyBirthdayWithName: 'お誕生日おめでとうございます、{name}🎉'
|
||||
},
|
||||
|
||||
keyword: {
|
||||
|
|
Loading…
Reference in a new issue