Skip to content

Error: Can't find scene #1323

@cmontesvergara

Description

@cmontesvergara

Hi, I have this implementation and it doesn't take the scenes, it tells me it can't find them:

[Nest] 93141  - 04/07/2025, 1:09:49   ERROR [ExceptionsHandler] Error: Can't find scene: verificar-telefono
    at SceneContextScene.enter (/Users/cmontes/EmpireSoft/Projects/notibot/node_modules/telegraf/lib/scenes/context.js:57:19)
    at TelegramService.onPhone (/Users/cmontes/EmpireSoft/Projects/notibot/src/adapters/in/telegram/telegram.service.ts:33:21)
    ...
[Nest] 93141  - 04/07/2025, 1:09:49   ERROR [Telegraf: bigsoco_bot] Error: Can't find scene: verificar-telefono

My implementation is:

//telegram.module.ts

import { Global, Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { TelegrafModule } from 'nestjs-telegraf';
import { TelegrafNotificationSender } from 'src/adapters/out/telegraf-notification-sender.adapter';
import { CreateChatUseCase } from 'src/application/use-cases/create-chat.use-case';
import { ChatRepository } from 'src/domain/interfaces/chat-repository.interface';
import { Scenes, session } from 'telegraf';
import { SubscribeToEventUseCase } from '../../../application/use-cases/subscribe-to-event.use-case';
import { PrismaModule } from '../../../infrastructure/prisma/prisma.module';
import { PrismaChatRepository } from '../../out/prisma-chat-repository.adapter';
import {
  CrearChatContext,
  createCrearChatScene,
} from './scenes/crear-chat.scene';
import { createSuscripcionScene } from './scenes/suscripcion.scene';
import { TelegramService } from './telegram.service';
@Global()
@Module({
  imports: [
    PrismaModule,
    TelegrafModule.forRootAsync({
      imports: [ConfigModule],
      useFactory: (
        configService: ConfigService,
        suscripcionScene: Scenes.BaseScene<Scenes.SceneContext>,
        validatePhoneScene: Scenes.BaseScene<Scenes.SceneContext>,
        crearChatScene: Scenes.BaseScene<CrearChatContext>,
      ) => {
        const stage = new Scenes.Stage([
          suscripcionScene,
          crearChatScene,
          validatePhoneScene,
        ]);
        console.log('✅ Escenas cargadas en Stage:');

        return {
          token: configService.get<string>('BOT_TOKEN')!,
          botName: 'telegram',
          middlewares: [session(), stage.middleware()],
        };
      },
      inject: [
        ConfigService,
        'SUSCRIPCION_SCENE',
        'CREAR_CHAT_SCENE',
        'VALIDATE_PHONE_SCENE',
      ],
    }),
  ],
  providers: [
    TelegramService,

    {
      provide: 'ChatRepository',
      useClass: PrismaChatRepository,
    },

    {
      provide: SubscribeToEventUseCase,
      useFactory: (chatRepo: ChatRepository) =>
        new SubscribeToEventUseCase(chatRepo),
      inject: ['ChatRepository'],
    },
    {
      provide: CreateChatUseCase,
      useFactory: (chatRepo: ChatRepository) => new CreateChatUseCase(chatRepo),
      inject: ['ChatRepository'],
    },

    {
      provide: 'SUSCRIPCION_SCENE',
      useFactory: (subscribeUseCase: SubscribeToEventUseCase) =>
        createSuscripcionScene(subscribeUseCase),
      inject: [SubscribeToEventUseCase],
    },
    {
      provide: 'CREAR_CHAT_SCENE',
      useFactory: (createUseCase: CreateChatUseCase) =>
        createCrearChatScene(createUseCase),
      inject: [CreateChatUseCase],
    },
    {
      provide: 'VALIDATE_PHONE_SCENE',
      useFactory: (createUseCase: CreateChatUseCase) =>
        createCrearChatScene(createUseCase),
      inject: [CreateChatUseCase],
    },
    TelegrafNotificationSender,
  ],
  exports: [
    TelegrafNotificationSender,
    'CREAR_CHAT_SCENE',
    'SUSCRIPCION_SCENE',
    'VALIDATE_PHONE_SCENE',
  ],
})
export class TelegramModule {}

//telegram.service.ts


import { Injectable } from '@nestjs/common';
import { Command, Ctx, Start, Update } from 'nestjs-telegraf';
import { SceneContext } from 'telegraf/scenes';
import {
  CREAR_CHAT_SCENE_ID,
  CrearChatContext,
} from './scenes/crear-chat.scene';
import { SUSCRIPCION_SCENE_ID } from './scenes/suscripcion.scene'; // si defines contexto personalizado allí
import { VERIFICAR_TELEFONO_SCENE_ID } from './scenes/validate-phone.scene';

@Update()
@Injectable()
export class TelegramService {
  constructor() {}

  @Start()
  async onStart(@Ctx() ctx: SceneContext) {
    await ctx.reply('👋 ¡Hola! Usa /menu para ver opciones.');
  }

  @Command('menu')
  async onMenu(@Ctx() ctx: SceneContext) {
    console.log('Contexto actual:', ctx);
    await ctx.reply(
      '📋 Opciones disponibles:\n/suscribir - Suscribirse a evento\n/crearChat - Crear nuevo chat',
    );
  }

  @Command('phone')
  async onPhone(@Ctx() ctx: SceneContext) {
    console.log('🧭 Entrando a escena de verificación de teléfono');
    console.log('Contexto actual:', ctx);
    await ctx.scene.enter(VERIFICAR_TELEFONO_SCENE_ID);
  }
  @Command('suscribir')
  async onSuscribir(@Ctx() ctx: SceneContext) {
    console.log('🧭 Entrando a escena de suscripción');
    console.log('Contexto actual:', ctx);
    await ctx.scene.enter(SUSCRIPCION_SCENE_ID);
  }

  @Command('crearChat')
  async crearChat(@Ctx() ctx: CrearChatContext) {
    console.log('🔍 Intentando entrar a crear-chat-scene');
    console.log('Contexto actual:', ctx);
    await ctx.scene.enter(CREAR_CHAT_SCENE_ID);
  }
}

//app.module.ts


import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';

import { EventsController } from './adapters/in/rest-api/events.controller';
import { NotificationsController } from './adapters/in/rest-api/notifications.controller'; // Si lo usas
import { TelegramModule } from './adapters/in/telegram/telegram.module';
import { EventModule } from './infrastructure/event/event.module';
import { NotificationModule } from './infrastructure/notification/notification.module';
import { PrismaModule } from './infrastructure/prisma/prisma.module';

@Module({
  imports: [
    ConfigModule.forRoot(),
    TelegramModule,

    PrismaModule,
    NotificationModule,
    EventModule,
  ],
  controllers: [NotificationsController, EventsController],
})
export class AppModule {}
//validate-phone.scene.ts


import { Scenes } from 'telegraf';
import { BaseScene } from 'telegraf/scenes';

export const VERIFICAR_TELEFONO_SCENE_ID = 'verificar-telefono';

type VerificarTelefonoContext = Scenes.SceneContext & {
  session: {
    intentos?: number;
  };
};

export function createVerificarTelefonoScene(): BaseScene<VerificarTelefonoContext> {
  const scene = new Scenes.BaseScene<VerificarTelefonoContext>(
    VERIFICAR_TELEFONO_SCENE_ID,
  );

  scene.enter(async (ctx) => {
    ctx.session.intentos = 0;
    await ctx.reply('📱 Comparte tu número de teléfono:', {
      reply_markup: {
        keyboard: [[{ text: '📤 Enviar mi número', request_contact: true }]],
        one_time_keyboard: true,
      },
    });
  });

  scene.on('contact', async (ctx) => {
    const contact = ctx.message.contact;
    const fromId = ctx.from?.id;

    if (contact.user_id === fromId) {
      await ctx.reply(`✅ Número verificado: ${contact.phone_number}`);
      return ctx.scene.leave();
    }

    await ctx.reply(
      '❌ El número no coincide con tu cuenta. Intenta de nuevo.',
    );
  });

  scene.on('message', async (ctx) => {
    ctx.session.intentos = (ctx.session.intentos ?? 0) + 1;

    if (ctx.session.intentos > 2) {
      await ctx.reply('🚫 Demasiados intentos inválidos. Cancelo el proceso.');
      return ctx.scene.leave();
    }

    await ctx.reply(
      '❗ Por favor, usa el botón para compartir tu número de teléfono.',
    );
  });

  return scene;
}

There are not many examples of implementation, help me.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions