diff --git a/__tests__/workers/postUpdated.ts b/__tests__/workers/postUpdated.ts index 2773e336bd..41acfee63b 100644 --- a/__tests__/workers/postUpdated.ts +++ b/__tests__/workers/postUpdated.ts @@ -558,6 +558,30 @@ it('save a post as private if source is private', async () => { expect(posts[3].flags.private).toBe(true); }); +it('should save a new post with recommendation and quality signals', async () => { + await expectSuccessfulBackground(worker, { + id: 'f99a445f-e2fb-48e8-959c-e02a17f5e816', + title: 'Title', + url: 'https://post.com', + source_id: 'a', + extra: { + specificity: 'high', + intent: 'tutorial', + substance_depth: 'deep', + title_content_alignment: 'aligned', + self_promotion_score: 0.25, + }, + }); + const posts = await con.getRepository(Post).find(); + expect(posts.length).toEqual(4); + const post = posts[3]; + expect(post.flags.specificity).toEqual('high'); + expect(post.flags.intent).toEqual('tutorial'); + expect(post.flags.substanceDepth).toEqual('deep'); + expect(post.flags.titleContentAlignment).toEqual('aligned'); + expect(post.flags.selfPromotionScore).toEqual(0.25); +}); + it('do not save post if source can not be found', async () => { await expectSuccessfulBackground(worker, { id: 'f99a445f-e2fb-48e8-959c-e02a17f5e816', @@ -1325,6 +1349,37 @@ describe('on post update', () => { }); }); + it('should update post with recommendation and quality signals', async () => { + const postId = 'p1'; + + await con.getRepository(ArticlePost).save({ + id: postId, + yggdrasilId: 'f99a445f-e2fb-48e8-959c-e02a17f5e816', + }); + + await expectSuccessfulBackground(worker, { + id: 'f99a445f-e2fb-48e8-959c-e02a17f5e816', + post_id: postId, + extra: { + specificity: 'medium', + intent: 'reference', + substance_depth: 'surface', + title_content_alignment: 'misaligned', + self_promotion_score: 0.75, + }, + }); + + const updatedPost = await con.getRepository(ArticlePost).findOneBy({ + id: postId, + }); + + expect(updatedPost?.flags.specificity).toEqual('medium'); + expect(updatedPost?.flags.intent).toEqual('reference'); + expect(updatedPost?.flags.substanceDepth).toEqual('surface'); + expect(updatedPost?.flags.titleContentAlignment).toEqual('misaligned'); + expect(updatedPost?.flags.selfPromotionScore).toEqual(0.75); + }); + describe('vordr', () => { it('should vordr post based on title', async () => { const uuid = randomUUID(); diff --git a/src/entity/posts/Post.ts b/src/entity/posts/Post.ts index 466aa9a1dd..aa4d6306e5 100644 --- a/src/entity/posts/Post.ts +++ b/src/entity/posts/Post.ts @@ -53,6 +53,13 @@ export type PostFlags = Partial<{ savedTime: number; generatedAt: Date; dedupKey: string; + // Recommendation signals + specificity: string; + intent: string; + // Quality signals + substanceDepth: string; + titleContentAlignment: string; + selfPromotionScore: number; }>; export type PostFlagsPublic = Pick< diff --git a/src/workers/postUpdated.ts b/src/workers/postUpdated.ts index e7e362696b..079b56f810 100644 --- a/src/workers/postUpdated.ts +++ b/src/workers/postUpdated.ts @@ -81,6 +81,11 @@ interface Data { content: string; video_id?: string; duration?: number; + specificity?: string; + intent?: string; + substance_depth?: string; + title_content_alignment?: string; + self_promotion_score?: number; }; meta?: { scraped_html?: string; @@ -607,6 +612,11 @@ const fixData = async ({ private: privacy, showOnFeed: !data?.order, sentAnalyticsReport: privacy || !authorId, + specificity: data?.extra?.specificity, + intent: data?.extra?.intent, + substanceDepth: data?.extra?.substance_depth, + titleContentAlignment: data?.extra?.title_content_alignment, + selfPromotionScore: data?.extra?.self_promotion_score, }, yggdrasilId: data?.id, type: data?.content_type as PostType,