New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

finochat-botkit

Package Overview
Dependencies
Maintainers
1
Versions
46
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

finochat-botkit

finochat bot framework

  • 2.0.5
  • latest
  • npm
  • Socket score

Version published
Maintainers
1
Created
Source

FinoChat Botkit机器人开发框架

Build Status


机器人框架主要基于Matrix聊天协议接入FinoChat应用并通过FSM(有限状态机)管理会话状态,以及FinoChat ConvoUI协议扩展实现的聊天机器人。


1. 安装

1.1 npm 安装

npm install finochat-botkit

nodejs版本要求为v9.4.0

2. 原理:

2.1 大致流程

  • 基于本框架的应用程序在启动时,就启动matrix聊天协议的客户端,并保持连接,并进行聊天服务器事件的监听
  • 用户添加机器人后,机器人受邀自动加入房间,机器人可以发送欢迎消息提示
  • 状态机以某个状态进行初始化,机器人接收到用户消息后进行匹配,成功后发给用户发送会话提问消息
  • 用户在ConvoUI操作或者文字回复,机器人根据回复消息选择是否推进会话到下一个状态,或者停留在本状态继续会话,甚至结束会话

2.2 ConvoUI协议

  • ConvoUI是指聊天对话当中的富文本消息(文字、图片、视频、菜单等等的组合)
  • 机器人框架通过封装ConvoUI工厂方法向客户端发送满足协议的扩展消息体,由客户端实现对扩展消息体的具体渲染

3. 使用

3.1 基本用法

3.1.1 配置文件

config.js说明

  • homeserver:finoChat聊天服务器接口
  • loginUrl:机器人中心登录接口
  • fcid:机器人登录ID
  • password:机器人登录密码
  • ENABLE_MONITOR:是否开启该机器人的监控,默认false
module.exports = {
    // 以下配置接口和机器人账号仅供演示测试用
    homeserver: process.env.HOMESERVER || "https://api.finolabs.club",
    loginUrl: process.env.LOGIN_URL || "https://api.finolabs.club/api/v1/registry/botlogin",
    fcid: process.env.FCID || "@test-bot:finolabs.club",
    password: process.env.PASSWORD || "123456",

    ENABLE_MONITOR: process.env.ENABLE_MONITOR || false
    logLevel: 'debug',
    timeout: 30000,
    routelist: [],
    whitelist: [],
    blacklist: [],
};
3.1.2 引入依赖
const botkit = require('finochat-botkit');
3.1.3 定义状态
const States = {
    INIT: 'INIT',
    STEP1: 'STEP1',
    STEP2: 'STEP2'
};
3.1.4 机器人开发

继承botkit.Bot类

class demoBot extends botkit.Bot
  • 机器人开发者只需继承botkit.Bot类,然后在状态机定义函数 describe()里面进行状态描述和消息匹配,即可集中于书写机器人业务处理逻辑。
  • describe(fsm, bot)接收两个参数,fsm状态机实例,bot实例

引入状态机和匹配 API

// 引入状态机API
const { startWith, when, goto, stay, stop } = botkit.DSL(fsm);

// 引入匹配API
const { match, BodyCase, ActionCase, CommandCase, DefaultCase } = botkit.Matcher;

状态机API基本用法

 // 初始化状态,接收一个状态参数
startWith(States.INIT);

// 描述某个状态,接收一个状态参数,返回一个asnyc回调函数
// sender发送消息的用户信息,content用户发送的消息体(注意:content.body才是消息体文本内容)
when(States.STEP1)(asnyc (sender, content) => {

	// 机器人发送消息接口,第一个参数为房间ID,第二个参数为JSON消息体
	bot.sendMessage(sender.roomId, { body: 'hello from bot' });
	
	// 机器人发送文本消息接口,第一个参数为房间ID,第二个参数为具体文本
	bot.sendMessage(sender.roomId, 'hello from bot');
	
	// 描述状态转移,全部都可以链式调用withConvoMsg方法给用户附带发送消息,其中goto接收下一个状态作为参数
	return stop()/stay()/goto(States.STEP2).withConvoMsg('Hi there!');
	
});

匹配API基本用法

when(States.STEP1)(asnyc (sender, content) => {
	
	 // 匹配函数,接收第一个参数(content消息体)和其他具体匹配方法作为后续参数传入
    return match(content,
    
        // 普通聊天文本消息匹配,支持字符串和正则表达式,匹配成功后做对应的逻辑处理
        BodyCase('Hey bot!')(() => {
            return goto(States.STEP1).withConvoMsg('Hi there!');
        })

    );
	
});
3.1.5 机器人运行
new demoBot(require('config')).run();

3.2 代码demo

// 引入机器人框架依赖
const botkit = require('finochat-botkit');

// 定义状态机的各种状态
const States = {
    INIT: 'INIT',
    STEP1: 'STEP1',
    STEP2: 'STEP2'
};

// 创建自己的机器人
class demoBot extends botkit.Bot {
	
	// 机器人被邀请加入房间
    onJoinRoom(bot, roomId, userId, displayName) {
        return `亲,我是DemoBot【roomId: ${roomId}, userId: ${userId}, displayName: ${displayName}】`;
    }

    // 用户被邀请加入房间
    onUserJoinRoom(bot, roomId, userId, displayName) {
        return this.onJoinRoom(bot, roomId, userId, displayName);
    }

