2018-08-27 08:24:04 +00:00
|
|
|
import * as loki from 'lokijs';
|
2018-08-13 08:54:56 +00:00
|
|
|
import 藍 from '../../ai';
|
|
|
|
import IModule from '../../module';
|
|
|
|
import config from '../../config';
|
|
|
|
import serifs from '../../serifs';
|
2018-08-29 07:26:33 +00:00
|
|
|
import getCollection from '../../utils/get-collection';
|
2018-08-13 09:17:38 +00:00
|
|
|
const MeCab = require('mecab-async');
|
2018-08-13 08:54:56 +00:00
|
|
|
|
2018-08-13 09:26:45 +00:00
|
|
|
function kanaToHira(str: string) {
|
|
|
|
return str.replace(/[\u30a1-\u30f6]/g, match => {
|
|
|
|
const chr = match.charCodeAt(0) - 0x60;
|
|
|
|
return String.fromCharCode(chr);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-08-13 08:54:56 +00:00
|
|
|
export default class KeywordModule implements IModule {
|
2018-08-30 23:20:49 +00:00
|
|
|
public readonly name = 'keyword';
|
2018-08-13 08:54:56 +00:00
|
|
|
|
|
|
|
private ai: 藍;
|
2018-08-13 09:17:38 +00:00
|
|
|
private tokenizer: any;
|
2018-08-27 08:24:04 +00:00
|
|
|
private learnedKeywords: loki.Collection<{
|
|
|
|
keyword: string;
|
|
|
|
learnedAt: number;
|
|
|
|
}>;
|
2018-08-13 08:54:56 +00:00
|
|
|
|
|
|
|
public install = (ai: 藍) => {
|
|
|
|
this.ai = ai;
|
|
|
|
|
2018-08-27 08:24:04 +00:00
|
|
|
//#region Init DB
|
2018-08-29 07:26:33 +00:00
|
|
|
this.learnedKeywords = getCollection(this.ai.db, '_keyword_learnedKeywords', {
|
|
|
|
indices: ['userId']
|
|
|
|
});
|
2018-08-27 08:24:04 +00:00
|
|
|
//#endregion
|
|
|
|
|
2018-08-13 09:17:38 +00:00
|
|
|
this.tokenizer = new MeCab();
|
|
|
|
this.tokenizer.command = config.mecab;
|
|
|
|
|
2018-08-13 20:02:02 +00:00
|
|
|
setInterval(this.say, 1000 * 60 * 60);
|
2018-08-13 08:54:56 +00:00
|
|
|
}
|
|
|
|
|
2018-08-27 08:24:04 +00:00
|
|
|
private say = async () => {
|
2018-08-13 20:43:31 +00:00
|
|
|
const tl = await this.ai.api('notes/local-timeline', {
|
|
|
|
limit: 30
|
|
|
|
});
|
2018-08-13 08:54:56 +00:00
|
|
|
|
|
|
|
const interestedNotes = tl.filter(note => note.userId !== this.ai.account.id && note.text != null);
|
|
|
|
|
2018-08-13 09:17:38 +00:00
|
|
|
let keywords: string[][] = [];
|
2018-08-13 08:54:56 +00:00
|
|
|
|
2018-08-13 09:17:38 +00:00
|
|
|
await Promise.all(interestedNotes.map(note => new Promise((res, rej) => {
|
|
|
|
this.tokenizer.parse(note.text, (err, tokens) => {
|
2018-08-13 09:20:39 +00:00
|
|
|
const keywordsInThisNote = tokens.filter(token => token[2] == '固有名詞' && token[8] != null);
|
2018-08-13 09:17:38 +00:00
|
|
|
keywords = keywords.concat(keywordsInThisNote);
|
|
|
|
res();
|
|
|
|
});
|
|
|
|
})));
|
2018-08-13 08:54:56 +00:00
|
|
|
|
2018-08-14 16:49:31 +00:00
|
|
|
const rnd = Math.floor((1 - Math.sqrt(Math.random())) * keywords.length);
|
|
|
|
const keyword = keywords.sort((a, b) => a[0].length < b[0].length ? 1 : -1)[rnd];
|
2018-08-13 08:54:56 +00:00
|
|
|
|
2018-08-27 08:24:04 +00:00
|
|
|
const exist = this.learnedKeywords.findOne({
|
|
|
|
keyword: keyword[0]
|
|
|
|
});
|
|
|
|
|
|
|
|
let text: string;
|
2018-08-13 09:17:38 +00:00
|
|
|
|
2018-08-27 08:24:04 +00:00
|
|
|
if (exist) {
|
2018-08-27 09:53:57 +00:00
|
|
|
text = serifs.keyword.remembered
|
2018-08-27 08:24:04 +00:00
|
|
|
.replace('{reading}', kanaToHira(keyword[8]));
|
2018-08-13 09:17:38 +00:00
|
|
|
} else {
|
2018-08-27 08:24:04 +00:00
|
|
|
this.learnedKeywords.insertOne({
|
|
|
|
keyword: keyword[0],
|
|
|
|
learnedAt: Date.now()
|
2018-08-13 09:30:13 +00:00
|
|
|
});
|
2018-08-13 08:54:56 +00:00
|
|
|
|
2018-08-27 09:53:57 +00:00
|
|
|
text = serifs.keyword.learned
|
|
|
|
.replace('{word}', keyword[0])
|
2018-08-27 08:24:04 +00:00
|
|
|
.replace('{reading}', kanaToHira(keyword[8]));
|
2018-08-13 08:54:56 +00:00
|
|
|
}
|
2018-08-27 08:24:04 +00:00
|
|
|
|
|
|
|
this.ai.post({
|
|
|
|
text: text
|
|
|
|
});
|
2018-08-13 08:54:56 +00:00
|
|
|
}
|
|
|
|
}
|