story-research-zapwall/lib/articleSuggestions.ts
2026-01-15 11:31:09 +01:00

84 lines
2.4 KiB
TypeScript

import type { Article } from '@/types/nostr'
/**
* Find similar articles based on category and title keywords
*/
export function findSimilarArticles(currentArticle: Article, allArticles: Article[], limit: number = 3): Article[] {
if (!currentArticle.category) {
return []
}
const currentTitleWords = extractKeywords(currentArticle.title)
const similar = allArticles
.filter((article) => {
if (article.id === currentArticle.id || article.isPresentation) {
return false
}
if (article.category !== currentArticle.category) {
return false
}
const articleTitleWords = extractKeywords(article.title)
return hasCommonKeywords(currentTitleWords, articleTitleWords)
})
.sort((a, b) => {
const aWords = extractKeywords(a.title)
const bWords = extractKeywords(b.title)
const aScore = countCommonKeywords(currentTitleWords, aWords)
const bScore = countCommonKeywords(currentTitleWords, bWords)
return bScore - aScore
})
.slice(0, limit)
return similar
}
/**
* Find articles by the same author
*/
export function findAuthorArticles(currentArticle: Article, allArticles: Article[], limit: number = 3): Article[] {
return allArticles
.filter((article) => {
if (article.id === currentArticle.id || article.isPresentation) {
return false
}
return article.pubkey === currentArticle.pubkey
})
.sort((a, b) => b.createdAt - a.createdAt)
.slice(0, limit)
}
/**
* Find articles in the same category
*/
export function findCategoryArticles(currentArticle: Article, allArticles: Article[], limit: number = 3): Article[] {
if (!currentArticle.category) {
return []
}
return allArticles
.filter((article) => {
if (article.id === currentArticle.id || article.isPresentation) {
return false
}
return article.category === currentArticle.category
})
.sort((a, b) => b.createdAt - a.createdAt)
.slice(0, limit)
}
function extractKeywords(text: string): string[] {
return text
.toLowerCase()
.split(/\s+/)
.filter((word) => word.length > 3)
.filter((word, index, array) => array.indexOf(word) === index)
}
function hasCommonKeywords(words1: string[], words2: string[]): boolean {
return words1.some((word) => words2.includes(word))
}
function countCommonKeywords(words1: string[], words2: string[]): number {
return words1.filter((word) => words2.includes(word)).length
}