Add recent outreach rejections stream
This commit is contained in:
1 parent
0c21202253
commit
94049ed9c4
9 files changed
+170
-16
No files matched your search
@@ -480,6 +480,21 @@ export class CandidateQueueRepository {
|
||||
return rows.map((row) => this.mapRow(row));
|
||||
}
|
||||
|
||||
/** Most recently completed screening rejections for the operator audit stream. */
|
||||
listRecentRejected(limit = 50): CandidateQueueRecord[] {
|
||||
if (!Number.isInteger(limit) || limit < 1 || limit > 50) {
|
||||
throw new Error('Rejected candidate limit must be an integer between 1 and 50');
|
||||
}
|
||||
const rows = this.db.prepare(`
|
||||
SELECT * FROM candidate_queue
|
||||
WHERE status = 'rejected'
|
||||
AND COALESCE(last_error, '') NOT IN ('Cleared manually by operator', 'Removed manually by operator')
|
||||
ORDER BY updated_at DESC, post_created_at DESC
|
||||
LIMIT ?
|
||||
`).all(limit) as Array<Record<string, unknown>>;
|
||||
return rows.map((row) => this.mapRow(row));
|
||||
}
|
||||
|
||||
private claim(
|
||||
from: 'discovered' | 'ready',
|
||||
to: 'screening' | 'sending',
|
||||
|
||||
@@ -45,6 +45,18 @@ interface OutreachCandidateView {
|
||||
owner: { accountId: string; redditUsername: string } | null;
|
||||
}
|
||||
|
||||
interface OutreachRejectedCandidateView {
|
||||
postId: string;
|
||||
subreddit: string;
|
||||
author: string;
|
||||
title: string;
|
||||
postUrl: string;
|
||||
sourceType: 'image' | 'chat';
|
||||
sourceContent: string | null;
|
||||
rejectedAt: number;
|
||||
reason: string;
|
||||
}
|
||||
|
||||
function redditPostUrl(permalink: string): string {
|
||||
try {
|
||||
return new URL(permalink, 'https://www.reddit.com').toString();
|
||||
@@ -65,6 +77,7 @@ export function createOutreachRouter(ctx: WebContext): Router {
|
||||
|
||||
const stats = queue.getStats();
|
||||
const records = queue.listActive();
|
||||
const rejectedRecords = queue.listRecentRejected();
|
||||
const accountById = new Map((ctx.services.redditAccounts?.list() ?? [])
|
||||
.map((account) => [account.accountId, account.redditUsername] as const));
|
||||
const candidates: OutreachCandidateView[] = records.map((candidate) => ({
|
||||
@@ -116,6 +129,17 @@ export function createOutreachRouter(ctx: WebContext): Router {
|
||||
}
|
||||
: null,
|
||||
}));
|
||||
const recentRejections: OutreachRejectedCandidateView[] = rejectedRecords.map((candidate) => ({
|
||||
postId: candidate.postId,
|
||||
subreddit: candidate.subreddit,
|
||||
author: candidate.author,
|
||||
title: candidate.post.title,
|
||||
postUrl: redditPostUrl(candidate.post.permalink),
|
||||
sourceType: candidate.sourceType,
|
||||
sourceContent: candidate.post.targetComment?.body ?? (candidate.post.selftext?.trim() || null),
|
||||
rejectedAt: candidate.updatedAt,
|
||||
reason: candidate.lastError ?? 'Unknown',
|
||||
}));
|
||||
const stages = {
|
||||
discovered: stats.byStatus.discovered,
|
||||
screening: stats.byStatus.screening,
|
||||
@@ -129,6 +153,7 @@ export function createOutreachRouter(ctx: WebContext): Router {
|
||||
stages,
|
||||
outcomes: { sent: stats.byStatus.sent, rejected: stats.byStatus.rejected },
|
||||
rejectionReasons: stats.rejectionReasons,
|
||||
recentRejections,
|
||||
oldestActiveAt: queue.getOldestActiveAt(),
|
||||
candidates,
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user