Model chatbots as conversations. A coroutine that allows you to write chatbot conversations using generator functions.
Have you ever wrote chatbot code looking like this?
const data = {}
myChatbot.on('message', (user, msg) => {
if (!data[user]) data[user] = {state: 0}
const d = data[user]
if (d.state === 0) {
d.state = 1
bot.send(user, 'Tell me foo!')
if (d.state === 1) {
d.foo = msg
d.state = 2
bot.send(user, 'Tell me bar!')
} else if (d.state === 2) {
d.state = 0
bot.send(user, `foo: ${foo} bar: ${msg}`)
}
delete data[user]
})
Now this example is still very naive, as it doesn't handle invalid input and keeps data only in memory. But it demonstrates how such a structure can get quickly get very complex. Using chatbot-coroutine
, you can model your converstional bot like you would reason about it: As one coherent flow of incoming and outgoing messages.
const createRespond = require('chatbot-coroutine')
const inMemStorage = require('chatbot-coroutine/in-mem-storage')
const conversation = function* (ctx) {
let foo = yield ctx.prompt('Tell me foo!')
let bar = yield ctx.prompt('Tell me bar!')
yield ctx.send(`foo: ${foo} bar: ${bar}`)
yield ctx.clear()
}
const respond = createRespond(inMemStorage, bot, conversation, console.error)
bot.on('message', respond)
To make the code handle crashes, write it like this:
const conversation = function* (ctx) {
let foo = yield ctx.read('foo')
if (!foo) {
foo = yield ctx.prompt('Tell me foo!')
yield ctx.write('foo', foo)
}
let bar = yield ctx.read('bar')
if (!bar) {
bar = yield ctx.prompt('Tell me bar!')
yield ctx.write('bar', bar)
}
yield ctx.send(`foo: ${foo} bar: ${bar}`)
yield ctx.clear()
}
npm install chatbot-coroutine
Write a generator function that represents the conversation the bot will have. See Rationale for an example.
const conversation = function* (ctx, user) {
// instructions
}
Using createRespond
, create a respond
function from it. Pass in a storage adapter that fits your needs.
const createRespond = require('chatbot-coroutine')
const inMemStorage = require('chatbot-coroutine/in-mem-storage')
const respond = createRespond(inMemStorage, bot, conversation, console.error)
bot.on('message', respond)
const inMemStorage = require('chatbot-coroutine/in-mem-storage')
const levelDBStorage = require('chatbot-coroutine/leveldb-storage')(db)
bot
should have a send(user, msg)
method.
conversation
should be a generator function function, taking two arguments:
ctx
: the context, allowing you to interact with the bot and the storageuser
: the current user ID
Waits for a message from the user.
Sends a message to the user.
Shorthand for ctx.send(msg)
+ ctx.msg()
.
Writes val
at key
to the storage. This is namespaced by the user.
Reads the value at key
from the storage. This is namespaced by the user.
Deletes everything in the storage. This is namespaced by the user.
storage
should accept a user
(working like a namespace) and have the following methods:
storage(user).write(key, val)
->Promise
– should encode JSONstorage(user).read(key)
->Promise
– should decode JSONstorage(user).clear()
->Promise
If you have a question or have difficulties using chatbot-coroutine
, please double-check your code and setup first. If you think you have found a bug or want to propose a feature, refer to the issues page.