import { ClusterClient , Command , Interaction } from 'detritus-client' ; import { EventSubscription } from 'detritus-utils' ; import { Store } from './store' ; import { fetchUser , putUser } from '../api' ; import { User } from '../api/structures/user' ; import { RedisChannels } from '../constants' ; import { RedisSpewer } from '../redis' ; import { RedisPayloads } from '../types' ; class UserStore extends Store < string , User > { constructor ( ) { super ( { expire : 2 * 60 * 60 * 1000 } ) ; } insert ( payload ) { this . set ( payload . id , payload ) ; } async getOrFetch ( context , userId ) { let user = null ; if ( UserPromisesStore . has ( userId ) ) { const promise = UserPromisesStore . get ( userId ) as UserPromise ; user = await promise ; } else { if ( this . has ( userId ) ) { user = this . get ( userId ) as User ; } else { user = await this . fetch ( context , userId ) ; } } return user ; } async fetch ( context , userId ) { let promise ; if ( UserPromisesStore . has ( userId ) ) { promise = UserPromisesStore . get ( userId ) as UserPromise ; } else { promise = new Promise ( async ( resolve ) => { const discordUser = context . users . get ( userId ) ; try { let user = null ; if ( discordUser ) { user = await putUser ( context , userId , { avatar : discordUser . avatar , bot : discordUser . bot , discriminator : discordUser . discriminator , username : discordUser . username , } ) ; } else { user = await fetchUser ( context , userId ) ; } this . insert ( user ) ; resolve ( user ) ; } catch ( error ) { resolve ( null ) ; } UserPromisesStore . delete ( userId ) ; } ) ; UserPromisesStore . insert ( userId , promise ) ; } return promise ; } create ( cluster , redis ) { const subscriptions = [ ] ; { const subscription = redis . subscribe ( RedisChannels . USER_UPDATE , ( payload ) => { if ( this . has ( payload . id ) ) { const user = this . get ( payload . id ) ! ; user . merge ( payload ) ; } } ) ; subscriptions . push ( subscription ) ; } return subscriptions ; } } export default new UserStore ( ) ; export type UserPromise = Promise < User | null > ; class UserPromises extends Store < string , UserPromise > { insert ( guildId , promise ) { this . set ( guildId , promise ) ; } } export const UserPromisesStore = new UserPromises ( ) ;