203 lines
9.8 KiB
TypeScript
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();
|
|
}
|
|
}
|