/** Threads Graph API reply_to_id must be a numeric media id (pk), not a URL shortcode. */ export function isNumericMediaId(raw?: string | null): boolean { const value = (raw || '').trim() if (value.length < 8) return false return /^\d+$/.test(value) } export function shortcodeFromPermalink(permalink?: string | null): string { const link = (permalink || '').trim().split('?')[0].split('#')[0] const match = link.match(/threads\.(?:com|net)\/@[^/]+\/post\/([^/?#]+)/i) return match?.[1]?.trim() || '' } export function mediaIdFromThreadObject(obj: Record): string | undefined { if (obj.pk != null) { const pk = String(obj.pk).trim() if (isNumericMediaId(pk)) return pk } if (obj.id != null) { const id = String(obj.id).trim() if (isNumericMediaId(id)) return id } return undefined } export function postShortcode(obj: Record): string | undefined { const code = typeof obj.code === 'string' ? obj.code.trim() : '' return code || undefined } type PostWithMedia = { externalId?: string permalink?: string } /** Upgrade shortcode-only crawler rows when JSON/network capture found numeric pk for same post. */ export function enrichPostsWithMediaIds(posts: T[]): T[] { const numericByShortcode = new Map() for (const post of posts) { const externalId = (post.externalId || '').trim() const shortcode = shortcodeFromPermalink(post.permalink) || (!isNumericMediaId(externalId) ? externalId : '') if (shortcode && isNumericMediaId(externalId)) { numericByShortcode.set(shortcode.toLowerCase(), externalId) } } return posts.map((post) => { const externalId = (post.externalId || '').trim() if (isNumericMediaId(externalId)) return post const shortcode = shortcodeFromPermalink(post.permalink) || externalId if (!shortcode) return post const numeric = numericByShortcode.get(shortcode.toLowerCase()) if (!numeric) return post return { ...post, externalId: numeric } }) } export function preferReplyExternalId(existing?: string, incoming?: string): string { const a = (existing || '').trim() const b = (incoming || '').trim() if (isNumericMediaId(a)) return a if (isNumericMediaId(b)) return b if (b) return b return a }