npm install nestjs-slack-listener

NestJS Slack listeners and handlers

More from hanchchch

hanchchch npm packages

Find the best node modules for your project.

Search npm

nestjs-slack-listener

NestJS Slack listeners and...

Read more

Dependencies

Core dependencies of this npm package and its dev dependencies.

@golevelup/nestjs-modules, @slack/web-api, rxjs, @nestjs/common, @nestjs/core, @nestjs/platform-express, @nestjs/testing, @types/express, @types/jest, @types/node, @types/supertest, @typescript-eslint/eslint-plugin, @typescript-eslint/parser, eslint, eslint-config-prettier, eslint-plugin-import, eslint-plugin-prettier, jest, pre-commit, prettier, reflect-metadata, supertest, ts-jest, ts-node, tsc-watch, tsconfig-paths, typescript

Documentation

A README file for the nestjs-slack-listener code repository. View Code

Nest Logo

NestJS Slack Listeners and Handlers

Built with NestJS

🥰 Any kinds of contributions are welcome! 🥰


Features

Installation

yarn add nestjs-slack-listener

Usage

Please refer to the example for more details.

Settings

Import SlackModule

Import the module at your app module.

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true }),
    SlackModule.forRootAsync({
      useFactory: async (config: ConfigService<EnvVars>) => ({
        botToken: config.get('SLACK_BOT_TOKEN'),
      }),
      inject: [ConfigService],
    }),
  ],
  controllers: [AppController],
  providers: [],
})
export class AppModule {}

Event and Interactivity Subscription

You need to set event and interactivity subscriptions URL of your slack app so that the app can receive events and interactivity from slack.

Decorators

Slack Event

Decorate the controller to use it as slack event listener.

@Controller('on-boarding')
@SlackEventListener()
export class OnBoardingController {}

Decorate the method of the controller to use it as slack event handler.

@Controller('on-boarding')
@SlackEventListener()
export class OnBoardingController {
  constructor(private readonly onboardingService: OnBoardingService) {}

  @SlackEventHandler('team_join')
  async onTeamJoin({ event: { user } }: IncomingSlackEvent<TeamJoinEvent>) {
    this.onboardingService.startOnBoarding({ user });
  }
}

Slack Interactivity

You can also decorate the listeners and handlers for slack-interactivity.

@Controller('on-boarding')
@SlackEventListener()
@SlackInteractivityListener()
export class OnBoardingController {
  constructor(private readonly onboardingService: OnBoardingService) {}

  @SlackEventHandler('team_join')
  async onTeamJoin({ event: { user } }: IncomingSlackEvent<TeamJoinEvent>) {
    this.onboardingService.startOnBoarding({ user });
  }

  @SlackInteractivityHandler(ACTION_ID.COMPLETE_QUEST)
  async completeOnBoarding({
    user: { id: userSlackId },
    actions: [{ value }],
  }: IncomingSlackInteractivity) {
    return this.onboardingService.completeOnBoarding({ userSlackId, value });
  }
}

Filters

Filter the events with function argument filter and string argument eventType of the decorator SlackEventHandler.

@Controller('memo')
@SlackEventListener()
export class MemoController {
  constructor(private readonly memoService: MemoService) {}

  @SlackEventHandler({
    eventType: 'message',
    filter: ({ event }) => event.text.includes('write this down!'),
  })
  async takeMemo({ event: { message } }: IncomingSlackEvent<MessageEvent>) {
    this.memoService.takeMemo({ message });
  }
}

You can also filter the events at the decorator SlackEventListener

@Controller('memo')
@SlackEventListener(({ event }) => event.channel === MEMO_CHANNEL)
export class OnBoardingController {
  constructor(private readonly memoService: MemoService) {}

  @SlackEventHandler({
    eventType: 'message',
    filter: ({ event }) => event.text.includes('write this down!'),
  })
  async onTeamJoin({ event: { user } }: IncomingSlackEvent<MessageEvent>) {
    this.memoService.takeMemo({ message });
  }
}

Slack Client

Use InjectSlackClient to use the slack web api client.

@Injectable()
export class OnBoardingService {
  constructor(
    private readonly userRepository: UserRepository,
    @InjectSlackClient()
    private readonly slack: SlackClient,
  ) {}
  ...
}

The injected SlackClient is identical to the official Slack Web API Client

await this.slack.chat.postMessage({
  channel: user.id,
  text: 'Hi there! 👋🏻',
  blocks: [
    {
      type: 'header',
      text: {
        type: 'plain_text',
        text: 'Hi there! 👋🏻',
      },
    },
    {
      type: 'section',
      text: {
        type: 'mrkdwn',
        text: `Hello! Nice to meet you, ${user.name}! I'm *hanch*, a slack bot that helps you with onboarding process.`,
      },
    },
  ],
});