nestjs-slack-listener
v1.1.3
Published
NestJS Slack listeners and handlers
Downloads
476
Maintainers
Readme
Features
- Class decorator
@SlackEventListener
- Decorate the class to use it as a Slack event listener, just like decorating HTTP listeners with
@Controller
.
- Decorate the class to use it as a Slack event listener, just like decorating HTTP listeners with
- Method decorator
@SlackEventHandler
- Decorate the method to use it as a Slack event handler, just like decorating HTTP handlers with
@Get
,@Post
, etc. - You can filter events by event type, or your custom filtering function.
- Decorate the method to use it as a Slack event handler, just like decorating HTTP handlers with
- Slack Web API Client
- Inject the Slack Web API client to your service class with
@InjectSlackClient
decorator. - You can use the client to send messages to Slack, or whatever you want to do.
- Inject the Slack Web API client to your service class with
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.
- Event subscription
- https://api.slack.com/apps/your-app-id/event-subscriptions
http://<hostname>/slack/events
- Interactivity subscription
- https://api.slack.com/apps/your-app-id/interactive-messages
http://<hostname>/slack/interactivity
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.`,
},
},
],
});