Persist comment source monitoring

This commit is contained in:
jjbrunton committed 2026-08-14 13:40:55 +01:00
1 parent 5e1fc5def9
commit 8d932fcf36
16 files changed
+376 -24

No files matched your search

+57
View File
@@ -9,6 +9,9 @@ import {
import type { PostsRepository, MessagesRepository } from '../src/database/repositories.js';
import { createMockLogger } from '../tests/mockLogger.js';
import { getTestConfig } from '../tests/testUtils.js';
import Database from 'better-sqlite3';
import { runMigrations } from '../src/database/client.js';
import { CommentSourceWatchRepository } from '../src/database/comment-source-watch-repository.js';
function createMockRedditApi(posts: RedditPost[] = []): RedditApiClient {
return {
@@ -677,6 +680,60 @@ describe('MonitorService', () => {
});
describe('comment-author targeting', () => {
it('keeps watching a durable source and classifies only new comments newest-first', async () => {
const db = new Database(':memory:');
runMigrations(db);
try {
const source: RedditPost = {
id: 'post1', name: 't3_post1', subreddit: 'scene', author: 'poster', title: 'A scene',
url: 'https://example.com/scene.jpg', permalink: '/r/scene/comments/post1/', thumbnail: '',
is_self: false, created_utc: Date.now() / 1_000, over_18: true, spoiler: false,
};
const first = {
fullname: 't1_first', kind: 'comment' as const, subreddit: 'scene', author: 'first',
permalink: '/first', createdAt: Date.now(), score: 1, text: 'As a woman I would love that done to me',
nsfw: true, parentPostId: 'post1', distinguished: null, removed: false,
};
const second = { ...first, fullname: 't1_second', author: 'second', permalink: '/second' };
const redditApi = createMockRedditApi([source]);
redditApi.getNewPosts = vi.fn()
.mockResolvedValueOnce([source])
.mockResolvedValueOnce([]);
redditApi.getBrowsingComments = vi.fn()
.mockResolvedValueOnce([first])
.mockResolvedValueOnce([second, first]);
const screener = { screenCommentReactions: vi.fn(async (comments) => comments.map((item) => ({
id: item.id, qualifies: true, expressedGender: 'female' as const, confidence: 0.95, evidence: 'recipient role',
}))) };
const config = getTestConfig({ reddit: {
subreddits: [{ name: 'scene', type: 'image', targetingMode: 'comment-author' }],
targetGenders: ['female'], recentWindowMinutes: 600,
} });
monitor = new MonitorService(
redditApi, createMockPostsRepo(), createMockMessagesRepo(), config, logger, 0, undefined, screener,
new CommentSourceWatchRepository(db),
);
await expect(monitor.fetchCandidates(config.reddit.subreddits[0]))
.resolves.toEqual([expect.objectContaining({ id: 't1_first' })]);
await expect(monitor.fetchCandidates(config.reddit.subreddits[0]))
.resolves.toEqual(expect.arrayContaining([
expect.objectContaining({ id: 't1_first' }),
expect.objectContaining({ id: 't1_second' }),
]));
expect(screener.screenCommentReactions).toHaveBeenNthCalledWith(1, [
{ id: 't1_first', text: first.text },
]);
expect(screener.screenCommentReactions).toHaveBeenNthCalledWith(2, [
{ id: 't1_second', text: second.text },
]);
expect(redditApi.getNewPosts).toHaveBeenCalledWith('scene', 100, 'image');
expect(redditApi.getBrowsingComments).toHaveBeenCalledWith('scene', 'post1', 100, 'new');
} finally {
db.close();
}
});
it('turns a high-confidence targeted reaction into a commenter candidate with source media intact', async () => {
const source: RedditPost = {
id: 'post1', name: 't3_post1', subreddit: 'scene', author: 'poster', title: 'A scene',