You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
86 lines
2.5 KiB
TypeScript
86 lines
2.5 KiB
TypeScript
import { Bun } from 'bun';
|
|
import { CommandService } from './services/command';
|
|
import { ResponseQueue } from './services/response-queue';
|
|
|
|
const PORT = 3007;
|
|
|
|
type WebhookPayload = {
|
|
event: string;
|
|
instance: string;
|
|
data: any;
|
|
// Other fields from Evolution API
|
|
};
|
|
|
|
export class WebhookServer {
|
|
static async handleRequest(request: Request): Promise<Response> {
|
|
// 1. Method validation
|
|
if (request.method !== 'POST') {
|
|
return new Response('Method not allowed', { status: 405 });
|
|
}
|
|
|
|
// 2. Content-Type validation
|
|
const contentType = request.headers.get('content-type');
|
|
if (!contentType?.includes('application/json')) {
|
|
return new Response('Invalid content type', { status: 400 });
|
|
}
|
|
|
|
try {
|
|
// 3. Parse and validate payload
|
|
const payload = await request.json() as WebhookPayload;
|
|
|
|
if (!payload.event || !payload.instance) {
|
|
return new Response('Invalid payload', { status: 400 });
|
|
}
|
|
|
|
// 4. Verify instance matches
|
|
if (payload.instance !== process.env.INSTANCE_NAME) {
|
|
return new Response('Invalid instance', { status: 403 });
|
|
}
|
|
|
|
// 5. Route events
|
|
switch (payload.event) {
|
|
case 'messages.upsert':
|
|
await this.handleMessageUpsert(payload.data);
|
|
break;
|
|
// Other events will be added later
|
|
}
|
|
|
|
return new Response('OK', { status: 200 });
|
|
} catch (error) {
|
|
return new Response('Invalid request', { status: 400 });
|
|
}
|
|
}
|
|
|
|
private static async handleMessageUpsert(data: any) {
|
|
// Basic message validation
|
|
if (!data?.key?.remoteJid || !data.message || !data.message.conversation) return;
|
|
|
|
// Forward to command service only if:
|
|
// 1. It's a text message (has conversation field)
|
|
// 2. Starts with /tarea command
|
|
const messageText = data.message.conversation;
|
|
if (typeof messageText === 'string' && messageText.trim().startsWith('/tarea')) {
|
|
const responses = await CommandService.handle({
|
|
sender: data.key.participant,
|
|
groupId: data.key.remoteJid,
|
|
message: messageText,
|
|
mentions: data.contextInfo?.mentionedJid || []
|
|
});
|
|
|
|
// Queue responses for sending
|
|
await ResponseQueue.add(responses);
|
|
}
|
|
}
|
|
|
|
static start() {
|
|
if (process.env.NODE_ENV !== 'test') {
|
|
const server = Bun.serve({
|
|
port: PORT,
|
|
fetch: WebhookServer.handleRequest,
|
|
});
|
|
console.log(`Server running on port ${PORT}`);
|
|
return server;
|
|
}
|
|
}
|
|
} // <-- This closing brace was missing
|