thread-master/old/backend/worker/threads-media-id.ts

67 lines
2.3 KiB
TypeScript

/** 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, unknown>): 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, unknown>): 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<T extends PostWithMedia>(posts: T[]): T[] {
const numericByShortcode = new Map<string, string>()
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
}