202 lines
6.4 KiB
TypeScript
202 lines
6.4 KiB
TypeScript
|
import * as electronRemote from '@electron/remote';
|
||
|
const electronConsole = electronRemote.getGlobal('console') as Console;
|
||
|
import Logger from '../../logger/logger';
|
||
|
const LOG = Logger.create(__filename, electronConsole);
|
||
|
|
||
|
import * as socketio from 'socket.io-client';
|
||
|
import PersonalDBGuild from './guild-personal-db';
|
||
|
import RAMGuild from './guild-ram';
|
||
|
import SocketGuild from './guild-socket';
|
||
|
import { Changes, Channel, GuildMetadata, Member, Message, Resource, ServerMetaData, SocketConfig, Token } from './data-types';
|
||
|
|
||
|
import MessageRAMCache from "./message-ram-cache";
|
||
|
import PersonalDB from "./personal-db";
|
||
|
import ResourceRAMCache from "./resource-ram-cache";
|
||
|
import SocketVerifier from './socket-verifier';
|
||
|
import { Connectable, AsyncGuaranteedFetchable } from './guild-types';
|
||
|
import { AutoVerifier } from './auto-verifier';
|
||
|
import { AutoVerifierWithArg, PartialListQuery } from './auto-verifier-with-args';
|
||
|
import GuildPairVerifierGuild from './guild-pair-verifier';
|
||
|
|
||
|
export default class GuildController extends Connectable implements AsyncGuaranteedFetchable {
|
||
|
private readonly ramGuild: RAMGuild;
|
||
|
private readonly personalDBGuild: PersonalDBGuild;
|
||
|
private readonly socketGuild: SocketGuild;
|
||
|
|
||
|
private readonly pairVerifiers: GuildPairVerifierGuild[];
|
||
|
private readonly fetchable: AsyncGuaranteedFetchable;
|
||
|
|
||
|
constructor(
|
||
|
private readonly id: number,
|
||
|
private readonly memberId: string,
|
||
|
socket: socketio.Socket,
|
||
|
socketVerifier: SocketVerifier,
|
||
|
messageRAMCache: MessageRAMCache,
|
||
|
resourceRAMCache: ResourceRAMCache,
|
||
|
personalDB: PersonalDB
|
||
|
) {
|
||
|
super();
|
||
|
|
||
|
this.ramGuild = new RAMGuild(messageRAMCache, resourceRAMCache, this.id);
|
||
|
this.personalDBGuild = new PersonalDBGuild(personalDB, this.id, this.memberId);
|
||
|
this.socketGuild = new SocketGuild(socket, socketVerifier);
|
||
|
|
||
|
// TODO: Only unverify the personaldb->socket connection on d/c?
|
||
|
|
||
|
this.socketGuild.on('connect', () => {
|
||
|
LOG.info(`g#${this.id} connected`);
|
||
|
this.emit('connect');
|
||
|
});
|
||
|
this.socketGuild.on('disconnect', () => {
|
||
|
LOG.info(`g#${this.id} disconnected`);
|
||
|
this.unverify();
|
||
|
this.emit('disconnect');
|
||
|
});
|
||
|
|
||
|
this.socketGuild.on('update-metadata', (guildMeta: GuildMetadata) => {
|
||
|
LOG.info(`g#${this.id} updated metadata: ${guildMeta}`);
|
||
|
this.emit('update-metadata', guildMeta);
|
||
|
});
|
||
|
|
||
|
let listenForList = <T>(
|
||
|
event: 'new-messages' | 'update-messages' | 'new-members' | 'update-members' | 'new-channels' | 'update-channels',
|
||
|
logFunc: (arg: T) => void,
|
||
|
guildUpdater: (args: T[]) => void
|
||
|
) => {
|
||
|
this.socketGuild.on(event, (args: any[]) => {
|
||
|
for (let arg of args) {
|
||
|
logFunc(arg);
|
||
|
}
|
||
|
guildUpdater(args);
|
||
|
this.emit(event, args);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
listenForList<Member>('new-members',
|
||
|
(member: Member) => LOG.info(`g#${this.id} ${member}`),
|
||
|
(members: Member[]) => {
|
||
|
this.ramGuild.handleMembersAdded(members);
|
||
|
this.personalDBGuild.handleMembersAdded(members);
|
||
|
}
|
||
|
);
|
||
|
listenForList<Member>('update-members',
|
||
|
(member: Member) => LOG.info(`g#${this.id} updated ${member}`),
|
||
|
(members: Member[]) => {
|
||
|
this.ramGuild.handleMembersChanged(members);
|
||
|
this.personalDBGuild.handleMembersChanged(members);
|
||
|
}
|
||
|
);
|
||
|
|
||
|
listenForList<Channel>('new-members',
|
||
|
(channel: Channel) => LOG.info(`g#${this.id} ${channel}`),
|
||
|
(channels: Channel[]) => {
|
||
|
this.ramGuild.handleChannelsAdded(channels);
|
||
|
this.personalDBGuild.handleChannelsAdded(channels);
|
||
|
}
|
||
|
);
|
||
|
listenForList<Channel>('update-members',
|
||
|
(channel: Channel) => LOG.info(`g#${this.id} updated ${channel}`),
|
||
|
(channels: Channel[]) => {
|
||
|
this.ramGuild.handleChannelsChanged(channels);
|
||
|
this.personalDBGuild.handleChannelsChanged(channels);
|
||
|
}
|
||
|
);
|
||
|
|
||
|
listenForList<Message>('new-messages',
|
||
|
(message: Message) => LOG.info(`g#${this.id} ${message}`),
|
||
|
(messages: Message[]) => {
|
||
|
this.ramGuild.handleMessagesAdded(messages);
|
||
|
this.personalDBGuild.handleMessagesAdded(messages);
|
||
|
}
|
||
|
);
|
||
|
listenForList<Message>('update-messages',
|
||
|
(message: Message) => LOG.info(`g#${this.id} updated ${message}`),
|
||
|
(messages: Message[]) => {
|
||
|
this.ramGuild.handleMessagesChanged(messages);
|
||
|
this.personalDBGuild.handleMessagesChanged(messages);
|
||
|
}
|
||
|
);
|
||
|
|
||
|
let personalDBSocketPairVerifier = new GuildPairVerifierGuild(
|
||
|
this.personalDBGuild,
|
||
|
this.socketGuild
|
||
|
);
|
||
|
|
||
|
let ramPersonalDBSocketPairVerifier = new GuildPairVerifierGuild(
|
||
|
this.ramGuild,
|
||
|
personalDBSocketPairVerifier
|
||
|
);
|
||
|
|
||
|
this.pairVerifiers = [ personalDBSocketPairVerifier, ramPersonalDBSocketPairVerifier ];
|
||
|
|
||
|
this.fetchable = ramPersonalDBSocketPairVerifier;
|
||
|
}
|
||
|
|
||
|
static async create(
|
||
|
personalGuildId: number,
|
||
|
socketConfig: SocketConfig,
|
||
|
messageRAMCache: MessageRAMCache,
|
||
|
resourceRAMCache: ResourceRAMCache,
|
||
|
personalDB: PersonalDB
|
||
|
) {
|
||
|
let socket = socketio.connect(socketConfig.url, {
|
||
|
forceNew: true,
|
||
|
ca: socketConfig.cert
|
||
|
});
|
||
|
let socketVerifier = new SocketVerifier(socket, socketConfig.publicKey, socketConfig.privateKey);
|
||
|
let memberId = await socketVerifier.verify();
|
||
|
return new GuildController(
|
||
|
personalGuildId,
|
||
|
memberId,
|
||
|
socket,
|
||
|
socketVerifier,
|
||
|
messageRAMCache,
|
||
|
resourceRAMCache,
|
||
|
personalDB
|
||
|
);
|
||
|
}
|
||
|
|
||
|
private unverify() {
|
||
|
for (let pairVerifier of this.pairVerifiers) {
|
||
|
pairVerifier.unverify();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async ensureRAMMembers() {
|
||
|
if (this.ramGuild.getMembers().size === 0) {
|
||
|
await this.fetchMembers();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async ensureRAMChannels() {
|
||
|
if (this.ramGuild.getChannels().size === 0) {
|
||
|
await this.fetchChannels();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async fetchMetadata(): Promise<GuildMetadata> {
|
||
|
return await this.fetchable.fetchMetadata();
|
||
|
}
|
||
|
async fetchMembers(): Promise<Member[]> {
|
||
|
return await this.fetchable.fetchMembers();
|
||
|
}
|
||
|
async fetchChannels(): Promise<Channel[]> {
|
||
|
return await this.fetchable.fetchChannels();
|
||
|
}
|
||
|
async fetchMessagesRecent(channelId: string, number: number): Promise<Message[]> {
|
||
|
return await this.fetchable.fetchMessagesRecent(channelId, number);
|
||
|
}
|
||
|
async fetchMessagesBefore(channelId: string, messageId: string, number: number): Promise<Message[]> {
|
||
|
return await this.fetchable.fetchMessagesBefore(channelId, messageId, number);
|
||
|
}
|
||
|
async fetchMessagesAfter(channelId: string, messageId: string, number: number): Promise<Message[]> {
|
||
|
return await this.fetchable.fetchMessagesAfter(channelId, messageId, number);
|
||
|
}
|
||
|
async fetchResource(resourceId: string): Promise<Resource> {
|
||
|
return await this.fetchable.fetchResource(resourceId);
|
||
|
}
|
||
|
async fetchTokens(): Promise<Token[]> {
|
||
|
return await this.fetchable.fetchTokens();
|
||
|
}
|
||
|
}
|