cordis/client/webapp/guild-combined.ts

202 lines
6.4 KiB
TypeScript
Raw Normal View History

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();
}
}