2. Handling Messages
Listen for and respond to messages with your bot
Now let's make the bot respond to messages.
Register a Message Handler
Update index.ts to add a message handler:
import { Effect } from "effect"
import { runHazelBot } from "@hazel/bot-sdk"
runHazelBot({
setup: (bot) =>
Effect.gen(function* () {
yield* Effect.log("Task Bot is starting...")
// Register a handler for new messages
yield* bot.onMessage((message) =>
Effect.gen(function* () {
yield* Effect.log(`New message: ${message.content}`)
}),
)
}),
})Run the bot and send a message - you'll see it logged in the console!
Access Message Properties
The message object contains useful information:
yield *
bot.onMessage((message) =>
Effect.gen(function* () {
// Message content
yield* Effect.log(`Content: ${message.content}`)
// Who sent it
yield* Effect.log(`Author ID: ${message.authorId}`)
// Where it was sent
yield* Effect.log(`Channel ID: ${message.channelId}`)
// When it was sent
yield* Effect.log(`Created at: ${message.createdAt}`)
}),
)Reply to Messages
Use bot.message.reply to respond:
yield *
bot.onMessage((message) =>
Effect.gen(function* () {
// Reply to messages containing "hello"
if (message.content.toLowerCase().includes("hello")) {
yield* bot.message.reply(message, "Hello! How can I help?")
}
}),
)Prevent Infinite Loops
When your bot sends a message, it will trigger the onMessage handler again. Always check to avoid responding to your own messages:
yield *
bot.onMessage((message) =>
Effect.gen(function* () {
// Skip messages that start with our response prefix
if (message.content.startsWith("Task Bot:")) {
return
}
if (message.content.toLowerCase().includes("help")) {
yield* bot.message.reply(message, "Task Bot: Use /task-add and /task-list!")
}
}),
)React to Task Mentions
For our Task Bot, let's react to any message mentioning "task":
import { Effect } from "effect"
import { runHazelBot } from "@hazel/bot-sdk"
runHazelBot({
setup: (bot) =>
Effect.gen(function* () {
yield* Effect.log("Task Bot is starting...")
yield* bot.onMessage((message) =>
Effect.gen(function* () {
// React to messages mentioning "task"
if (message.content.toLowerCase().includes("task")) {
yield* bot.message.react(message, "📝")
}
}),
)
}),
})Multiple Handlers
You can register multiple handlers for the same event:
// Handler 1: React to task mentions
yield *
bot.onMessage((message) =>
Effect.gen(function* () {
if (message.content.toLowerCase().includes("task")) {
yield* bot.message.react(message, "📝")
}
}),
)
// Handler 2: Log all messages
yield *
bot.onMessage((message) =>
Effect.gen(function* () {
yield* Effect.log(`[${message.channelId}] ${message.content}`)
}),
)All handlers run in parallel when a message arrives.
What's Next?
Message handlers are great for reactions, but for structured input, slash commands are better.