const bot = require('bbot') /** * All branch examples start from the "global" conversation scope. * We are working on features to provide branching within a conversational * context, but as those methods are changing in the beta, they aren't included * as examples to follow just yet. */ /** * Branch types are declared from their scope, see all available types here: * http://bbot.chat/docs/path#builtforbranching * * `text` branches take the following arguments: * - matcher: expression, semantic conditions object, or array of conditions * - callback: to fire on successful match, given the state object (b) * - [options]: object with `id` (string) and/or `force` (boolean) attributes * * Test with "Hello bots!" */ bot.global.text(/(hi|hello).*bots?/, (b) => b.respond('Hello :wave:'), { id: 'hello-bots' }) /** * `direct` branch type requires the bot to be explicitly addressed. * * `reply` instead of `respond` prepends messages with user's name. * * In Rocket.Chat all messages to a bot in a direct room have the name prepended * by the Rocket.Chat SDK before it's processed by the bot framework. * * Test with "@brocket Hello" or just "Hello" in a DM. */ bot.global.direct(/hi|hello/i, (b) => b.reply('Hey there.'), { id: 'hello-direct' }) /** * `respondVia` allows using custom platform methods to dispatch response. * * Matcher conditions allow semantic attributes with a string or array of * optional values to match against, possibly capturing content. * Accepted atts: is, starts, ends, contains, excludes, after, before, range * * Test with "Hello anyone?" */ bot.global.text({ contains: ['hi', 'hello'] }, (b) => b.respondVia('react', ':wave:'), { id: 'hello-react' }) /** * Branch callbacks allow asynchronous responding, if they return a promise. * State (b) includes branch matching attributes, see bbot.chat/docs/thought. * * Test with "@brocket ping back in 5 seconds" */ bot.global.direct(/ping back in (\d*)/i, async (b) => { const ms = parseInt(b.match[1]) * 1000 await new Promise((resolve) => setTimeout(resolve, ms)) return b.respond('Ping :ping_pong:') }, { id: 'ping-delay' }) /** * The `respond` method can accept attachment objects as well as strings. * Rendering support depends on the message platform and adapter. In shell, * it will display the fallback text. * * Test with "bot attach image" */ bot.global.text(/attach image/i, (b) => { return b.respond({ fallback: `See: https://www.wikiwand.com/en/Three_Laws_of_Robotics`, image: `https://upload.wikimedia.org/wikipedia/en/8/8e/I_Robot_-_Runaround.jpg`, title: { text: `Asimov's Three Laws of Robotics`, link: `https://www.wikiwand.com/en/Three_Laws_of_Robotics` } }) }, { id: 'attach-image' }) /** * The `envelope` provides helpers for adding rich-message payloads before * responding. Preparing envelopes before dispatch also allows changing the * user/room the envelope is addressed to or dispatching multiple envelopes. * * Test with "I want a prize" */ bot.global.text({ contains: 'prize' }, (b) => { b.envelope.write('Choose your fate! 🚪... 🎁 ') b.envelope.attach({ color: '#f4426e' }) b.envelope.payload .quickReply({ text: 'Door number 1' }) .quickReply({ text: 'Door number 2' }) .quickReply({ text: 'Door number 3' }) return b.respond().catch((err) => console.error(err)) }, { id: 'door-prize-intro' }) /** * The `conditions` attribute contains results of semantic condition matching * and capture groups. Each condition can be given a key for easy reference. * * Test with "what's behind door number 2" */ bot.global.text({ door: { after: 'door', range: '1-3' } }, (b) => { switch (b.conditions.captured.door) { case '1': return b.respond(`You win nothing 💔`) case '2': return b.respond(`You win a monkey 🐒`) case '3': return b.respond(`It's a new car!! 🚗`) } }, { id: 'door-prize-award' }) /** * Branch callbacks can be async functions, to awaiting one or more processes * before responding. This example uses API requests to fill a dynamic array * of actions, using the url property to provide link action buttons. * * Test with "@brocket plan meeting" in a public or private room. */ bot.global.direct({ is: 'plan meeting' }, async (b) => { if (bot.adapters.message.name !== 'rocketchat-message-adapter') return b.envelope.write('Please review time zones in the room...') const { id, type } = b.message.user.room let room const q = { roomId: id } if (type === 'c') { room = await bot.adapters.message.api.get('channels.members', q, true) } else if (type === 'p') { room = await bot.adapters.message.api.get('groups.members', q, true) } else { return b.respond('Sorry, that only works in channels and private groups.') } const offsets = room.members .map((member) => member.utcOffset || undefined) .filter((offset) => !!offset) for (let utc of offsets) { b.envelope.payload.quickReply({ text: `🌐 UTC ${utc}`, url: `https://www.timeanddate.com/worldclock/timezone/utc${utc}` }) } b.respond() }) /** * @todo This example requires PR #11811 to be merged. Room names are undefined. */ bot.global.text(/where am i/i, (b) => { const { name, type } = b.message.user.room switch (type) { case 'c': return b.respond(`You're in the #${name} public channel.`) case 'p': return b.respond(`You're in a private group called **${name}**.`) case 'l': return b.respond(`You're in a livechat channel.`) case 'd': return b.respond(`You're in a DM with me :hugging:`) } }, { id: 'location-check' }) /** * Custom options can be added to the bot, with the full config utility of bBot, * allowing them to be defined as environment variables, command line args or * package.json attributes. Extend settings with a yargs option format. * * Try any of the following: * - `node index.js --avatar ` * - BOT_AVATAR= in .env * - `{ "bot": { "avatar": "" } }` in package.json */ bot.settings.extend({ avatar: { 'type': 'string', 'description': 'Set a custom avatar for your bot account profile' } }) /** * The bot can access lower level methods of the Rocket.Chat SDK through the * message adapter, once it's connected. This example sets an avatar on login. * * Try replacing the avatar configured in package.json with your own. */ bot.events.on('started', () => { if (bot.adapters.message.name !== 'rocketchat-message-adapter') return if (bot.settings.get('avatar')) { bot.logger.info('Setting bot avatar') bot.adapters.message.api.post('users.setAvatar', { avatarUrl: bot.settings.get('avatar') }) } })