    // 用户当前视图切换入房间
    onUserEnterRoom(bot, roomId, userId, displayName) {
        return this.onJoinRoom(bot, roomId, userId, displayName);
    }

    // 会话超时结束
    onTimeout(bot, roomId, userId, displayName) {
        return `会话结束【roomId: ${roomId}, userId: ${userId}, displayName: ${displayName}】`;
    }
    
    // 状态机定义函数, 主要的逻辑写在这里
    describe(fsm, bot) {
 		/**
         * 状态机 DSL
         * startWith 描述状态机的初始状态和初始 data,只需调用一次
         * when 描述某个状态下,发生Event时,Bot业务执行与状态迁移的细节
         * goto 用于生成when()函数的返回值,返回 nextState
         * stay goto(CurrentState)的另一种形式,停留在本状态
         * stop goto(Done)的另一种形式,结束会话
         */
        const { startWith, when, goto, stay, stop } = botkit.DSL(fsm);
		/**
         * matcher API
         * BodyCase 匹配普通聊天中的string, 支持变长 pattern(String or RegExp type)
         * ActionCase 匹配convoUI消息的action,支持变长 pattern(String or RegExp type)
         * CommandCase 匹配convoUI消息的command类型,支持变长pattern(String or RegExp type)
         * DefaultCase 模式匹配的Default分支
         */
        const { match, BodyCase, ActionCase, CommandCase, DefaultCase } = botkit.Matcher;
		
		// 初始化状态
        startWith(States.INIT);
		
		// INIT状态描述
        when(States.INIT)(async (sender, content) => {
        
        	// 匹配函数,接收第一个参数(content消息体)和其余参数(消息匹配方法)
            return match(content,
            
				// 匹配消息成功后回调,返回客户端消息(withConvoMsg方法)并转移到STEP1状态
                BodyCase('Hey bot!')(() => {
                    return goto(States.STEP1).withConvoMsg('Hi there!');
                })

            );
        });

        when(States.STEP1)(async (sender, content) => {
            return match(content,

                ActionCase('action1')(() => {
                    return goto(States.STEP2).withConvoMsg('U r in Step2 now');
                }),

                DefaultCase(() => {
                
                	// ConvoUI工厂方法创建Assist消息
                    const ui = botkit.ConvoFactory.ui()
                    	
                    	// body文本在ConvoUI无法渲染时显示,类似HTML中img标签的alt提示属性
                        .setBody('assist demo')
                        
                        // Layout工厂方法创建带两个按钮的Assist消息
                        .setPayload(
                            botkit.LayoutFactory.assist().setTitle('assist').addItems(
                                botkit.ActionFactory.button('button1', 'action1')
                                botkit.ActionFactory.button('button2', 'action2')
                            )
                        );
                    return stay().withConvoMsg(ui);
                })

            );
        });

        when(States.STEP2)(async (sender, content) => {
            return match(content,

                BodyCase('apple')(() => {
                    return stop().withConvoMsg('You can buy an Apple product in https://www.apple.com/');
                })

            );
        });
    }
}

// 机器人运行
new demoBot(require('config')).run();

4. 接口

4.1 会话事件

  • onJoinRoom(bot, roomId, userId, displayName) :机器人被邀请加入房间
  • onUserJoinRoom(bot, roomId, userId, displayName):用户被邀请加入房间
  • onUserEnterRoom(bot, roomId, userId, displayName):用户当前视图切换入房间
  • onTimeout(bot, roomId, userId, displayName):会话超时结束

4.2 状态机DSL

  • startWith:描述状态机的初始状态和初始 data,只需调用一次
  • when:描述某个状态下,发生Event时,Bot业务执行与状态迁移的细节
  • goto:用于生成when()函数的返回值,返回 nextState
  • stay:goto(CurrentState)的另一种形式,停留在本状态
  • stop:goto(Done)的另一种形式,结束会话

4.3 消息匹配API

  • BodyCase:匹配普通聊天中的string, 支持变长 pattern(String or RegExp type)
  • ActionCase:匹配convoUI消息的action,支持变长 pattern(String or RegExp type)
  • CommandCase:匹配convoUI消息的command类型,支持变长pattern(String or RegExp type)
  • DefaultCase:模式匹配的Default分支

4.4 状态机data的共享

状态机describe()的方法体内可以使用如下两种方式共享变量(session scope)

  • 常规方式是在状态迁移时,将修改后的data对象传递给 using(). 这里建议通过 spread-rest 语法构造 immutable object 对象。后续会方便利用到状态跟踪,重演,TimeTravel Debugging 等很多玩法。
  • 还有一种可行的方式是,直接将变量挂在 fsm 上面

4.5 底层API

在回调函数内,可以不借助 matcher API,通过判断 content 或者 data 的具体细节来控制分支走向, 获得最大的灵活度:

when(MyStates.IDLE)(async (sender, content, data) => {
    if(content.body === "step1") {
        return goto(MyStates.STEP1).withConvoMsg({body: "I goto step1!"});
    } else if (content.body === "开始业务2") {
        return goto(MyStates.STEP2)
    }

    return stay().withConvoMsg({body: "Stay!"});
});

FAQs

Package last updated on 06 May 2020

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc