golang跨平台聊天机器人开发框架插件库go-sarah的使用
Golang跨平台聊天机器人开发框架插件库go-sarah的使用
介绍
Sarah是一个通用机器人框架,以作者第一个女儿的名字命名。它提供了"有状态命令"等独特功能,以及命令和定时任务等基本功能。此外,该项目还提供丰富的生命周期管理功能,包括实时配置更新、可定制的警报机制、自动命令/任务(重新)构建和防panic的并发命令/任务执行。
重要通知
v4版本发布
这是go-sarah
的第四个主要版本,包含一些架构变更:
sarah.NewBot
现在返回单个值:sarah.Bot
- 包括logger、retry和worker在内的实用包现在由
github.com/oklahomer/go-kasumi
托管
支持的聊天服务/协议
虽然开发者可以实现sarah.Adapter
来集成所需的聊天服务,但项目提供了一些适配器作为参考实现:
- Slack
- Gitter
- XMPP
- LINE
快速入门
一般命令执行
上图展示了go-sarah
的一般用法。注册的命令会检查用户输入,匹配的命令会被执行;当用户输入".hello"时,hello命令执行并返回"Hello, 世界"消息。
有状态命令执行
下图展示了带有用户对话上下文的命令如何工作。"用户对话上下文"的想法和实现是go-sarah
的标志性功能,使机器人命令具有"状态感知"能力。
示例代码
以下是实现上述一般命令和有状态命令的最小代码示例。这个例子展示了两种实现sarah.Command
的方式:一种是直接实现sarah.Command
接口;另一种使用sarah.CommandPropsBuilder
进行延迟构造。
主程序
package main
import (
"context"
"fmt"
"github.com/oklahomer/go-sarah/v4"
"github.com/oklahomer/go-sarah/v4/slack"
"os"
"os/signal"
"syscall"
// 下面的包在init()中注册命令
// 使用空白标识符导入即可实现
_ "guess"
_ "hello"
)
func main() {
// 设置Slack适配器
setupSlack()
// 准备Sarah的核心上下文
ctx, cancel := context.WithCancel(context.Background())
// 运行
config := sarah.NewConfig()
err := sarah.Run(ctx, config)
if err != nil {
panic(fmt.Errorf("failed to run: %s", err.Error()))
}
// 当收到信号时停止
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGTERM)
select {
case <-c:
cancel()
}
}
func setupSlack() {
// 设置slack适配器
slackConfig := slack.NewConfig()
slackConfig.Token = "REPLACE THIS"
adapter, err := slack.NewAdapter(slackConfig, slack.WithRTMPayloadHandler(slack.DefaultRTMPayloadHandler))
if err != nil {
panic(fmt.Errorf("faileld to setup Slack Adapter: %s", err.Error()))
}
// 设置可选存储,以便存储对话上下文
cacheConfig := sarah.NewCacheConfig()
storage := sarah.NewUserContextStorage(cacheConfig)
// 使用Slack适配器和默认存储设置机器人
bot := sarah.NewBot(adapter, sarah.BotWithStorage(storage))
sarah.RegisterBot(bot)
}
猜数字命令实现
package guess
import (
"context"
"github.com/oklahomer/go-sarah/v4"
"github.com/oklahomer/go-sarah/v4/slack"
"math/rand"
"strconv"
"strings"
"time"
)
func init() {
sarah.RegisterCommandProps(props)
}
var props = sarah.NewCommandPropsBuilder().
BotType(slack.SLACK).
Identifier("guess").
Instruction("Input .guess to start a game.").
MatchFunc(func(input sarah.Input) bool {
return strings.HasPrefix(strings.TrimSpace(input.Message()), ".guess")
}).
Func(func(ctx context.Context, input sarah.Input) (*sarah.CommandResponse, error) {
// 在开始时生成答案值
rand.Seed(time.Now().UnixNano())
answer := rand.Intn(10)
// 让用户猜测正确答案
return slack.NewResponse(input, "Input number.", slack.RespWithNext(func(c context.Context, i sarah.Input) (*sarah.CommandResponse, error){
return guessFunc(c, i, answer)
}))
}).
MustBuild()
func guessFunc(_ context.Context, input sarah.Input, answer int) (*sarah.CommandResponse, error) {
// 为了方便,创建一个递归调用guessFunc的函数,直到用户输入正确答案
retry := func(c context.Context, i sarah.Input) (*sarah.CommandResponse, error) {
return guessFunc(c, i, answer)
}
// 检查用户是否输入了有效数字
guess, err := strconv.Atoi(strings.TrimSpace(input.Message()))
if err != nil {
return slack.NewResponse(input, "Invalid input format.", slack.RespWithNext(retry))
}
// 如果猜对了,告诉用户并结束当前用户上下文
// 否则,让用户输入下一个猜测并给出提示
if guess == answer {
return slack.NewResponse(input, "Correct!")
} else if guess > answer {
return slack.NewResponse(input, "Smaller!", slack.RespWithNext(retry))
} else {
return slack.NewResponse(input, "Bigger!", slack.RespWithNext(retry))
}
}
Hello命令实现
package hello
import (
"context"
"github.com/oklahomer/go-sarah/v4"
"github.com/oklahomer/go-sarah/v4/slack"
"strings"
)
func init() {
sarah.RegisterCommand(slack.SLACK, &command{})
}
type command struct {
}
var _ sarah.Command = (*command)(nil)
func (hello *command) Identifier() string {
return "hello"
}
func (hello *command) Execute(_ context.Context, i sarah.Input) (*sarah.CommandResponse, error) {
return slack.NewResponse(i, "Hello!")
}
func (hello *command) Instruction(input *sarah.HelpInput) string {
if 12 < input.SentAt().Hour() {
// 此命令仅在上午活动
// 下午不显示指令
return ""
}
return "Input .hello to greet"
}
func (hello *command) Match(input sarah.Input) bool {
return strings.TrimSpace(input.Message()) == ".hello"
}
支持的Golang版本
官方发布策略规定"每个主要的Go版本支持到有两个更新的主要版本发布为止"。遵循这一策略有助于本项目享受后续版本中的改进。然而,并非所有项目都能立即切换到新环境。特别是当本项目在新的主要Go版本发布后立即切断对旧版本的支持时,迁移可能会特别困难。
作为过渡期,本项目比Go项目多支持一个旧版本。这样的版本保证会列在.travis.ci中。换句话说,1.10中引入的新功能/接口只有等到1.12发布后才能在本项目中使用。
更多关于golang跨平台聊天机器人开发框架插件库go-sarah的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang跨平台聊天机器人开发框架插件库go-sarah的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
go-sarah: Golang跨平台聊天机器人开发框架
go-sarah是一个轻量级的Golang聊天机器人框架,支持多平台集成,包括Slack、LINE、Gitter等。它提供了插件化架构,使得开发者可以轻松扩展功能。
核心特性
- 多平台支持:统一接口对接不同聊天平台
- 插件系统:模块化开发,易于扩展
- 定时任务:支持定时消息推送
- 上下文管理:维护用户会话状态
- 配置热加载:无需重启即可更新配置
基本使用示例
安装
go get github.com/oklahomer/go-sarah/v4
简单机器人示例
package main
import (
"context"
"github.com/oklahomer/go-sarah/v4"
"github.com/oklahomer/go-sarah/v4/slack"
"os"
"os/signal"
)
func main() {
// 创建上下文
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// 配置Slack适配器
slackConfig := slack.NewConfig()
slackConfig.Token = "xoxb-your-slack-token" // 替换为你的Slack token
// 创建Slack适配器
adapter, err := slack.NewAdapter(slackConfig)
if err != nil {
panic(err)
}
// 创建机器人核心
bot := sarah.NewBot(adapter)
// 注册一个简单的"ping"命令
pingCommand := &sarah.Command{
Match: func(input sarah.Input) bool {
return input.Message() == "ping"
},
Func: func(ctx context.Context, input sarah.Input) (*sarah.CommandResponse, error) {
return &sarah.CommandResponse{
Content: "pong",
}, nil
},
}
// 将命令添加到机器人
bot.AppendCommand(pingCommand)
// 启动机器人
go func() {
if err := sarah.Run(ctx, bot); err != nil {
panic(err)
}
}()
// 等待中断信号
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt)
<-sigChan
}
插件开发
go-sarah的强大之处在于其插件系统。下面是一个更复杂的插件示例:
package main
import (
"context"
"github.com/oklahomer/go-sarah/v4"
"github.com/oklahomer/go-sarah/v4/slack"
"os"
"os/signal"
"time"
)
// 定义一个天气插件
type WeatherPlugin struct{}
func (p *WeatherPlugin) Name() string {
return "weather"
}
func (p *WeatherPlugin) Match(input sarah.Input) bool {
return input.Message() == "weather"
}
func (p *WeatherPlugin) Execute(ctx context.Context, input sarah.Input) (*sarah.CommandResponse, error) {
// 这里可以调用天气API获取实时天气
return &sarah.CommandResponse{
Content: "当前天气: 晴朗, 25°C",
}, nil
}
func (p *WeatherPlugin) DefaultResponse(input sarah.Input) string {
return "输入'weather'获取天气信息"
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// 配置Slack
slackConfig := slack.NewConfig()
slackConfig.Token = "xoxb-your-slack-token"
adapter, err := slack.NewAdapter(slackConfig)
if err != nil {
panic(err)
}
bot := sarah.NewBot(adapter)
// 注册天气插件
bot.AppendCommand(&WeatherPlugin{})
// 添加定时任务
bot.Schedule(sarah.NewScheduleTask(
"morning_greeting",
"0 9 * * *", // 每天上午9点
func(_ context.Context) ([]*sarah.ScheduledTaskResult, error) {
return []*sarah.ScheduledTaskResult{
{
Content: "早上好!今天是" + time.Now().Format("2006-01-02"),
Destination: sarah.Broadcast, // 广播到所有频道
},
}, nil
},
))
go func() {
if err := sarah.Run(ctx, bot); err != nil {
panic(err)
}
}()
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt)
<-sigChan
}
配置热加载
go-sarah支持配置热加载,可以在运行时更新配置:
// 创建配置存储
storage := sarah.NewUserContextStorage(sarah.NewCacheConfig())
// 创建配置监视器
watcher, err := sarah.NewConfigWatcher(".", "*.yml", time.Minute)
if err != nil {
panic(err)
}
// 启动机器人时传入配置监视器
sarah.RunWithOptions(ctx, []sarah.Bot{bot}, sarah.WithConfigWatcher(watcher))
多平台支持
go-sarah支持多种聊天平台,只需更换适配器:
// LINE适配器示例
lineConfig := line.NewConfig()
lineConfig.ChannelSecret = "your-channel-secret"
lineConfig.ChannelToken = "your-channel-token"
adapter, err := line.NewAdapter(lineConfig)
// Gitter适配器示例
gitterConfig := gitter.NewConfig()
gitterConfig.Token = "your-gitter-token"
adapter, err := gitter.NewAdapter(gitterConfig)
最佳实践
- 错误处理:为每个插件实现健壮的错误处理
- 日志记录:使用go-sarah内置的日志接口
- 状态管理:合理使用UserContext管理会话状态
- 测试:为每个插件编写单元测试
- 性能监控:集成Prometheus等监控工具
go-sarah是一个灵活且功能丰富的框架,适合构建从简单到复杂的企业级聊天机器人应用。通过其插件系统,开发者可以轻松扩展功能,而无需修改核心代码。