cordis/client/webapp/fetchable-pair-verifier.ts
2021-12-04 07:54:43 -06:00

203 lines
9.8 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 { Changes, Channel, GuildMetadata, Member, Message, Resource, Token } from './data-types';
import { AsyncFetchable, Fetchable, Lackable, Conflictable } from './guild-types';
import { AutoVerifier, AutoVerifierChangesType } from './auto-verifier';
import { AutoVerifierWithArg, PartialMessageListQuery, IDQuery } from './auto-verifier-with-args';
import { EventEmitter } from 'tsee';
export default class PairVerifierFetchable extends EventEmitter<Conflictable> implements AsyncFetchable {
private readonly fetchMetadataVerifier: AutoVerifier<GuildMetadata>;
private readonly fetchMembersVerifier: AutoVerifier<Member[]>;
private readonly fetchChannelsVerifier: AutoVerifier<Channel[]>;
private readonly fetchTokensVerifier: AutoVerifier<Token[]>;
private readonly fetchResourceVerifier: AutoVerifierWithArg<Resource, IDQuery>
private readonly fetchMessagesRecentVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>;
private readonly fetchMessagesBeforeVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>;
private readonly fetchMessagesAfterVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>;
constructor(
private primary: Fetchable & Lackable,
private trusted: Fetchable
) {
super();
if (trusted instanceof PairVerifierFetchable) {
// handle trusted conflicts
trusted.on('conflict-metadata', this.handleMetadataConflict.bind(this));
trusted.on('conflict-members', this.handleMembersConflict.bind(this) );
trusted.on('conflict-channels', this.handleChannelsConflict.bind(this));
trusted.on('conflict-tokens', this.handleTokensConflict.bind(this) );
trusted.on('conflict-resource', this.handleResourceConflict.bind(this));
trusted.on('conflict-messages', this.handleMessagesConflict.bind(this));
}
this.fetchMetadataVerifier = AutoVerifier.createStandardSingleAutoVerifier<GuildMetadata>(
async () => await this.primary.fetchMetadata(),
async () => await this.trusted.fetchMetadata(),
this.handleMetadataConflict.bind(this)
);
this.fetchMembersVerifier = AutoVerifier.createStandardListAutoVerifier<Member>(
async () => await this.primary.fetchMembers(),
async () => await this.trusted.fetchMembers(),
this.handleMembersConflict.bind(this)
);
this.fetchChannelsVerifier = AutoVerifier.createStandardListAutoVerifier<Channel>(
async () => await this.primary.fetchChannels(),
async () => await this.trusted.fetchChannels(),
this.handleChannelsConflict.bind(this)
);
this.fetchTokensVerifier = AutoVerifier.createStandardListAutoVerifier<Token>(
async () => await this.primary.fetchTokens(),
async () => await this.trusted.fetchTokens(),
this.handleTokensConflict.bind(this)
);
this.fetchResourceVerifier = AutoVerifierWithArg.createStandardIDQueriedSingleAutoVerifier<Resource>(
async (query: IDQuery) => await this.primary.fetchResource(query.id),
async (query: IDQuery) => await this.trusted.fetchResource(query.id),
this.handleResourceConflict.bind(this)
);
this.fetchMessagesRecentVerifier = AutoVerifierWithArg.createStandardPartialMessageListAutoVerifier(
async (query: PartialMessageListQuery) => await this.primary.fetchMessagesRecent(query.channelId, query.number),
async (query: PartialMessageListQuery) => await this.trusted.fetchMessagesRecent(query.channelId, query.number),
this.handleMessagesConflict.bind(this)
);
this.fetchMessagesBeforeVerifier = AutoVerifierWithArg.createStandardPartialMessageListAutoVerifier(
async (query: PartialMessageListQuery) => await this.primary.fetchMessagesBefore(query.channelId, query.messageId as string, query.number),
async (query: PartialMessageListQuery) => await this.trusted.fetchMessagesBefore(query.channelId, query.messageId as string, query.number),
this.handleMessagesConflict.bind(this)
);
this.fetchMessagesAfterVerifier = AutoVerifierWithArg.createStandardPartialMessageListAutoVerifier(
async (query: PartialMessageListQuery) => await this.primary.fetchMessagesAfter(query.channelId, query.messageId as string, query.number),
async (query: PartialMessageListQuery) => await this.trusted.fetchMessagesAfter(query.channelId, query.messageId as string, query.number),
this.handleMessagesConflict.bind(this)
);
}
canFetch() {
return true;
}
async handleMetadataConflict(changesType: AutoVerifierChangesType, primaryMetadata: GuildMetadata | null, trustedMetadata: GuildMetadata | null): Promise<void> {
// LOG.debug('metadata conflict', {
// primaryClass: this.primary.constructor.name,
// trustedClass: this.trusted.constructor.name,
// changesType: AutoVerifierChangesType[changesType],
// primaryMetadata: primaryMetadata,
// trustedMetadata: trustedMetadata,
// });
if (changesType === AutoVerifierChangesType.TRUSTED_ONLY) {
await this.primary.handleMetadataChanged(trustedMetadata as GuildMetadata);
} else if (changesType === AutoVerifierChangesType.CONFLICT) {
await this.primary.handleMetadataChanged(trustedMetadata as GuildMetadata);
this.emit('conflict-metadata', changesType, primaryMetadata as GuildMetadata, trustedMetadata as GuildMetadata);
}
}
async handleMembersConflict(changesType: AutoVerifierChangesType, changes: Changes<Member>): Promise<void>{
if (changes.added.length > 0) await this.primary.handleMembersAdded(changes.added);
if (changes.updated.length > 0) await this.primary.handleMembersChanged(changes.updated.map(change => change.newDataPoint));
if (changes.deleted.length > 0) await this.primary.handleMembersDeleted(changes.deleted);
if (changesType === AutoVerifierChangesType.CONFLICT) {
this.emit('conflict-members', changesType, changes);
}
}
async handleChannelsConflict(changesType: AutoVerifierChangesType, changes: Changes<Channel>): Promise<void> {
if (changes.added.length > 0) await this.primary.handleChannelsAdded(changes.added);
if (changes.updated.length > 0) await this.primary.handleChannelsChanged(changes.updated.map(change => change.newDataPoint));
if (changes.deleted.length > 0) await this.primary.handleChannelsDeleted(changes.deleted);
if (changesType === AutoVerifierChangesType.CONFLICT) {
this.emit('conflict-channels', changesType, changes);
}
}
async handleTokensConflict(changesType: AutoVerifierChangesType, changes: Changes<Token>): Promise<void> {
if (changes.added.length > 0) await this.primary.handleTokensAdded(changes.added);
if (changes.updated.length > 0) await this.primary.handleTokensChanged(changes.updated.map(change => change.newDataPoint));
if (changes.deleted.length > 0) await this.primary.handleTokensDeleted(changes.deleted);
if (changesType === AutoVerifierChangesType.CONFLICT) {
this.emit('conflict-tokens', changesType, changes);
}
}
async handleResourceConflict(query: IDQuery, changesType: AutoVerifierChangesType, primaryResource: Resource | null, trustedResource: Resource | null): Promise<void> {
if (changesType === AutoVerifierChangesType.PRIMARY_ONLY) {
await this.primary.handleResourceDeleted(trustedResource as Resource);
} else if (changesType === AutoVerifierChangesType.TRUSTED_ONLY) {
await this.primary.handleResourceAdded(trustedResource as Resource);
} else if (changesType === AutoVerifierChangesType.CONFLICT) {
await this.primary.handleResourceChanged(trustedResource as Resource);
this.emit('conflict-resource', changesType, query, primaryResource as Resource, trustedResource as Resource);
}
}
async handleMessagesConflict(query: PartialMessageListQuery, changesType: AutoVerifierChangesType, changes: Changes<Message>): Promise<void> {
if (changes.added.length > 0) await this.primary.handleMessagesAdded(changes.added);
if (changes.updated.length > 0) await this.primary.handleMessagesChanged(changes.updated.map(change => change.newDataPoint));
if (changes.deleted.length > 0) await this.primary.handleMessagesDeleted(changes.deleted);
if (changesType === AutoVerifierChangesType.CONFLICT) {
this.emit('conflict-messages', changesType, query, changes);
}
}
unverify() {
this.fetchMetadataVerifier.unverify();
this.fetchMembersVerifier.unverify();
this.fetchChannelsVerifier.unverify();
this.fetchTokensVerifier.unverify();
this.fetchResourceVerifier.unverifyAll();
this.fetchMessagesRecentVerifier.unverifyAll();
this.fetchMessagesBeforeVerifier.unverifyAll();
this.fetchMessagesAfterVerifier.unverifyAll();
if (this.trusted instanceof PairVerifierFetchable) {
this.trusted.unverify();
}
}
async fetchMetadata(): Promise<GuildMetadata | null> {
return await this.fetchMetadataVerifier.fetchAndVerifyIfNeeded();
}
async fetchMembers(): Promise<Member[] | null> {
return await this.fetchMembersVerifier.fetchAndVerifyIfNeeded();
}
async fetchChannels(): Promise<Channel[] | null> {
return await this.fetchChannelsVerifier.fetchAndVerifyIfNeeded();
}
async fetchMessagesRecent(channelId: string, number: number): Promise<Message[] | null> {
return await this.fetchMessagesRecentVerifier.fetchAndVerifyIfNeded({ channelId, messageId: null, number });
}
async fetchMessagesBefore(channelId: string, messageId: string, number: number): Promise<Message[] | null> {
return await this.fetchMessagesBeforeVerifier.fetchAndVerifyIfNeded({ channelId, messageId, number });
}
async fetchMessagesAfter(channelId: string, messageId: string, number: number): Promise<Message[] | null> {
return await this.fetchMessagesAfterVerifier.fetchAndVerifyIfNeded({ channelId, messageId, number });
}
async fetchResource(resourceId: string): Promise<Resource | null> {
return await this.fetchResourceVerifier.fetchAndVerifyIfNeded({ id: resourceId }, true); // lazy verification
}
async fetchTokens(): Promise<Token[] | null> {
return await this.fetchTokensVerifier.fetchAndVerifyIfNeeded();
}
}