修复当bot在线的情况下执行热登录,会开启多次事件监听 🐛

This commit is contained in:
eatmoreapple 2021-08-01 00:51:52 +08:00
parent 825dc51bf9
commit 67b71542c8
3 changed files with 65 additions and 362 deletions

13
bot.go
View File

@ -5,6 +5,7 @@ import (
"errors" "errors"
"log" "log"
"net/url" "net/url"
"sync"
) )
type Bot struct { type Bot struct {
@ -14,7 +15,8 @@ type Bot struct {
UUIDCallback func(uuid string) // 获取UUID的回调函数 UUIDCallback func(uuid string) // 获取UUID的回调函数
MessageHandler MessageHandler // 获取消息成功的handle MessageHandler MessageHandler // 获取消息成功的handle
GetMessageErrorHandler func(err error) // 获取消息发生错误的handle GetMessageErrorHandler func(err error) // 获取消息发生错误的handle
isHot bool isHot bool // 是否为热登录模式
once sync.Once
err error err error
context context.Context context context.Context
cancel context.CancelFunc cancel context.CancelFunc
@ -56,6 +58,9 @@ func (b *Bot) GetCurrentUser() (*Self, error) {
// err := bot.HotLogin(storage, true) // err := bot.HotLogin(storage, true)
// fmt.Println(err) // fmt.Println(err)
func (b *Bot) HotLogin(storage HotReloadStorage, retry ...bool) error { func (b *Bot) HotLogin(storage HotReloadStorage, retry ...bool) error {
if b.Alive() {
b.cancel()
}
b.isHot = true b.isHot = true
b.hotReloadStorage = storage b.hotReloadStorage = storage
@ -201,14 +206,16 @@ func (b *Bot) webInit() error {
return err return err
} }
// 开启协程,轮询获取是否有新的消息返回 // 开启协程,轮询获取是否有新的消息返回
go func() {
// FIX: 当bot在线的情况下执行热登录,会开启多次事件监听
go b.once.Do(func() {
if b.GetMessageErrorHandler == nil { if b.GetMessageErrorHandler == nil {
b.GetMessageErrorHandler = b.stopAsyncCALL b.GetMessageErrorHandler = b.stopAsyncCALL
} }
if err = b.asyncCall(); err != nil { if err = b.asyncCall(); err != nil {
b.GetMessageErrorHandler(err) b.GetMessageErrorHandler(err)
} }
}() })
return nil return nil
} }

View File

@ -1,218 +1,29 @@
package openwechat package openwechat
import ( import (
"os"
"testing" "testing"
"time"
) )
func defaultBot(modes ...mode) *Bot { func TestLogin(t *testing.T) {
bot := DefaultBot(modes...) bot := DefaultBot(Desktop)
bot.UUIDCallback = PrintlnQrcodeUrl bot.LoginCallBack = func(body []byte) {
return bot t.Log("login success")
}
func getSelf(modes ...mode) (*Self, error) {
bot := defaultBot(modes...)
if err := bot.Login(); err != nil {
return nil, err
}
return bot.GetCurrentUser()
}
func TestBotLogin(t *testing.T) {
bot := defaultBot()
if err := bot.Login(); err != nil {
t.Error(err)
return
}
self, err := bot.GetCurrentUser()
if err != nil {
t.Error(err)
return
}
t.Log(self.NickName)
}
func TestMessage(t *testing.T) {
bot := defaultBot()
bot.MessageHandler = func(msg *Message) {
t.Log(msg.MsgType)
t.Log(msg.Content)
if msg.IsMedia() {
t.Log(msg.Content)
t.Log(msg.FileName)
}
if msg.IsCard() {
c, _ := msg.Card()
t.Log(c.Alias)
}
if msg.IsSystem() {
t.Log(msg.Content)
}
if msg.IsRecalled() {
t.Log(msg.Content)
}
} }
if err := bot.Login(); err != nil { if err := bot.Login(); err != nil {
t.Error(err) t.Error(err)
return
}
bot.Block()
}
func TestFriend(t *testing.T) {
self, err := getSelf()
if err != nil {
t.Error(err)
return
}
friends, err := self.Friends()
if err != nil {
t.Error(err)
return
}
t.Log(friends)
}
func TestGroup(t *testing.T) {
self, err := getSelf()
if err != nil {
t.Error(err)
return
}
group, err := self.Groups()
if err != nil {
t.Error(err)
return
}
t.Log(group)
g := group.SearchByNickName(1, "杭州Gopher群组")
if g.First() != nil {
members, err := g.First().Members()
if err != nil {
t.Error(err)
return
}
t.Log(members.Count())
}
}
func TestMps(t *testing.T) {
self, err := getSelf()
if err != nil {
t.Error(err)
return
}
mps, err := self.Mps()
if err != nil {
t.Error(err)
return
}
t.Log(mps)
}
func TestAddFriendIntoChatRoom(t *testing.T) {
self, err := getSelf(Desktop)
if err != nil {
t.Error(err)
return
}
groups, err := self.Groups()
if err != nil {
t.Error(err)
return
}
friends, err := self.Friends()
if err != nil {
t.Error(err)
return
}
searchGroups := groups.SearchByNickName(1, "厉害了")
if g := searchGroups.First(); g != nil {
addFriends := friends.SearchByRemarkName(1, "1")
if err := g.AddFriendsIn(addFriends...); err != nil {
t.Error(err)
}
}
}
func TestRemoveFriendIntoChatRoom(t *testing.T) {
self, err := getSelf()
if err != nil {
t.Error(err)
return
}
groups, err := self.Groups()
if err != nil {
t.Error(err)
return
}
friends, err := self.Friends()
if err != nil {
t.Error(err)
return
}
searchGroups := groups.SearchByNickName(1, "厉害了")
if g := searchGroups.First(); g != nil {
addFriends := friends.SearchByRemarkName(1, "大爷")
if f := addFriends.First(); f != nil {
if err := g.RemoveMembers(Members{f.User}); err != nil {
t.Error(err)
}
}
} }
} }
func TestLogout(t *testing.T) { func TestLogout(t *testing.T) {
bot := defaultBot(Desktop) bot := DefaultBot(Desktop)
bot.LoginCallBack = func(body []byte) {
t.Log("login success")
}
bot.LogoutCallBack = func(bot *Bot) {
t.Log("logout")
}
bot.MessageHandler = func(msg *Message) { bot.MessageHandler = func(msg *Message) {
if msg.Content == "logout" { if msg.IsText() && msg.Content == "logout" {
msg.Bot.Logout()
}
}
if err := bot.Login(); err != nil {
t.Error(err)
return
}
bot.Block()
}
func TestSendMessage(t *testing.T) {
bot := defaultBot(Desktop)
if err := bot.Login(); err != nil {
t.Error(err)
return
}
self, err := bot.GetCurrentUser()
if err != nil {
t.Error(err)
return
}
helper, err := self.FileHelper()
if err != nil {
t.Error(err)
return
}
if _, err = helper.SendText("test message! received ?"); err != nil {
t.Error(err)
return
}
time.Sleep(time.Second)
if _, err = self.SendTextToFriend(helper, "send test message twice ! received?"); err != nil {
t.Error(err)
return
}
}
func TestAgreeFriendsAdd(t *testing.T) {
bot := defaultBot()
bot.MessageHandler = func(msg *Message) {
msg.Sender()
if msg.IsFriendAdd() {
if err := msg.Agree(); err != nil {
t.Error(err)
}
bot.Logout() bot.Logout()
} }
} }
@ -223,155 +34,54 @@ func TestAgreeFriendsAdd(t *testing.T) {
bot.Block() bot.Block()
} }
func TestHotLogin(t *testing.T) { func TestMessageHandle(t *testing.T) {
filename := "test.json" bot := DefaultBot(Desktop)
bot := defaultBot() bot.MessageHandler = func(msg *Message) {
s := NewJsonFileHotReloadStorage(filename) if msg.IsText() && msg.Content == "ping" {
if err := bot.HotLogin(s); err != nil { msg.ReplyText("pong")
t.Error(err)
return
}
self, err := bot.GetCurrentUser()
if err != nil {
t.Error(err)
return
}
t.Log(self.NickName)
}
func TestFriendHelper(t *testing.T) {
bot := defaultBot(Desktop)
if err := bot.HotLogin(NewJsonFileHotReloadStorage("2.json"), true); err != nil {
t.Error(err)
return
}
self, err := bot.GetCurrentUser()
if err != nil {
t.Error(err)
return
}
fh, err := self.FileHelper()
if err != nil {
t.Error(err)
return
}
f, _ := os.Open("run")
defer f.Close()
msg, err := fh.SendFile(f)
if err != nil {
t.Error(err)
return
}
t.Log(msg.MsgId)
}
func TestRevokeMessage(t *testing.T) {
bot := defaultBot(Desktop)
if err := bot.HotLogin(NewJsonFileHotReloadStorage("2.json")); err != nil {
t.Error(err)
return
}
self, err := bot.GetCurrentUser()
if err != nil {
t.Error(err)
return
}
friends, err := self.Friends()
if err != nil {
t.Error(err)
return
}
fs := friends.SearchByRemarkName(1, "1")
ms, err := fs.First().SendText("test")
if err != nil {
t.Error(err)
return
}
time.Sleep(time.Second)
if err := ms.Revoke(); err != nil {
t.Error(err)
}
}
func TestSendFile(t *testing.T) {
bot := defaultBot(Desktop)
if err := bot.HotLogin(NewJsonFileHotReloadStorage("2.json"), true); err != nil {
t.Error(err)
return
}
self, err := bot.GetCurrentUser()
if err != nil {
t.Error(err)
return
}
fh, err := self.FileHelper()
if err != nil {
t.Error(err)
return
}
f, _ := os.Open("README.md")
defer f.Close()
msg, err := fh.SendFile(f)
if err != nil {
t.Error(err)
return
}
t.Log(msg.MsgId)
}
func TestForwardMessage(t *testing.T) {
bot := defaultBot(Desktop)
if err := bot.HotLogin(NewJsonFileHotReloadStorage("2.json"), true); err != nil {
t.Error(err)
return
}
self, err := bot.GetCurrentUser()
if err != nil {
t.Error(err)
return
}
groups, err := self.Groups()
if err != nil {
t.Error(err)
return
}
f, _ := os.Open("README.md")
defer f.Close()
sentM, err := self.SendFileToGroup(groups.First(), f)
if err != nil {
t.Log(err)
return
}
self.ForwardMessageToGroups(sentM, groups...)
}
func TestMessageMatchDispatcher(t *testing.T) {
dispatcher := NewMessageMatchDispatcher()
m1 := func(ctx *MessageContext) {
if ctx.Content == "ping" {
ctx.ReplyText("pong")
}
ctx.Next()
t.Log("处理完毕~")
}
m2 := func(ctx *MessageContext) {
if ctx.Content == "hello" {
ctx.ReplyText("world")
} }
} }
dispatcher.OnText(m1, m2)
dispatcher.OnFriendByRemarkName("1", func(ctx *MessageContext) { ctx.ReplyText("我收到了你的信息了") })
bot := defaultBot(Desktop)
bot.MessageHandler = DispatchMessage(dispatcher)
if err := bot.Login(); err != nil { if err := bot.Login(); err != nil {
t.Error(err) t.Error(err)
return return
} }
bot.Block() bot.Block()
} }
func TestFriends(t *testing.T) {
bot := DefaultBot(Desktop)
if err := bot.Login(); err != nil {
t.Error(err)
return
}
user, err := bot.GetCurrentUser()
if err != nil {
t.Error(err)
return
}
friends, err := user.Friends()
if err != nil {
t.Error(err)
return
}
t.Log(friends)
}
func TestGroups(t *testing.T) {
bot := DefaultBot(Desktop)
if err := bot.Login(); err != nil {
t.Error(err)
return
}
user, err := bot.GetCurrentUser()
if err != nil {
t.Error(err)
return
}
groups, err := user.Groups()
if err != nil {
t.Error(err)
return
}
t.Log(groups)
}

View File

@ -9,20 +9,6 @@ func TestFormatEmoji(t *testing.T) {
t.Log(FormatEmoji(`多吃点苹果<span class="emoji emoji1f34f"></span>高兴<span class="emoji emoji1f604"></span><span class="emoji emoji1f604"></span><span class="emoji emoji1f604"></span> 生气<span class="emoji emoji1f64e"></span> 点赞<span class="emoji emoji1f44d"></span>`)) t.Log(FormatEmoji(`多吃点苹果<span class="emoji emoji1f34f"></span>高兴<span class="emoji emoji1f604"></span><span class="emoji emoji1f604"></span><span class="emoji emoji1f604"></span> 生气<span class="emoji emoji1f64e"></span> 点赞<span class="emoji emoji1f44d"></span>`))
} }
func TestSendEmoji(t *testing.T) {
self, err := getSelf()
if err != nil {
t.Error(err)
return
}
f, err := self.FileHelper()
if err != nil {
t.Error(err)
return
}
_, _ = f.SendText(Emoji.Dagger)
}
func BenchmarkFormatEmojiString(b *testing.B) { func BenchmarkFormatEmojiString(b *testing.B) {
str := `多吃点苹果<span class="emoji emoji1f34f"></span>高兴<span class="emoji emoji1f604"></span><span class="emoji emoji1f604"></span><span class="emoji emoji1f604"></span> 生气<span class="emoji emoji1f64e"></span> 点赞<span class="emoji emoji1f44d"></span>` str := `多吃点苹果<span class="emoji emoji1f34f"></span>高兴<span class="emoji emoji1f604"></span><span class="emoji emoji1f604"></span><span class="emoji emoji1f604"></span> 生气<span class="emoji emoji1f64e"></span> 点赞<span class="emoji emoji1f44d"></span>`
b.SetBytes(int64(len(str))) b.SetBytes(int64(len(str)))