Skip to content

Commit 298502c

Browse files
authored
Merge pull request #36 from TogetherCrew/refactor
Refactor
2 parents 2d76446 + 4bc80fe commit 298502c

File tree

9 files changed

+254
-202
lines changed

9 files changed

+254
-202
lines changed

apps/bot/src/bot.module.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { TemporalModule } from 'nestjs-temporal';
88
import { temporalConfig } from '@app/common/config/temporal.config';
99
import { Connection } from '@temporalio/client';
1010
import { RabbitMQModule } from './rabbitmq/rabbitmq.module';
11+
import { HandlersModule } from './handlers/handlers.module';
1112

1213
@Module({
1314
imports: [
@@ -17,25 +18,19 @@ import { RabbitMQModule } from './rabbitmq/rabbitmq.module';
1718
isGlobal: true,
1819
}),
1920
RabbitMQModule,
21+
HandlersModule,
2022
TemporalModule.registerClientAsync({
2123
inject: [ConfigService],
2224
useFactory: async (config: ConfigService) => {
2325
const uri = config.get('temporal.uri');
24-
console.log('uri', uri);
25-
let connection: Connection;
26-
try {
27-
connection = await Connection.connect({
28-
address: uri,
29-
});
30-
} catch (error) {
31-
console.error('Failed to connect to Temporal:', error);
32-
throw error;
33-
}
26+
const connection: Connection = await Connection.connect({
27+
address: uri,
28+
});
3429
return { connection };
3530
},
3631
}),
3732
],
3833
controllers: [BotController],
3934
providers: [BotService],
4035
})
41-
export class BotModule {}
36+
export class BotModule { }

apps/bot/src/bot.service.ts

Lines changed: 76 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { IgnoreEvent, UpdateEvent } from '@app/common';
22
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
33
import { ConfigService } from '@nestjs/config';
4-
import { WorkflowClient } from '@temporalio/client';
54
import { API_CONSTANTS, Bot, Context, RawApi } from 'grammy';
65
import { Other } from 'grammy/out/core/api';
7-
import { Message, Update } from 'grammy/types';
8-
import { InjectTemporalClient } from 'nestjs-temporal';
9-
10-
const HIVEMIND_BLOCKLIST = ['-1002141367711'];
6+
import { Message } from 'grammy/types';
7+
import { QuestionHandler } from './handlers/question.handler';
8+
import { UpdateHandler } from './handlers/update.handler';
9+
import { VerifyHandler } from './handlers/verify.handler';
10+
import { SummaryHandler } from './handlers/summary.handler';
1111

