import { EventEmitter } from 'node:events'; import { setTimeout } from 'timers/promises'; import type Log from 'bunyan'; import type { Want } from '@prisma/client'; import { Pg } from './pg'; import { wantDetails } from './utils'; import routerAuth from './routers/router.auth'; export enum Events { WantsAdded = 'WantsAdded', StartupSync = 'StartupSync', ListingsUpdated = 'ListingsUpdated', } export default function createEvents(log: Log, pg: Pg, discogs, offers) { const events = new EventEmitter({ captureRejections: true }); events.on('error', function eventError(e) { log.error('event error', e); }); events.on(Events.WantsAdded, async function wantsAdded(wants: Want[]) { log.info({ event: Events.WantsAdded, wants: wants.length }); for (const want of wants) { const listings = await discogs.listings(want); log.info({ count: listings.length, ...wantDetails(want) }, 'listings added') } log.info('finished fetching listings', { wants: wants.length }); }); events.on(Events.StartupSync, async function wantsAdded() { const wants = await pg.wantsToSync(); log.info({ event: Events.StartupSync, wants: wants.length }); for (const want of wants) { try { const listings = await discogs.listings(want); log.info({ count: listings.length, ...wantDetails(want) }, 'listings added') } catch (e) { if (e.message === 'rate limited') { log.warn('rate limited, trying again in 60s'); await setTimeout(60 * 1000); const listings = await discogs.listings(want); } } } log.info('finished syncing', { wants: wants.length }); }); events.on(Events.ListingsUpdated, async function listingsUpdated() { const bundles = await offers.bundles(); log.info({ event: Events.ListingsUpdated, bundles: bundles.length }); // const bundle = { // username: b[0]?.data.seller.username, // seller: b[0]?.data.seller.id, // shipsFrom: b[0]?.data.ships_from, // total, // currency: b[0]?.data.price.currency, // shipping: '...', // items, // mentionsAustralia: shipping.toLowerCase().includes('australia'), // mentionsWorldwide: shipping.toLowerCase().includes('world'), // } for (const bundle of bundles) { log.info({ seller: bundle.seller, items: bundle.items.length }, 'generating offers...'); const listingIds = bundle.items.map(i => i.id); const updatedOffers = await offers.generate(listingIds, 100, 30) log.info({ offers: updatedOffers.length }, 'offers set'); } log.info('offers up to date'); }); return events; }