Initial
This commit is contained in:
commit
c552956516
23 files changed
+5193
No files matched your search
@@ -0,0 +1,267 @@
|
||||
import type Database from 'better-sqlite3';
|
||||
|
||||
export interface ProcessedPostRecord {
|
||||
id: string;
|
||||
subreddit: string;
|
||||
author: string;
|
||||
title: string;
|
||||
imageUrl: string | null;
|
||||
imageAnalysis: string | null;
|
||||
generatedMessage: string | null;
|
||||
processedAt: number;
|
||||
messageSent: boolean;
|
||||
error: string | null;
|
||||
}
|
||||
|
||||
export interface SentMessageRecord {
|
||||
id: number;
|
||||
postId: string;
|
||||
recipient: string;
|
||||
subject: string;
|
||||
message: string;
|
||||
sentAt: number;
|
||||
gotResponse: boolean;
|
||||
responseCheckedAt: number | null;
|
||||
}
|
||||
|
||||
export interface SuccessfulMessageRecord {
|
||||
id: number;
|
||||
sentMessageId: number;
|
||||
originalMessage: string;
|
||||
imageAnalysis: string | null;
|
||||
postTitle: string | null;
|
||||
responseSnippet: string | null;
|
||||
createdAt: number;
|
||||
}
|
||||
|
||||
export class PostsRepository {
|
||||
private insertStmt: Database.Statement;
|
||||
private existsStmt: Database.Statement;
|
||||
private markSentStmt: Database.Statement;
|
||||
private updateAnalysisStmt: Database.Statement;
|
||||
private setErrorStmt: Database.Statement;
|
||||
private getByIdStmt: Database.Statement;
|
||||
|
||||
constructor(private db: Database.Database) {
|
||||
this.insertStmt = db.prepare(`
|
||||
INSERT INTO processed_posts (id, subreddit, author, title, image_url, processed_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
`);
|
||||
|
||||
this.existsStmt = db.prepare(`SELECT 1 FROM processed_posts WHERE id = ?`);
|
||||
|
||||
this.markSentStmt = db.prepare(`UPDATE processed_posts SET message_sent = 1 WHERE id = ?`);
|
||||
|
||||
this.updateAnalysisStmt = db.prepare(`
|
||||
UPDATE processed_posts
|
||||
SET image_analysis = ?, generated_message = ?
|
||||
WHERE id = ?
|
||||
`);
|
||||
|
||||
this.setErrorStmt = db.prepare(`UPDATE processed_posts SET error = ? WHERE id = ?`);
|
||||
|
||||
this.getByIdStmt = db.prepare(`SELECT * FROM processed_posts WHERE id = ?`);
|
||||
}
|
||||
|
||||
isProcessed(postId: string): boolean {
|
||||
return this.existsStmt.get(postId) !== undefined;
|
||||
}
|
||||
|
||||
insert(post: {
|
||||
id: string;
|
||||
subreddit: string;
|
||||
author: string;
|
||||
title: string;
|
||||
imageUrl: string | null;
|
||||
processedAt: number;
|
||||
}): void {
|
||||
this.insertStmt.run(
|
||||
post.id,
|
||||
post.subreddit,
|
||||
post.author,
|
||||
post.title,
|
||||
post.imageUrl,
|
||||
post.processedAt
|
||||
);
|
||||
}
|
||||
|
||||
updateAnalysis(postId: string, analysis: string, message: string): void {
|
||||
this.updateAnalysisStmt.run(analysis, message, postId);
|
||||
}
|
||||
|
||||
markMessageSent(postId: string): void {
|
||||
this.markSentStmt.run(postId);
|
||||
}
|
||||
|
||||
setError(postId: string, error: string): void {
|
||||
this.setErrorStmt.run(error, postId);
|
||||
}
|
||||
|
||||
getById(postId: string): ProcessedPostRecord | undefined {
|
||||
const row = this.getByIdStmt.get(postId) as Record<string, unknown> | undefined;
|
||||
if (!row) return undefined;
|
||||
|
||||
return {
|
||||
id: row.id as string,
|
||||
subreddit: row.subreddit as string,
|
||||
author: row.author as string,
|
||||
title: row.title as string,
|
||||
imageUrl: row.image_url as string | null,
|
||||
imageAnalysis: row.image_analysis as string | null,
|
||||
generatedMessage: row.generated_message as string | null,
|
||||
processedAt: row.processed_at as number,
|
||||
messageSent: Boolean(row.message_sent),
|
||||
error: row.error as string | null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class MessagesRepository {
|
||||
private insertStmt: Database.Statement;
|
||||
private getByPostIdStmt: Database.Statement;
|
||||
private getRecentStmt: Database.Statement;
|
||||
private getUncheckedStmt: Database.Statement;
|
||||
private markResponseStmt: Database.Statement;
|
||||
private markCheckedStmt: Database.Statement;
|
||||
|
||||
constructor(private db: Database.Database) {
|
||||
this.insertStmt = db.prepare(`
|
||||
INSERT INTO sent_messages (post_id, recipient, subject, message, sent_at)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
`);
|
||||
|
||||
this.getByPostIdStmt = db.prepare(`SELECT * FROM sent_messages WHERE post_id = ?`);
|
||||
|
||||
this.getRecentStmt = db.prepare(`
|
||||
SELECT * FROM sent_messages ORDER BY sent_at DESC LIMIT ?
|
||||
`);
|
||||
|
||||
this.getUncheckedStmt = db.prepare(`
|
||||
SELECT * FROM sent_messages
|
||||
WHERE got_response = 0
|
||||
AND (response_checked_at IS NULL OR response_checked_at < ?)
|
||||
AND sent_at < ?
|
||||
ORDER BY sent_at ASC
|
||||
LIMIT ?
|
||||
`);
|
||||
|
||||
this.markResponseStmt = db.prepare(`
|
||||
UPDATE sent_messages SET got_response = 1, response_checked_at = ? WHERE id = ?
|
||||
`);
|
||||
|
||||
this.markCheckedStmt = db.prepare(`
|
||||
UPDATE sent_messages SET response_checked_at = ? WHERE id = ?
|
||||
`);
|
||||
}
|
||||
|
||||
insert(message: {
|
||||
postId: string;
|
||||
recipient: string;
|
||||
subject: string;
|
||||
message: string;
|
||||
sentAt: number;
|
||||
}): number {
|
||||
const result = this.insertStmt.run(
|
||||
message.postId,
|
||||
message.recipient,
|
||||
message.subject,
|
||||
message.message,
|
||||
message.sentAt
|
||||
);
|
||||
return result.lastInsertRowid as number;
|
||||
}
|
||||
|
||||
getByPostId(postId: string): SentMessageRecord | undefined {
|
||||
const row = this.getByPostIdStmt.get(postId) as Record<string, unknown> | undefined;
|
||||
if (!row) return undefined;
|
||||
return this.mapRow(row);
|
||||
}
|
||||
|
||||
getRecent(limit: number = 10): SentMessageRecord[] {
|
||||
const rows = this.getRecentStmt.all(limit) as Record<string, unknown>[];
|
||||
return rows.map((row) => this.mapRow(row));
|
||||
}
|
||||
|
||||
getUncheckedMessages(minAgeMs: number, recheckAfterMs: number, limit: number = 10): SentMessageRecord[] {
|
||||
const now = Date.now();
|
||||
const minSentAt = now - minAgeMs;
|
||||
const recheckBefore = now - recheckAfterMs;
|
||||
const rows = this.getUncheckedStmt.all(recheckBefore, minSentAt, limit) as Record<string, unknown>[];
|
||||
return rows.map((row) => this.mapRow(row));
|
||||
}
|
||||
|
||||
markGotResponse(messageId: number): void {
|
||||
this.markResponseStmt.run(Date.now(), messageId);
|
||||
}
|
||||
|
||||
markChecked(messageId: number): void {
|
||||
this.markCheckedStmt.run(Date.now(), messageId);
|
||||
}
|
||||
|
||||
private mapRow(row: Record<string, unknown>): SentMessageRecord {
|
||||
return {
|
||||
id: row.id as number,
|
||||
postId: row.post_id as string,
|
||||
recipient: row.recipient as string,
|
||||
subject: row.subject as string,
|
||||
message: row.message as string,
|
||||
sentAt: row.sent_at as number,
|
||||
gotResponse: Boolean(row.got_response),
|
||||
responseCheckedAt: row.response_checked_at as number | null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class SuccessfulMessagesRepository {
|
||||
private insertStmt: Database.Statement;
|
||||
private getRecentStmt: Database.Statement;
|
||||
private countStmt: Database.Statement;
|
||||
|
||||
constructor(private db: Database.Database) {
|
||||
this.insertStmt = db.prepare(`
|
||||
INSERT INTO successful_messages (sent_message_id, original_message, image_analysis, post_title, response_snippet, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
`);
|
||||
|
||||
this.getRecentStmt = db.prepare(`
|
||||
SELECT * FROM successful_messages ORDER BY created_at DESC LIMIT ?
|
||||
`);
|
||||
|
||||
this.countStmt = db.prepare(`SELECT COUNT(*) as count FROM successful_messages`);
|
||||
}
|
||||
|
||||
insert(data: {
|
||||
sentMessageId: number;
|
||||
originalMessage: string;
|
||||
imageAnalysis: string | null;
|
||||
postTitle: string | null;
|
||||
responseSnippet: string | null;
|
||||
}): void {
|
||||
this.insertStmt.run(
|
||||
data.sentMessageId,
|
||||
data.originalMessage,
|
||||
data.imageAnalysis,
|
||||
data.postTitle,
|
||||
data.responseSnippet,
|
||||
Date.now()
|
||||
);
|
||||
}
|
||||
|
||||
getRecent(limit: number = 5): SuccessfulMessageRecord[] {
|
||||
const rows = this.getRecentStmt.all(limit) as Record<string, unknown>[];
|
||||
return rows.map((row) => ({
|
||||
id: row.id as number,
|
||||
sentMessageId: row.sent_message_id as number,
|
||||
originalMessage: row.original_message as string,
|
||||
imageAnalysis: row.image_analysis as string | null,
|
||||
postTitle: row.post_title as string | null,
|
||||
responseSnippet: row.response_snippet as string | null,
|
||||
createdAt: row.created_at as number,
|
||||
}));
|
||||
}
|
||||
|
||||
count(): number {
|
||||
const result = this.countStmt.get() as { count: number };
|
||||
return result.count;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user