Improve messaging and dashboard reliability
This commit is contained in:
1 parent
345ec99348
commit
5a5a30a1d4
20 files changed
+406
-56
No files matched your search
@@ -9,6 +9,7 @@ import {
|
||||
DeliveryOutboxRepository, ConversationStateRepository,
|
||||
ConversationOutcomesRepository, RedditUsersRepository,
|
||||
ActivityLogRepository,
|
||||
RecipientHistoryRepository,
|
||||
} from '../database/repositories.js';
|
||||
import { AccountContentRepository } from '../database/account-repositories.js';
|
||||
import { RedditApiClient } from '../reddit/api.js';
|
||||
@@ -36,6 +37,7 @@ import {
|
||||
accountBrowserProfileDir, type RedditAccountRuntimeResources,
|
||||
type VerifiedAccountSession,
|
||||
} from './reddit-account-runtime.js';
|
||||
import { RecipientDeduplicator } from './recipient-deduplicator.js';
|
||||
|
||||
export interface ConcreteRuntimeFactoryOptions {
|
||||
config: Config;
|
||||
@@ -47,12 +49,18 @@ export interface ConcreteRuntimeFactoryOptions {
|
||||
export function createConcreteRedditAccountRuntimeFactory(
|
||||
options: ConcreteRuntimeFactoryOptions,
|
||||
): RedditAccountRuntimeFactory {
|
||||
return new RedditAccountRuntimeFactory((session) => buildRuntime(options, session));
|
||||
const recipientDeduplicator = new RecipientDeduplicator(
|
||||
new RecipientHistoryRepository(options.db),
|
||||
);
|
||||
return new RedditAccountRuntimeFactory(
|
||||
(session) => buildRuntime(options, session, recipientDeduplicator),
|
||||
);
|
||||
}
|
||||
|
||||
async function buildRuntime(
|
||||
{ config, logger, db, isBotRunning = () => true }: ConcreteRuntimeFactoryOptions,
|
||||
session: VerifiedAccountSession,
|
||||
recipientDeduplicator: RecipientDeduplicator,
|
||||
): Promise<RedditAccountRuntime> {
|
||||
const browserProfileDir = accountBrowserProfileDir(
|
||||
path.resolve(process.cwd(), config.browser.sessionDir),
|
||||
@@ -103,7 +111,9 @@ async function buildRuntime(
|
||||
redditApi.setBrowserContext(browserClient.getContext()!);
|
||||
const chatPage = await browserClient.getContext()!.newPage();
|
||||
const aiClient = new OpenRouterClient(accountConfig, logger);
|
||||
const monitorService = new MonitorService(redditApi, postsRepo, messagesRepo, accountConfig, logger);
|
||||
const monitorService = new MonitorService(
|
||||
redditApi, postsRepo, recipientDeduplicator, accountConfig, logger,
|
||||
);
|
||||
const processorService = new ProcessorService(redditApi, aiClient, accountConfig, logger);
|
||||
processorService.setStrategySelector(new StrategySelector(accountConfig, messagesRepo, logger));
|
||||
processorService.setChatStrategySelector(new StrategySelector(accountConfig, messagesRepo, logger, 'chatStrategies'));
|
||||
@@ -146,7 +156,9 @@ async function buildRuntime(
|
||||
monitorService, processorService, responseChecker, chatService, mediaService,
|
||||
mediaSyncService, rateLimiter,
|
||||
};
|
||||
const lifecycle = new AccountRuntimeLoop(resources, accountConfig, logger, isBotRunning);
|
||||
const lifecycle = new AccountRuntimeLoop(
|
||||
resources, accountConfig, logger, isBotRunning, recipientDeduplicator,
|
||||
);
|
||||
return new RedditAccountRuntime(session, resources, lifecycle);
|
||||
} catch (error) {
|
||||
await browserClient.close();
|
||||
@@ -175,6 +187,7 @@ class AccountRuntimeLoop {
|
||||
private readonly config: Config,
|
||||
private readonly logger: Logger,
|
||||
private readonly isBotRunning: () => boolean,
|
||||
private readonly recipientDeduplicator: RecipientDeduplicator,
|
||||
) {}
|
||||
|
||||
start(): void {
|
||||
@@ -257,8 +270,26 @@ class AccountRuntimeLoop {
|
||||
}
|
||||
postsRepo.updateAnalysis(post.id, processed.imageAnalysis, processed.generatedMessage);
|
||||
await rateLimiter.throttle(async () => {
|
||||
const chat = await chatService.startConversation(post.author, processed.generatedMessage, post.author_fullname);
|
||||
if (!chat) return false;
|
||||
if (!this.recipientDeduplicator.tryReserve(post.author)) {
|
||||
postsRepo.setError(post.id, 'User already contacted across accounts');
|
||||
this.resources.activityLogRepo.insert({
|
||||
timestamp: Date.now(), type: 'skipped',
|
||||
message: `Skipped u/${post.author} (already contacted across accounts)`,
|
||||
recipient: post.author,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
let chat;
|
||||
try {
|
||||
chat = await chatService.startConversation(post.author, processed.generatedMessage, post.author_fullname);
|
||||
} catch (error) {
|
||||
this.recipientDeduplicator.release(post.author);
|
||||
throw error;
|
||||
}
|
||||
if (!chat) {
|
||||
this.recipientDeduplicator.release(post.author);
|
||||
return false;
|
||||
}
|
||||
postsRepo.markMessageSent(post.id);
|
||||
messagesRepo.insert({
|
||||
postId: post.id, recipient: post.author, subject: post.author,
|
||||
|
||||
Reference in new issue
Block a user