metadata 是bot 的数据集,用户可以任意扩展这个结构用于适配自己的应用程序的逻辑需求。
它被bot持有,并被所有的Card引用。
// BotDat bot的metadata
type BotDat struct {
Token string
AccID string
}
// NewBotData 创建bot metadata
func NewBotData() (*BotDat, error) {
b := &BotDat{}
return b, nil
}
Card 代理了每个 http 请求,它主要被用于复用在各个策略逻辑以及不同的编排上
// LoginGuestCard 游客登录
type LoginGuestCard struct {
Base *card.Card
URL string
delay time.Duration
md *prefab.BotDat
}
// NewGuestLoginCard 生成账号创建预制
func NewGuestLoginCard(md *prefab.BotDat) *LoginGuestCard {
return &LoginGuestCard{
Base: card.NewCardWithConfig(),
URL: prefab.Urls[prefab.LoginGuest],
delay: time.Millisecond,
md: md,
}
}
func (card *LoginGuestCard) GetName() string { return prefab.LoginGuest }
func (card *LoginGuestCard) GetURL() string { return card.URL }
func (card *LoginGuestCard) GetClient() *http.Client { return nil }
func (card *LoginGuestCard) GetHeader() map[string]string { return card.Base.Header }
func (card *LoginGuestCard) GetMethod() string { return card.Base.Method }
func (card *LoginGuestCard) SetDelay(delay time.Duration) { card.delay = delay }
func (card *LoginGuestCard) GetDelay() time.Duration { return card.delay }
func (card *LoginGuestCard) Enter() []byte {
b := []byte{}
card.Base.AddInjectAssert("token assert", func() error {
return assert.NotEqual(card.md.Token, "")
})
return b
}
// Leave 反序列化返回消息
func (card *LoginGuestCard) Leave(res *http.Response) error {
var err error
var body []byte
cres := LoginGuestRes{}
body, _ = ioutil.ReadAll(res.Body)
err = json.Unmarshal(body, &cres)
if err != nil {
err = fmt.Errorf("%v json.Unmarshal err %v", card.GetURL(), err.Error())
goto EXT
}
card.md.Token = cres.Token
err = card.Base.Assert()
EXT:
return err
}
step 用于编排一段执行逻辑
例: 我们创建一个account step 他将被复用到不同的strategy中(因为登陆是每个bot必须执行的步骤
同样的我们可以编排任意多的step,用于复用在各种不同的strategy中。
step := prefab.NewStep()
# 登录
step.AddCard(NewGuestLoginCard(md))
# 获取帐号数据
aic := NewAccountGetInfoCard(md)
# 注入一个参数变量,这个注入函数会在 card.enter 头部执行
aic.AddInjectParm("Token", func()interface{} { return md.Acc.Token })
# 注入一个断言,这个断言会在 card.leave 尾部执行
aic.AddInjectAssert("account id assert",
func()error{ return assert.NotEqual(md.Acc.ID, "", errcode) },
)
step.AddCard(aic)
# ...
return step
strategy bot的创建函数,用于定制不同的策略&行为模式
func StrategyMail() *Bot {
md, _ := prefab.NewBotData()
bot := bot.New(bot.BotConfig{ ... })
// 创建一个登录步骤(这样才能将用户数据拿到本地bot的metadata中
bot.Timeline.AddStep(prefab.NewAccountLoginStep(md))
// 创建一个发送邮件的步骤 (用于测试验证mail的逻辑
bot.Timeline.AddStep(prefab.NewMailSendStep(md))
return bot
}
factory 机器人的批量创建工厂
主要用于定义bot的创建模式,运行时间,以及各种运行参数。
f , _ := factory.Create( opts ... )
f.Append("strategy_mail", StrategyMail)
// ...
defer f.Close()
f.Run()