2018-08-11 06:26:25 +00:00
|
|
|
// AI CORE
|
|
|
|
|
2018-08-26 21:16:56 +00:00
|
|
|
import * as loki from 'lokijs';
|
2018-08-11 06:26:25 +00:00
|
|
|
import * as WebSocket from 'ws';
|
|
|
|
import * as request from 'request-promise-native';
|
|
|
|
import config from './config';
|
|
|
|
import IModule from './module';
|
|
|
|
import MessageLike from './message-like';
|
2018-08-27 11:22:59 +00:00
|
|
|
import { FriendDoc } from './friend';
|
2018-08-11 06:26:25 +00:00
|
|
|
const ReconnectingWebSocket = require('../node_modules/reconnecting-websocket/dist/reconnecting-websocket-cjs.js');
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 藍
|
|
|
|
*/
|
|
|
|
export default class 藍 {
|
2018-08-12 14:03:00 +00:00
|
|
|
public account: any;
|
2018-08-11 06:26:25 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* ホームストリーム
|
|
|
|
*/
|
|
|
|
private connection: any;
|
|
|
|
|
2018-08-13 21:14:47 +00:00
|
|
|
/**
|
|
|
|
* ローカルタイムラインストリーム
|
|
|
|
*/
|
|
|
|
private localTimelineConnection: any;
|
|
|
|
|
2018-08-11 06:26:25 +00:00
|
|
|
private modules: IModule[] = [];
|
|
|
|
|
2018-08-26 21:16:56 +00:00
|
|
|
public db: loki;
|
|
|
|
|
|
|
|
private contexts: loki.Collection<{
|
|
|
|
isMessage: boolean;
|
|
|
|
noteId?: string;
|
|
|
|
userId?: string;
|
|
|
|
module: string;
|
|
|
|
key: string;
|
2018-08-26 21:59:18 +00:00
|
|
|
data?: any;
|
|
|
|
}>;
|
|
|
|
|
2018-08-27 11:22:59 +00:00
|
|
|
public friends: loki.Collection<FriendDoc>;
|
2018-08-26 21:16:56 +00:00
|
|
|
|
2018-08-28 07:02:20 +00:00
|
|
|
constructor(account: any, modules: IModule[]) {
|
2018-08-11 06:26:25 +00:00
|
|
|
this.account = account;
|
2018-08-28 07:02:20 +00:00
|
|
|
this.modules = modules;
|
2018-08-11 06:26:25 +00:00
|
|
|
|
2018-08-26 21:16:56 +00:00
|
|
|
this.db = new loki('memory.json', {
|
|
|
|
autoload: true,
|
|
|
|
autosave: true,
|
|
|
|
autosaveInterval: 1000,
|
|
|
|
autoloadCallback: this.init
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private init = () => {
|
|
|
|
//#region Init DB
|
|
|
|
this.contexts = this.db.getCollection('contexts');
|
|
|
|
if (this.contexts === null) {
|
|
|
|
this.contexts = this.db.addCollection('contexts', {
|
|
|
|
indices: ['key']
|
|
|
|
});
|
|
|
|
}
|
2018-08-26 21:59:18 +00:00
|
|
|
|
|
|
|
this.friends = this.db.getCollection('friends');
|
|
|
|
if (this.friends === null) {
|
|
|
|
this.friends = this.db.addCollection('friends', {
|
|
|
|
indices: ['userId']
|
|
|
|
});
|
|
|
|
}
|
2018-08-26 21:16:56 +00:00
|
|
|
//#endregion
|
|
|
|
|
|
|
|
// Install modules
|
|
|
|
this.modules.forEach(m => m.install(this));
|
|
|
|
|
2018-08-13 21:14:47 +00:00
|
|
|
//#region Home stream
|
2018-08-11 06:26:25 +00:00
|
|
|
this.connection = new ReconnectingWebSocket(`${config.wsUrl}/?i=${config.i}`, [], {
|
|
|
|
WebSocket: WebSocket
|
|
|
|
});
|
|
|
|
|
|
|
|
this.connection.addEventListener('open', () => {
|
|
|
|
console.log('home stream opened');
|
|
|
|
});
|
|
|
|
|
|
|
|
this.connection.addEventListener('close', () => {
|
|
|
|
console.log('home stream closed');
|
2018-08-25 05:18:16 +00:00
|
|
|
|
|
|
|
this.connection.reconnect();
|
2018-08-11 06:26:25 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
this.connection.addEventListener('message', message => {
|
|
|
|
const msg = JSON.parse(message.data);
|
|
|
|
|
|
|
|
this.onMessage(msg);
|
|
|
|
});
|
2018-08-13 21:14:47 +00:00
|
|
|
//#endregion
|
2018-08-11 06:26:25 +00:00
|
|
|
|
2018-08-13 21:14:47 +00:00
|
|
|
//#region Local timeline stream
|
|
|
|
this.localTimelineConnection = new ReconnectingWebSocket(`${config.wsUrl}/local-timeline?i=${config.i}`, [], {
|
|
|
|
WebSocket: WebSocket
|
|
|
|
});
|
|
|
|
|
|
|
|
this.localTimelineConnection.addEventListener('open', () => {
|
|
|
|
console.log('local-timeline stream opened');
|
|
|
|
});
|
|
|
|
|
|
|
|
this.localTimelineConnection.addEventListener('close', () => {
|
|
|
|
console.log('local-timeline stream closed');
|
2018-08-27 06:40:41 +00:00
|
|
|
|
|
|
|
this.localTimelineConnection.reconnect();
|
2018-08-13 21:14:47 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
this.localTimelineConnection.addEventListener('message', message => {
|
|
|
|
const msg = JSON.parse(message.data);
|
|
|
|
|
|
|
|
this.onLocalNote(msg.body);
|
|
|
|
});
|
|
|
|
//#endregion
|
2018-08-11 06:26:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private onMessage = (msg: any) => {
|
|
|
|
switch (msg.type) {
|
|
|
|
// メンションされたとき
|
|
|
|
case 'mention': {
|
|
|
|
if (msg.body.userId == this.account.id) return; // 自分は弾く
|
|
|
|
if (msg.body.text.startsWith('@' + this.account.username)) {
|
|
|
|
this.onMention(new MessageLike(this, msg.body, false));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 返信されたとき
|
|
|
|
case 'reply': {
|
|
|
|
if (msg.body.userId == this.account.id) return; // 自分は弾く
|
|
|
|
this.onMention(new MessageLike(this, msg.body, false));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// メッセージ
|
|
|
|
case 'messaging_message': {
|
|
|
|
if (msg.body.userId == this.account.id) return; // 自分は弾く
|
|
|
|
this.onMention(new MessageLike(this, msg.body, true));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-13 21:14:47 +00:00
|
|
|
private onLocalNote = (note: any) => {
|
|
|
|
this.modules.filter(m => m.hasOwnProperty('onLocalNote')).forEach(m => {
|
|
|
|
return m.onLocalNote(note);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-08-11 06:26:25 +00:00
|
|
|
private onMention = (msg: MessageLike) => {
|
|
|
|
console.log(`mention received: ${msg.id}`);
|
|
|
|
|
2018-08-11 12:16:52 +00:00
|
|
|
setTimeout(() => {
|
|
|
|
if (msg.isMessage) {
|
|
|
|
// 既読にする
|
2018-08-11 12:43:55 +00:00
|
|
|
this.api('messaging/messages/read', {
|
2018-08-11 12:16:52 +00:00
|
|
|
messageId: msg.id,
|
2018-08-11 06:26:25 +00:00
|
|
|
});
|
2018-08-11 12:16:52 +00:00
|
|
|
} else {
|
|
|
|
// リアクションする
|
2018-08-11 12:43:55 +00:00
|
|
|
this.api('notes/reactions/create', {
|
2018-08-11 12:16:52 +00:00
|
|
|
noteId: msg.id,
|
|
|
|
reaction: 'love'
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}, 1000);
|
2018-08-11 06:26:25 +00:00
|
|
|
|
2018-08-26 21:16:56 +00:00
|
|
|
const context = !msg.isMessage && msg.replyId == null ? null : this.contexts.findOne(msg.isMessage ? {
|
2018-08-12 14:03:00 +00:00
|
|
|
isMessage: true,
|
|
|
|
userId: msg.userId
|
|
|
|
} : {
|
|
|
|
isMessage: false,
|
|
|
|
noteId: msg.replyId
|
2018-08-11 06:26:25 +00:00
|
|
|
});
|
2018-08-12 14:03:00 +00:00
|
|
|
|
|
|
|
if (context != null) {
|
|
|
|
const module = this.modules.find(m => m.name == context.module);
|
2018-08-26 21:59:18 +00:00
|
|
|
module.onReplyThisModule(msg, context.data);
|
2018-08-12 14:03:00 +00:00
|
|
|
} else {
|
|
|
|
this.modules.filter(m => m.hasOwnProperty('onMention')).some(m => {
|
|
|
|
return m.onMention(msg);
|
|
|
|
});
|
|
|
|
}
|
2018-08-11 06:26:25 +00:00
|
|
|
}
|
|
|
|
|
2018-08-12 14:03:00 +00:00
|
|
|
public post = async (param: any) => {
|
|
|
|
const res = await this.api('notes/create', param);
|
|
|
|
return res.createdNote;
|
2018-08-11 06:26:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public sendMessage = (userId: any, param: any) => {
|
2018-08-12 14:03:00 +00:00
|
|
|
return this.api('messaging/messages/create', Object.assign({
|
2018-08-11 06:26:25 +00:00
|
|
|
userId: userId,
|
|
|
|
}, param));
|
|
|
|
}
|
|
|
|
|
2018-08-13 08:54:56 +00:00
|
|
|
public api = (endpoint: string, param?: any) => {
|
2018-08-11 06:26:25 +00:00
|
|
|
return request.post(`${config.apiUrl}/${endpoint}`, {
|
|
|
|
json: Object.assign({
|
|
|
|
i: config.i
|
|
|
|
}, param)
|
|
|
|
});
|
|
|
|
};
|
2018-08-12 14:03:00 +00:00
|
|
|
|
2018-08-26 21:59:18 +00:00
|
|
|
public subscribeReply = (module: IModule, key: string, isMessage: boolean, id: string, data?: any) => {
|
2018-08-26 21:16:56 +00:00
|
|
|
this.contexts.insertOne(isMessage ? {
|
2018-08-12 14:03:00 +00:00
|
|
|
isMessage: true,
|
|
|
|
userId: id,
|
|
|
|
module: module.name,
|
|
|
|
key: key,
|
2018-08-26 21:59:18 +00:00
|
|
|
data: data
|
2018-08-12 14:03:00 +00:00
|
|
|
} : {
|
|
|
|
isMessage: false,
|
|
|
|
noteId: id,
|
|
|
|
module: module.name,
|
|
|
|
key: key,
|
2018-08-26 21:59:18 +00:00
|
|
|
data: data
|
2018-08-12 14:03:00 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public unsubscribeReply = (module: IModule, key: string) => {
|
2018-08-26 21:16:56 +00:00
|
|
|
this.contexts.findAndRemove({
|
2018-08-12 14:03:00 +00:00
|
|
|
key: key,
|
|
|
|
module: module.name
|
|
|
|
});
|
|
|
|
}
|
2018-08-11 06:26:25 +00:00
|
|
|
}
|