import { logger } from '../util/logger.js'; import type { LinkMode, PostAction } from '../types.js'; import type { ConfigStore } from './ConfigStore.js'; export interface TradeLink { id: string; url: string; name: string; label: string; active: boolean; mode: LinkMode; postAction: PostAction; addedAt: string; } export class LinkManager { private links: Map = new Map(); private store: ConfigStore; constructor(store: ConfigStore) { this.store = store; } addLink(url: string, name: string = '', mode?: LinkMode, postAction?: PostAction): TradeLink { url = this.stripLive(url); const id = this.extractId(url); const label = this.extractLabel(url); const savedLink = this.store.links.find((l) => l.url === url); const resolvedMode = mode || savedLink?.mode || 'live'; const link: TradeLink = { id, url, name: name || savedLink?.name || '', label, active: savedLink?.active !== undefined ? savedLink.active : true, mode: resolvedMode, postAction: postAction || savedLink?.postAction || (resolvedMode === 'scrap' ? 'salvage' : 'stash'), addedAt: new Date().toISOString(), }; this.links.set(id, link); this.store.addLink(url, link.name, link.mode, link.postAction); logger.info({ id, url, name: link.name, active: link.active, mode: link.mode, postAction: link.postAction }, 'Trade link added'); return link; } removeLink(id: string): void { const link = this.links.get(id); this.links.delete(id); if (link) { this.store.removeLink(link.url); } else { this.store.removeLinkById(id); } logger.info({ id }, 'Trade link removed'); } toggleLink(id: string, active: boolean): TradeLink | undefined { const link = this.links.get(id); if (!link) return undefined; link.active = active; this.store.updateLinkById(id, { active }); logger.info({ id, active }, `Trade link ${active ? 'activated' : 'deactivated'}`); return link; } updateName(id: string, name: string): void { const link = this.links.get(id); if (!link) return; link.name = name; this.store.updateLinkById(id, { name }); } updateMode(id: string, mode: LinkMode): TradeLink | undefined { const link = this.links.get(id); if (!link) return undefined; link.mode = mode; this.store.updateLinkById(id, { mode }); logger.info({ id, mode }, 'Trade link mode updated'); return link; } updatePostAction(id: string, postAction: PostAction): TradeLink | undefined { const link = this.links.get(id); if (!link) return undefined; link.postAction = postAction; this.store.updateLinkById(id, { postAction }); logger.info({ id, postAction }, 'Trade link postAction updated'); return link; } isActive(id: string): boolean { const link = this.links.get(id); return link ? link.active : false; } getLinks(): TradeLink[] { return Array.from(this.links.values()); } getLink(id: string): TradeLink | undefined { return this.links.get(id); } private stripLive(url: string): string { return url.replace(/\/live\/?$/, ''); } private extractId(url: string): string { const parts = url.split('/'); return parts[parts.length - 1] || url; } private extractLabel(url: string): string { try { const urlObj = new URL(url); const parts = urlObj.pathname.split('/').filter(Boolean); const poe2Idx = parts.indexOf('poe2'); if (poe2Idx >= 0 && parts.length > poe2Idx + 2) { const league = decodeURIComponent(parts[poe2Idx + 1]); const searchId = parts[poe2Idx + 2]; return `${league} / ${searchId}`; } } catch { // fallback } return url.substring(0, 60); } }