This app is a simple example of how to use nestjs-slack-listener
to build a slack app. It sends a welcome message with instructions to a new user. The user can press the 'Done!' button to complete the onboarding process.
The controller is decorated with @SlackEventListener()
and @SlackInteractivityListener
to subscribe the events and interactivity.
@Controller('on-boarding')
@SlackEventListener()
@SlackInteractivityListener()
export class OnBoardingController {
...
}
When the user joins to the team, the method decorated with @SlackEventHandler('team_join')
is called.
@SlackEventHandler('team_join')
async onTeamJoin({
event: { user: member },
}: IncomingSlackEvent<TeamJoinEvent>) {
return this.onboardingService.startOnBoarding({ member });
}
When the user presses the 'Done!' button, the method decorated with @SlackInteractivityHandler(ACTION_ID.COMPLETE_QUEST)
is called.
@SlackInteractivityHandler(ACTION_ID.COMPLETE_QUEST)
async completeQuest({
user: { id: userSlackId },
actions: [{ value: questUserId }],
}: IncomingSlackInteractivity) {
if (userSlackId !== questUserId) {
throw new ForbiddenException();
}
return this.onboardingService.completeQuest({
userSlackId,
});
}
The SlackClient
is injected to the service class, enabling it to send a message to the channel.
@Injectable()
export class OnBoardingService {
constructor(
private readonly userRepository: UserRepository,
@InjectSlackClient()
private readonly slack: SlackClient,
) {}
...
}
Include a action block in the message so the user can call the controller method decorated with @SlackInteractivityHandler(ACTION_ID.COMPLETE_QUEST)
.
{
type: 'actions',
elements: [
{
type: 'button',
value: `${user.id}`,
action_id: ACTION_ID.COMPLETE_QUEST,
text: { type: 'plain_text', text: ':white_check_mark: Done!' },
},
],
},
The SlackClient
is identical to the official Slack Web API Client
await this.slack.chat.postMessage(this.buildIntroBlock(user));