import { Controller, Get, Post, Query, Body, HttpCode, HttpStatus, Logger, Res } from '@nestjs/common'; import { Response } from 'express'; import { InstagramService } from './instagram.service'; @Controller('webhook') export class InstagramController { private readonly logger = new Logger(InstagramController.name); constructor(private readonly instagramService: InstagramService) {} /** * Webhook verification endpoint required by Meta. * Responds to the GET request with the hub.challenge if verify_token matches. */ @Get() verifyWebhook( @Query('hub.mode') mode: string, @Query('hub.verify_token') verifyToken: string, @Query('hub.challenge') challenge: string, @Res() res: Response ) { const localVerifyToken = process.env.META_VERIFY_TOKEN || 'kodelyx_verify_token_2026'; this.logger.log(`Received Meta verification request: token=${verifyToken}, mode=${mode}`); if (mode === 'subscribe' && verifyToken === localVerifyToken) { this.logger.log('Webhook successfully verified!'); return res.status(HttpStatus.OK).send(challenge); } else { this.logger.warn('Webhook verification failed: token mismatch'); return res.status(HttpStatus.FORBIDDEN).send('Verification failed'); } } /** * Receives events from Instagram (comments, messages, mentions). */ @Post() @HttpCode(HttpStatus.OK) async handleWebhookEvents(@Body() body: any) { this.logger.log('Received webhook event from Meta'); // Make sure it is an instagram object if (body.object !== 'instagram') { this.logger.warn(`Ignored event: object type is ${body.object}`); return { status: 'ignored' }; } try { const entries = body.entry || []; for (const entry of entries) { const instagramId = entry.id; // Instagram Business Account ID const changes = entry.changes || []; for (const change of changes) { // Check if the change is a comment event if (change.field === 'comments') { const commentVal = change.value; const commentId = commentVal.id; const commentText = commentVal.text; const senderId = commentVal.from?.id; if (commentId && commentText && senderId) { this.logger.log( `Processing comment trigger from Instagram user ID ${senderId}: "${commentText}"` ); // Run the background trigger processing this.instagramService.processCommentWebhook( instagramId, commentId, commentText, senderId ).catch((err) => { this.logger.error(`Error in webhook processing async handler: ${err.message}`); }); } } } } return { status: 'processed' }; } catch (error: any) { this.logger.error(`Failed to handle webhook POST request: ${error.message}`); return { status: 'error', message: error.message }; } } }