1212
@Injectable()
1313
export class BotService implements OnModuleInit {
@@ -16,14 +16,23 @@ export class BotService implements OnModuleInit {
1616

1717
constructor(
1818
private readonly configService: ConfigService,
19-
@InjectTemporalClient()
20-
private readonly temporalClient: WorkflowClient,
19+
private readonly questionHandler: QuestionHandler,
20+
private readonly updateHandler: UpdateHandler,
21+
private readonly verifyHandler: VerifyHandler,
22+
private readonly summaryHandler: SummaryHandler,
2123
) {
22-
this.bot = new Bot(configService.get<string>('telegram.token'));
24+
this.bot = new Bot(this.configService.get<string>('telegram.token'));
2325

2426
this.bot.command('start', this.start);
25-
this.bot.command('verify', this.isAdmin, this.verify);
26-
this.bot.command('summary', this.getSummary);
27+
this.bot.command(
28+
'verify',
29+
this.isAdmin,
30+
this.verifyHandler.handle.bind(this.verifyHandler),
31+
);
32+
this.bot.command(
33+
'summary',
34+
this.summaryHandler.handle.bind(this.summaryHandler),
35+
);
2736

2837
Object.values(IgnoreEvent).map((event) => {
2938
this.bot.on(event, () => {
@@ -34,20 +43,8 @@ export class BotService implements OnModuleInit {
3443
Object.values(UpdateEvent).map((event) => {
3544
this.bot.on(event, (ctx: Context) => {
3645
this.logger.log(`Received ${event} from ${ctx.chat.id}`);
37-
this.processEvent(event, ctx.update);
38-
try {
39-
if (
40-
event !== UpdateEvent.CHAT_MEMBER &&
41-
ctx.update.message?.from &&
42-
!ctx.update.message.from.is_bot &&
43-
ctx.update.message.text?.trim().length > 0
44-
) {
45-
this.processQuestion(ctx);
46-
}
47-
} catch (error) {
48-
this.logger.error(error);
49-
}
50-
46+
this.updateHandler.handle(ctx);
47+
this.questionHandler.handle(ctx);
5148
return;
5249
});
5350
});
@@ -123,153 +120,59 @@ export class BotService implements OnModuleInit {
123120
await ctx.reply(text, { parse_mode: 'HTML' });
124121
};
125122

126-
protected verify = async (ctx: Context) => {
127-
const token = ctx.match;
128-
const chat = ctx.chat;
129-
const from = ctx.from;
130-
131-
if (!token || !chat || !from) {
132-
await ctx.reply(
133-
'Not enough data to complete this request. Reach out to our support team.',
134-
);
135-
return;
136-
}
137-
138-
try {
139-
const handle = await this.temporalClient.start('TelegramVerifyWorkflow', {
140-
taskQueue: this.configService.get<string>('temporal.queue'),
141-
args: [{ token, chat, from }],
142-
workflowId: `telegram:verify:${token}`,
143-
});
144-
145-
const result = await handle.result();
146-
await ctx.reply(result);
147-
} catch (error) {
148-
console.error(error);
149-
await ctx.reply(
150-
'Something unexpected happened. Reach out to our support team.',
151-
);
152-
}
153-
};
154-
155-
protected processEvent = async (event: string, update: Update) => {
156-
try {
157-
await this.temporalClient.start('TelegramEventWorkflow', {
158-
taskQueue: this.configService.get<string>('temporal.queue'),
159-
args: [{ event, update }],
160-
workflowId: `telegram:event:${update.update_id}`,
161-
});
162-
} catch (error) {
163-
console.error(error);
164-
}
165-
};
166-
167-
protected processQuestion = async (ctx: Context) => {
168-
try {
169-
if (HIVEMIND_BLOCKLIST.includes(ctx.chat.id.toString())) {
170-
console.log('Skipping question from HIVEMIND for', ctx.chat.id);
171-
return;
172-
}
173-
174-
const community = await this.temporalClient.execute(
175-
'TelegramGetCommunityWorkflow',
176-
{
177-
taskQueue: 'TEMPORAL_QUEUE_LIGHT',
178-
args: [{ chatId: ctx.chat.id }],
179-
workflowId: `telegram:getcommunity:${ctx.update.update_id}`,
180-
},
181-
);
182-
if (!community) {
183-
console.log('No community found for', ctx.chat.id);
184-
return;
185-
}
186-
187-
const reply = await this.temporalClient.execute(
188-
'AgenticHivemindTemporalWorkflow',
189-
{
190-
taskQueue: 'HIVEMIND_AGENT_QUEUE',
191-
args: [
192-
{
193-
community_id: community.id,
194-
query: ctx.update.message.text,
195-
enable_answer_skipping: true,
196-
},
197-
],
198-
workflowId: `telegram:hivemind:${ctx.update.update_id}`,
199-
},
200-
);
201-
202-
if (!reply || reply.length === 0) {
203-
console.log('No reply from hivemind.');
204-
return;
205-
}
206-
207-
const other = {
208-
reply_parameters: {
209-
message_id: ctx.update.message.message_id,
210-
},
211-
};
212-
213-
console.log('Reply from hivemind:', reply);
214-
await ctx.reply(reply, other);
215-
} catch (error) {
216-
console.error(error);
217-
}
218-
};
219-
220-
protected getSummary = async (ctx: Context) => {
221-
try {
222-
const community = await this.temporalClient.execute(
223-
'TelegramGetCommunityWorkflow',
224-
{
225-
taskQueue: 'TEMPORAL_QUEUE_LIGHT',
226-
args: [{ chatId: ctx.chat.id }],
227-
workflowId: `telegram:getcommunity:${ctx.update.update_id}`,
228-
},
229-
);
230-
if (!community) {
231-
console.log('No community found for', ctx.chat.id);
232-
return;
233-
}
234-
235-
const platform = await this.temporalClient.execute(
236-
'TelegramGetPlatformWorkflow',
237-
{
238-
taskQueue: 'TEMPORAL_QUEUE_LIGHT',
239-
args: [{ chatId: ctx.chat.id }],
240-
workflowId: `telegram:getplatform:${ctx.update.update_id}`,
241-
},
242-
);
243-
if (!platform) {
244-
console.log('No platform found for', ctx.chat.id);
245-
return;
246-
}
247-
248-
const summary = await this.temporalClient.execute(
249-
'PlatformSummariesWorkflow',
250-
{
251-
taskQueue: 'TEMPORAL_QUEUE_PYTHON_LIGHT',
252-
args: [
253-
{
254-
platform_id: platform.id,
255-
community_id: community.id,
256-
start_date: null,
257-
end_date: null,
258-
extract_text_only: true,
259-
},
260-
],
261-
workflowId: `telegram:summaries:${ctx.update.update_id}`,
262-
},
263-
);
264-
265-
if (!summary || summary.length === 0) {
266-
console.log('No summary found for', ctx.chat.id);
267-
return;
268-
}
269-
270-
await ctx.reply(summary);
271-
} catch (error) {
272-
console.error(error);
273-
}
274-
};
123+
// protected getSummary = async (ctx: Context) => {
124+
// try {
125+
// const community = await this.temporalClient.execute(
126+
// 'TelegramGetCommunityWorkflow',
127+
// {
128+
// taskQueue: 'TEMPORAL_QUEUE_LIGHT',
129+
// args: [{ chatId: ctx.chat.id }],
130+
// workflowId: `telegram:getcommunity:${ctx.update.update_id}`,
131+
// },
132+
// );
133+
// if (!community) {
134+
// console.log('No community found for', ctx.chat.id);
135+
// return;
136+
// }
137+
138+
// const platform = await this.temporalClient.execute(
139+
// 'TelegramGetPlatformWorkflow',
140+
// {
141+
// taskQueue: 'TEMPORAL_QUEUE_LIGHT',
142+
// args: [{ chatId: ctx.chat.id }],
143+
// workflowId: `telegram:getplatform:${ctx.update.update_id}`,
144+
// },
145+
// );
146+
// if (!platform) {
147+
// console.log('No platform found for', ctx.chat.id);
148+
// return;
149+
// }
150+
151+
// const summary = await this.temporalClient.execute(
152+
// 'PlatformSummariesWorkflow',
153+
// {
154+
// taskQueue: 'TEMPORAL_QUEUE_PYTHON_LIGHT',
155+
// args: [
156+
// {
157+
// platform_id: platform.id,
158+
// community_id: community.id,
159+
// start_date: null,
160+
// end_date: null,
161+
// extract_text_only: true,
162+
// },
163+
// ],
164+
// workflowId: `telegram:summaries:${ctx.update.update_id}`,
165+
// },
166+
// );
167+
168+
// if (!summary || summary.length === 0) {
169+
// console.log('No summary found for', ctx.chat.id);
170+
// return;
171+
// }
172+
173+
// await ctx.reply(summary);
174+
// } catch (error) {
175+
// console.error(error);
176+
// }
177+
// };
275178
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Logger } from '@nestjs/common';
2+
import { ConfigService } from '@nestjs/config';
3+
import { WorkflowClient } from '@temporalio/client';
4+
import { Context, FilterQuery } from 'grammy';
5+
import { InjectTemporalClient } from 'nestjs-temporal';
6+
7+
export abstract class BaseHandler {
8+
protected readonly logger = new Logger(this.constructor.name);
9+
10+
constructor(
11+
@InjectTemporalClient()
12+
protected readonly temporalClient: WorkflowClient,
13+
protected readonly configService: ConfigService,
14+
) { }
15+
abstract handle(ctx: Context, event?: FilterQuery): Promise<void>;
16+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Module } from '@nestjs/common';
2+
import { ConfigModule } from '@nestjs/config';
3+
import { TemporalModule } from 'nestjs-temporal';
4+
import { QuestionHandler } from './question.handler';
5+
import { UpdateHandler } from './update.handler';
6+
import { VerifyHandler } from './verify.handler';
7+
import { SummaryHandler } from './summary.handler';
8+
9+
@Module({
10+
imports: [ConfigModule, TemporalModule],
11+
providers: [QuestionHandler, UpdateHandler, VerifyHandler, SummaryHandler],
12+
exports: [QuestionHandler, UpdateHandler, VerifyHandler, SummaryHandler],
13+
})
14+
export class HandlersModule { }

0 commit comments

Comments
 (0)