🚚 ⬆️ 📝 🔥 🎨 迁移 ctrl, utils

This commit is contained in:
fumiama 2022-01-11 11:40:33 +08:00
parent 4ac1674cc0
commit 0185d0c730
95 changed files with 146 additions and 2449 deletions

View File

@ -45,7 +45,7 @@ zerobot [-h] [-t token] [-u url] [-n nickname] [-p prefix] [-d|w] [-g 监听地
## 功能
> 在编译时,以下功能除插件控制外,均可通过注释`main.go`中的相应`import`而物理禁用,减小插件体积。
> 通过插件控制,还可动态管理某个功能在某个群的打开/关闭。
- **web管理** `import _ "github.com/FloatTech/ZeroBot-Plugin/control/web"`
- **web管理** `import _ "github.com/FloatTech/zbpctrl/web"`
- 开启后可执行文件大约增加 5M ,默认注释不开启。如需开启请自行编辑`main.go`取消注释
- 需要配合 [webgui](https://github.com/FloatTech/bot-manager) 使用
- **动态加载插件** `import _ github.com/FloatTech/ZeroBot-Plugin-Dynamic/dyloader`

View File

@ -1,94 +0,0 @@
package control
import (
"encoding/binary"
"strings"
"time"
b14 "github.com/fumiama/go-base16384"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
)
var startTime int64
func init() {
// 插件冲突检测 会在本群发送一条消息并在约 1s 后撤回
zero.OnFullMatch("插件冲突检测", zero.OnlyGroup, zero.AdminPermission, zero.OnlyToMe).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
tok, err := genToken()
if err != nil {
return
}
t := message.Text("●cd" + tok)
startTime = time.Now().Unix()
id := ctx.SendChain(t)
process.SleepAbout1sTo2s()
ctx.DeleteMessage(id)
})
zero.OnRegex("^●cd([\u4e00-\u8e00]{4})$", zero.OnlyGroup).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
if isValidToken(ctx.State["regex_matched"].([]string)[1]) {
msg := ""
gid := ctx.Event.GroupID
ForEach(func(key string, manager *Control) bool {
if manager.IsEnabledIn(gid) {
msg += "\xfe\xff" + key
}
return true
})
if len(msg) > 2 {
my, err := b14.UTF16be2utf8(b14.EncodeString(msg[2:]))
mys := "●cd●" + helper.BytesToString(my)
if err == nil {
id := ctx.SendChain(message.Text(mys))
process.SleepAbout1sTo2s()
ctx.DeleteMessage(id)
}
}
}
})
zero.OnRegex("^●cd●(([\u4e00-\u8e00]*[\u3d01-\u3d06]?))", zero.OnlyGroup).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
if time.Now().Unix()-startTime < 10 {
msg, err := b14.UTF82utf16be(helper.StringToBytes(ctx.State["regex_matched"].([]string)[1]))
if err == nil {
gid := ctx.Event.GroupID
for _, s := range strings.Split(b14.DecodeString(msg), "\xfe\xff") {
mu.RLock()
c, ok := managers[s]
mu.RUnlock()
if ok && c.IsEnabledIn(gid) {
c.Disable(gid)
}
}
}
}
})
}
func genToken() (tok string, err error) {
timebytes := make([]byte, 8)
binary.BigEndian.PutUint64(timebytes, uint64(time.Now().Unix()))
timebytes, err = b14.UTF16be2utf8(b14.Encode(timebytes[1:]))
if err == nil {
tok = helper.BytesToString(timebytes)
}
return
}
func isValidToken(tok string) (yes bool) {
s, err := b14.UTF82utf16be(helper.StringToBytes(tok))
if err == nil {
timebytes := make([]byte, 1, 8)
timebytes = append(timebytes, b14.Decode(s)...)
yes = math.Abs64(time.Now().Unix()-int64(binary.BigEndian.Uint64(timebytes))) < 10
}
return
}

View File

@ -1,19 +0,0 @@
package control
import "testing"
func TestGenToken(t *testing.T) {
tok, err := genToken()
if err == nil {
t.Log(tok)
t.Log(isValidToken(tok))
t.Fail()
} else {
t.Fatal(err)
}
}
func TestMaru(t *testing.T) {
t.Log(len("\xff"))
t.Fail()
}

View File

@ -1,31 +0,0 @@
package control
import (
zero "github.com/wdvxdr1123/ZeroBot"
)
var enmap = make(map[string]*zero.Engine)
// Register 注册插件控制器
func Register(service string, o *Options) *zero.Engine {
engine := zero.New()
engine.UsePreHandler(newctrl(service, o).Handler)
enmap[service] = engine
return engine
}
// Delete 删除插件控制器,不会删除数据
func Delete(service string) {
engine, ok := enmap[service]
if ok {
engine.Delete()
mu.RLock()
_, ok = managers[service]
mu.RUnlock()
if ok {
mu.Lock()
delete(managers, service)
mu.Unlock()
}
}
}

View File

@ -1,502 +0,0 @@
// Package control 控制插件的启用与优先级等
package control
import (
"crypto/md5"
"encoding/binary"
"fmt"
"os"
"strconv"
"strings"
"sync"
log "github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
"github.com/FloatTech/ZeroBot-Plugin/utils/txt2img"
)
var (
db = &sql.Sqlite{DBPath: "data/control/plugins.db"}
// managers 每个插件对应的管理
managers = map[string]*Control{}
mu = sync.RWMutex{}
hasinit bool
)
// Control is to control the plugins.
type Control struct {
sync.RWMutex
service string
options Options
}
// newctrl returns Manager with settings.
func newctrl(service string, o *Options) *Control {
m := &Control{service: service,
options: func() Options {
if o == nil {
return Options{}
}
return *o
}(),
}
mu.Lock()
managers[service] = m
mu.Unlock()
err := db.Create(service, &grpcfg{})
if err != nil {
panic(err)
}
err = db.Create(service+"ban", &ban{})
if err != nil {
panic(err)
}
return m
}
// Enable enables a group to pass the Manager.
// groupID == 0 (ALL) will operate on all grps.
func (m *Control) Enable(groupID int64) {
var c grpcfg
m.RLock()
err := db.Find(m.service, &c, "WHERE gid = "+strconv.FormatInt(groupID, 10))
m.RUnlock()
if err != nil {
c.GroupID = groupID
}
c.Disable = int64(uint64(c.Disable) & 0xffffffff_fffffffe)
m.Lock()
err = db.Insert(m.service, &c)
m.Unlock()
if err != nil {
log.Errorf("[control] %v", err)
}
}
// Disable disables a group to pass the Manager.
// groupID == 0 (ALL) will operate on all grps.
func (m *Control) Disable(groupID int64) {
var c grpcfg
m.RLock()
err := db.Find(m.service, &c, "WHERE gid = "+strconv.FormatInt(groupID, 10))
m.RUnlock()
if err != nil {
c.GroupID = groupID
}
c.Disable |= 1
m.Lock()
err = db.Insert(m.service, &c)
m.Unlock()
if err != nil {
log.Errorf("[control] %v", err)
}
}
// Reset resets the default config of a group.
// groupID == 0 (ALL) is not allowed.
func (m *Control) Reset(groupID int64) {
if groupID != 0 {
m.Lock()
err := db.Del(m.service, "WHERE gid = "+strconv.FormatInt(groupID, 10))
m.Unlock()
if err != nil {
log.Errorf("[control] %v", err)
}
}
}
// IsEnabledIn 开启群
func (m *Control) IsEnabledIn(gid int64) bool {
var c grpcfg
var err error
log.Debugln("[control] IsEnabledIn recv gid =", gid)
if gid != 0 {
m.RLock()
err = db.Find(m.service, &c, "WHERE gid = "+strconv.FormatInt(gid, 10))
m.RUnlock()
if err == nil && gid == c.GroupID {
log.Debugf("[control] plugin %s of grp %d : %d", m.service, c.GroupID, c.Disable&1)
return c.Disable&1 == 0
}
}
m.RLock()
err = db.Find(m.service, &c, "WHERE gid = 0")
m.RUnlock()
if err == nil && c.GroupID == 0 {
log.Debugf("[control] plugin %s of all : %d", m.service, c.Disable&1)
return c.Disable&1 == 0
}
return !m.options.DisableOnDefault
}
// Ban 禁止某人在某群使用本插件
func (m *Control) Ban(uid, gid int64) {
var err error
var digest [16]byte
log.Debugln("[control] Ban recv gid =", gid, "uid =", uid)
if gid != 0 { // 特定群
digest = md5.Sum(helper.StringToBytes(fmt.Sprintf("%d_%d", uid, gid)))
m.RLock()
err = db.Insert(m.service+"ban", &ban{ID: int64(binary.LittleEndian.Uint64(digest[:8])), UserID: uid, GroupID: gid})
m.RUnlock()
if err == nil {
log.Debugf("[control] plugin %s is banned in grp %d for usr %d.", m.service, gid, uid)
return
}
}
// 所有群
digest = md5.Sum(helper.StringToBytes(fmt.Sprintf("%d_all", uid)))
m.RLock()
err = db.Insert(m.service+"ban", &ban{ID: int64(binary.LittleEndian.Uint64(digest[:8])), UserID: uid, GroupID: 0})
m.RUnlock()
if err == nil {
log.Debugf("[control] plugin %s is banned in all grp for usr %d.", m.service, uid)
}
}
// Permit 允许某人在某群使用本插件
func (m *Control) Permit(uid, gid int64) {
var digest [16]byte
log.Debugln("[control] Permit recv gid =", gid, "uid =", uid)
if gid != 0 { // 特定群
digest = md5.Sum(helper.StringToBytes(fmt.Sprintf("%d_%d", uid, gid)))
m.RLock()
_ = db.Del(m.service+"ban", "WHERE id = "+strconv.FormatInt(int64(binary.LittleEndian.Uint64(digest[:8])), 10))
m.RUnlock()
log.Debugf("[control] plugin %s is permitted in grp %d for usr %d.", m.service, gid, uid)
return
}
// 所有群
digest = md5.Sum(helper.StringToBytes(fmt.Sprintf("%d_all", uid)))
m.RLock()
_ = db.Del(m.service+"ban", "WHERE id = "+strconv.FormatInt(int64(binary.LittleEndian.Uint64(digest[:8])), 10))
m.RUnlock()
log.Debugf("[control] plugin %s is permitted in all grp for usr %d.", m.service, uid)
}
// IsBannedIn 某人是否在某群被 ban
func (m *Control) IsBannedIn(uid, gid int64) bool {
var b ban
var err error
var digest [16]byte
log.Debugln("[control] IsBannedIn recv gid =", gid, "uid =", uid)
if gid != 0 {
digest = md5.Sum(helper.StringToBytes(fmt.Sprintf("%d_%d", uid, gid)))
m.RLock()
err = db.Find(m.service+"ban", &b, "WHERE id = "+strconv.FormatInt(int64(binary.LittleEndian.Uint64(digest[:8])), 10))
m.RUnlock()
if err == nil && gid == b.GroupID && uid == b.UserID {
log.Debugf("[control] plugin %s is banned in grp %d for usr %d.", m.service, b.GroupID, b.UserID)
return true
}
}
digest = md5.Sum(helper.StringToBytes(fmt.Sprintf("%d_all", uid)))
m.RLock()
err = db.Find(m.service+"ban", &b, "WHERE id = "+strconv.FormatInt(int64(binary.LittleEndian.Uint64(digest[:8])), 10))
m.RUnlock()
if err == nil && b.GroupID == 0 && uid == b.UserID {
log.Debugf("[control] plugin %s is banned in all grp for usr %d.", m.service, b.UserID)
return true
}
return false
}
// GetData 获取某个群的 63 字节配置信息
func (m *Control) GetData(gid int64) int64 {
var c grpcfg
var err error
log.Debugln("[control] IsEnabledIn recv gid =", gid)
m.RLock()
err = db.Find(m.service, &c, "WHERE gid = "+strconv.FormatInt(gid, 10))
m.RUnlock()
if err == nil && gid == c.GroupID {
log.Debugf("[control] plugin %s of grp %d : 0x%x", m.service, c.GroupID, c.Disable>>1)
return c.Disable >> 1
}
return 0
}
// SetData 为某个群设置低 63 位配置数据
func (m *Control) SetData(groupID int64, data int64) error {
var c grpcfg
m.RLock()
err := db.Find(m.service, &c, "WHERE gid = "+strconv.FormatInt(groupID, 10))
m.RUnlock()
if err != nil {
c.GroupID = groupID
if m.options.DisableOnDefault {
c.Disable = 1
}
}
c.Disable &= 1
c.Disable |= data << 1
log.Debugf("[control] set plugin %s of grp %d : 0x%x", m.service, c.GroupID, data)
m.Lock()
err = db.Insert(m.service, &c)
m.Unlock()
if err != nil {
log.Errorf("[control] %v", err)
}
return err
}
// Handler 返回 预处理器
func (m *Control) Handler(ctx *zero.Ctx) bool {
ctx.State["manager"] = m
grp := ctx.Event.GroupID
if grp == 0 {
// 个人用户
return m.IsEnabledIn(-ctx.Event.UserID)
}
log.Debugln("[control] handler get gid =", grp)
return m.IsEnabledIn(grp) && !m.IsBannedIn(ctx.Event.UserID, grp)
}
// Lookup returns a Manager by the service name, if
// not exist, it will return nil.
func Lookup(service string) (*Control, bool) {
mu.RLock()
m, ok := managers[service]
mu.RUnlock()
return m, ok
}
// ForEach iterates through managers.
func ForEach(iterator func(key string, manager *Control) bool) {
mu.RLock()
m := copyMap(managers)
mu.RUnlock()
for k, v := range m {
if !iterator(k, v) {
return
}
}
}
func copyMap(m map[string]*Control) map[string]*Control {
ret := make(map[string]*Control, len(m))
for k, v := range m {
ret[k] = v
}
return ret
}
func userOrGrpAdmin(ctx *zero.Ctx) bool {
if zero.OnlyGroup(ctx) {
return zero.AdminPermission(ctx)
}
return zero.OnlyToMe(ctx)
}
func init() {
if !hasinit {
mu.Lock()
if !hasinit {
err := os.MkdirAll("data/control", 0755)
if err != nil {
panic(err)
} else {
hasinit = true
zero.OnCommandGroup([]string{
"启用", "enable", "禁用", "disable",
}, userOrGrpAdmin).SetBlock(true).FirstPriority().Handle(func(ctx *zero.Ctx) {
model := extension.CommandModel{}
_ = ctx.Parse(&model)
service, ok := Lookup(model.Args)
if !ok {
ctx.SendChain(message.Text("没有找到指定服务!"))
return
}
grp := ctx.Event.GroupID
if grp == 0 {
// 个人用户
grp = -ctx.Event.UserID
}
if strings.Contains(model.Command, "启用") || strings.Contains(model.Command, "enable") {
service.Enable(grp)
ctx.SendChain(message.Text("已启用服务: " + model.Args))
} else {
service.Disable(grp)
ctx.SendChain(message.Text("已禁用服务: " + model.Args))
}
})
zero.OnCommandGroup([]string{
"全局启用", "enableall", "全局禁用", "disableall",
}, zero.OnlyToMe, zero.SuperUserPermission).SetBlock(true).FirstPriority().Handle(func(ctx *zero.Ctx) {
model := extension.CommandModel{}
_ = ctx.Parse(&model)
service, ok := Lookup(model.Args)
if !ok {
ctx.SendChain(message.Text("没有找到指定服务!"))
return
}
if strings.Contains(model.Command, "启用") || strings.Contains(model.Command, "enable") {
service.Enable(0)
ctx.SendChain(message.Text("已全局启用服务: " + model.Args))
} else {
service.Disable(0)
ctx.SendChain(message.Text("已全局禁用服务: " + model.Args))
}
})
zero.OnCommandGroup([]string{"还原", "reset"}, userOrGrpAdmin).SetBlock(true).FirstPriority().Handle(func(ctx *zero.Ctx) {
model := extension.CommandModel{}
_ = ctx.Parse(&model)
service, ok := Lookup(model.Args)
if !ok {
ctx.SendChain(message.Text("没有找到指定服务!"))
return
}
grp := ctx.Event.GroupID
if grp == 0 {
// 个人用户
grp = -ctx.Event.UserID
}
service.Reset(grp)
ctx.SendChain(message.Text("已还原服务的默认启用状态: " + model.Args))
})
zero.OnCommandGroup([]string{
"禁止", "ban", "允许", "permit",
}, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).FirstPriority().Handle(func(ctx *zero.Ctx) {
model := extension.CommandModel{}
_ = ctx.Parse(&model)
args := strings.Split(model.Args, " ")
if len(args) >= 2 {
service, ok := Lookup(args[0])
if !ok {
ctx.SendChain(message.Text("没有找到指定服务!"))
return
}
grp := ctx.Event.GroupID
msg := "**" + args[0] + "报告**"
if strings.Contains(model.Command, "允许") || strings.Contains(model.Command, "permit") {
for _, usr := range args[1:] {
uid, err := strconv.ParseInt(usr, 10, 64)
if err == nil {
service.Permit(uid, grp)
msg += "\n+ 已允许" + usr
}
}
} else {
for _, usr := range args[1:] {
uid, err := strconv.ParseInt(usr, 10, 64)
if err == nil {
service.Ban(uid, grp)
msg += "\n- 已禁止" + usr
}
}
}
ctx.SendChain(message.Text(msg))
return
}
ctx.SendChain(message.Text("参数错误!"))
})
zero.OnCommandGroup([]string{
"全局禁止", "banall", "全局允许", "permitall",
}, zero.OnlyGroup, zero.SuperUserPermission).SetBlock(true).FirstPriority().Handle(func(ctx *zero.Ctx) {
model := extension.CommandModel{}
_ = ctx.Parse(&model)
args := strings.Split(model.Args, " ")
if len(args) >= 2 {
service, ok := Lookup(args[0])
if !ok {
ctx.SendChain(message.Text("没有找到指定服务!"))
return
}
msg := "**" + args[0] + "全局报告**"
if strings.Contains(model.Command, "允许") || strings.Contains(model.Command, "permit") {
for _, usr := range args[1:] {
uid, err := strconv.ParseInt(usr, 10, 64)
if err == nil {
service.Permit(uid, 0)
msg += "\n+ 已允许" + usr
}
}
} else {
for _, usr := range args[1:] {
uid, err := strconv.ParseInt(usr, 10, 64)
if err == nil {
service.Ban(uid, 0)
msg += "\n- 已禁止" + usr
}
}
}
ctx.SendChain(message.Text(msg))
return
}
ctx.SendChain(message.Text("参数错误!"))
})
zero.OnCommandGroup([]string{"用法", "usage"}, userOrGrpAdmin).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
model := extension.CommandModel{}
_ = ctx.Parse(&model)
service, ok := Lookup(model.Args)
if !ok {
ctx.SendChain(message.Text("没有找到指定服务!"))
return
}
if service.options.Help != "" {
ctx.SendChain(message.Text(service.options.Help))
} else {
ctx.SendChain(message.Text("该服务无帮助!"))
}
})
zero.OnCommandGroup([]string{"服务列表", "service_list"}, userOrGrpAdmin).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
msg := "--------服务列表--------\n发送\"/用法 name\"查看详情"
i := 0
gid := ctx.Event.GroupID
ForEach(func(key string, manager *Control) bool {
i++
msg += "\n" + strconv.Itoa(i) + `: `
if manager.IsEnabledIn(gid) {
msg += "●" + key
} else {
msg += "○" + key
}
return true
})
ctx.SendChain(message.Text(msg))
})
zero.OnCommandGroup([]string{"服务详情", "service_detail"}, userOrGrpAdmin).SetBlock(true).FirstPriority().
Handle(func(ctx *zero.Ctx) {
text := "---服务详情---\n"
i := 0
ForEach(func(key string, manager *Control) bool {
service, _ := Lookup(key)
help := service.options.Help
i++
msg := strconv.Itoa(i) + `: `
if manager.IsEnabledIn(ctx.Event.GroupID) {
msg += "●" + key
} else {
msg += "○" + key
}
msg += "\n" + help
text += msg + "\n\n"
return true
})
data, err := txt2img.RenderToBase64(text, 40, 20)
if err != nil {
log.Errorf("[control] %v", err)
}
if id := ctx.SendChain(message.Image("base64://" + helper.BytesToString(data))); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
}
})
}
}
mu.Unlock()
}
}

View File

@ -1,19 +0,0 @@
package control
// grpcfg holds the group config for the Manager.
type grpcfg struct {
GroupID int64 `db:"gid"` // GroupID 群号
Disable int64 `db:"disable"` // Disable 默认启用该插件
}
type ban struct {
ID int64 `db:"id"`
UserID int64 `db:"uid"`
GroupID int64 `db:"gid"`
}
// Options holds the optional parameters for the Manager.
type Options struct {
DisableOnDefault bool
Help string // 帮助文本信息
}

View File

@ -1,561 +0,0 @@
// Package webctrl 包含 webui 所需的所有内容
package webctrl
import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"strconv"
"sync"
manager "github.com/FloatTech/bot-manager"
// 依赖gin监听server
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
// 前端静态文件
log "github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
ctrl "github.com/FloatTech/ZeroBot-Plugin/control"
)
var (
// 向前端推送消息的ws链接
conn *websocket.Conn
// 向前端推送日志的ws链接
logConn *websocket.Conn
l logWriter
// 存储请求事件flag作为键一个request对象作为值
requestData sync.Map
)
// logWriter
// @Description:
//
type logWriter struct {
}
// request
// @Description: 一个请求事件的结构体
//
type request struct {
RequestType string `json:"request_type"`
SubType string `json:"sub_type"`
Type string `json:"type"`
Comment string `json:"comment"`
GroupID int64 `json:"group_id"`
UserID int64 `json:"user_id"`
Flag string `json:"flag"`
SelfID int64 `json:"self_id"`
}
// InitGui 初始化gui
func InitGui(addr string) {
// 将日志重定向到前端hook
writer := io.MultiWriter(l, os.Stdout)
log.SetOutput(writer)
// 监听后端
go controller(addr)
// 注册消息handle
messageHandle()
}
// websocket的协议升级
var upGrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
func controller(addr string) {
defer func() {
err := recover()
if err != nil {
log.Errorln("[gui]" + "bot-manager出现不可恢复的错误")
log.Errorln("[gui]", err)
}
}()
engine := gin.New()
// 支持跨域
engine.Use(cors())
// 注册静态文件
engine.StaticFS("/dist", http.FS(manager.Dist))
engine.POST("/get_bots", getBots)
engine.POST("/get_group_list", getGroupList)
engine.POST("/get_friend_list", getFriendList)
// 注册主路径路由,使其跳转到主页面
engine.GET("/", func(context *gin.Context) {
context.Redirect(http.StatusMovedPermanently, "/dist/dist/default.html")
})
// 更改某个插件状态
engine.POST("/update_plugin_status", updatePluginStatus)
// 更改某一个插件在所有群的状态
engine.POST("/update_plugin_all_group_status", updatePluginAllGroupStatus)
// 更改所有插件状态
engine.POST("/update_all_plugin_status", updateAllPluginStatus)
// 获取所有插件状态
engine.POST("/get_plugins_status", getPluginsStatus)
// 获取一个插件状态
engine.POST("/get_plugin_status", getPluginStatus)
// 获取插件列表
engine.POST("/get_plugins", func(context *gin.Context) {
var datas []map[string]interface{}
ctrl.ForEach(func(key string, manager *ctrl.Control) bool {
datas = append(datas, map[string]interface{}{"id": 1, "handle_type": "", "name": key, "enable": manager.IsEnabledIn(0)})
return true
})
context.JSON(200, datas)
})
// 获取所有请求
engine.POST("/get_requests", getRequests)
// 执行一个请求事件
engine.POST("handle_request", handelRequest)
// 链接日志
engine.GET("/get_log", getLogs)
// 获取前端标签
engine.GET("/get_label", func(context *gin.Context) {
context.JSON(200, "ZeroBot-Plugin")
})
// 发送信息
engine.POST("/send_msg", sendMsg)
engine.GET("/data", upgrade)
log.Infoln("[gui] the webui is running on", addr)
log.Infoln("[gui] ", "you input the `ZeroBot-Plugin.exe -g` can disable the gui")
if err := engine.Run(addr); err != nil {
log.Debugln("[gui] ", err.Error())
}
}
// handelRequest
/**
* @Description: 处理一个请求
* @param context
*/
func handelRequest(context *gin.Context) {
var data map[string]interface{}
err := context.BindJSON(&data)
if err != nil {
context.JSON(404, nil)
return
}
r, ok := requestData.LoadAndDelete(data["flag"].(string))
if !ok {
context.JSON(404, "flag not found")
}
r2 := r.(*request)
r2.handle(data["approve"].(bool), data["reason"].(string))
context.JSON(200, "操作成功")
}
// getRequests
/**
* @Description: 获取所有的请求
* @param context
*/
func getRequests(context *gin.Context) {
var data []interface{}
requestData.Range(func(key, value interface{}) bool {
data = append(data, value)
return true
})
context.JSON(200, data)
}
// updateAllPluginStatus
/**
* @Description: 改变所有插件的状态
* @param context
* example
*/
func updateAllPluginStatus(context *gin.Context) {
enable, err := strconv.ParseBool(context.PostForm("enable"))
if err != nil {
var parse map[string]interface{}
err := context.BindJSON(&parse)
if err != nil {
log.Errorln("[gui] " + err.Error())
return
}
enable = parse["enable"].(bool)
}
ctrl.ForEach(func(key string, manager *ctrl.Control) bool {
if enable {
manager.Enable(0)
} else {
manager.Disable(0)
}
return true
})
context.JSON(200, nil)
}
// updatePluginAllGroupStatus
/**
* @Description: 改变插件在所有群的状态
* @param context
* example
*/
func updatePluginAllGroupStatus(context *gin.Context) {
name := context.PostForm("name")
enable, err := strconv.ParseBool(context.PostForm("enable"))
if err != nil {
var parse map[string]interface{}
err := context.BindJSON(&parse)
if err != nil {
log.Errorln("[gui]" + err.Error())
return
}
name = parse["name"].(string)
enable = parse["enable"].(bool)
}
control, b := ctrl.Lookup(name)
if !b {
context.JSON(404, nil)
return
}
if enable {
control.Enable(0)
} else {
control.Disable(0)
}
context.JSON(200, nil)
}
// updatePluginStatus
/**
* @Description: 更改某一个插件状态
* @param context
* example
*/
func updatePluginStatus(context *gin.Context) {
var parse map[string]interface{}
err := context.BindJSON(&parse)
if err != nil {
log.Errorln("[gui] ", err)
return
}
groupID := int64(parse["group_id"].(float64))
name := parse["name"].(string)
enable := parse["enable"].(bool)
fmt.Println(name)
control, b := ctrl.Lookup(name)
if !b {
context.JSON(404, "服务不存在")
return
}
if enable {
control.Enable(groupID)
} else {
control.Disable(groupID)
}
context.JSON(200, nil)
}
// getPluginStatus
/**
* @Description: 获取一个插件的状态
* @param context
* example
*/
func getPluginStatus(context *gin.Context) {
groupID, err := strconv.ParseInt(context.PostForm("group_id"), 10, 64)
name := context.PostForm("name")
if err != nil {
var parse map[string]interface{}
err := context.BindJSON(&parse)
if err != nil {
log.Errorln("[gui]" + err.Error())
return
}
groupID = int64(parse["group_id"].(float64))
name = parse["name"].(string)
}
control, b := ctrl.Lookup(name)
if !b {
context.JSON(404, "服务不存在")
return
}
context.JSON(200, gin.H{"enable": control.IsEnabledIn(groupID)})
}
// getPluginsStatus
/**
* @Description: 获取所有插件的状态
* @param context
* example
*/
func getPluginsStatus(context *gin.Context) {
groupID, err := strconv.ParseInt(context.PostForm("group_id"), 10, 64)
if err != nil {
var parse map[string]interface{}
err := context.BindJSON(&parse)
if err != nil {
log.Errorln("[gui]" + err.Error())
return
}
groupID = int64(parse["group_id"].(float64))
}
var datas []map[string]interface{}
ctrl.ForEach(func(key string, manager *ctrl.Control) bool {
enable := manager.IsEnabledIn(groupID)
datas = append(datas, map[string]interface{}{"name": key, "enable": enable})
return true
})
context.JSON(200, datas)
}
// getLogs
/**
* @Description: 连接日志
* @param context
* example
*/
func getLogs(context *gin.Context) {
con1, err := upGrader.Upgrade(context.Writer, context.Request, nil)
if err != nil {
return
}
logConn = con1
}
// getFriendList
/**
* @Description: 获取好友列表
* @param context
* example
*/
func getFriendList(context *gin.Context) {
selfID, err := strconv.Atoi(context.PostForm("self_id"))
if err != nil {
log.Errorln("[gui]" + err.Error())
var data map[string]interface{}
err := context.BindJSON(&data)
if err != nil {
log.Errorln("[gui]" + err.Error())
log.Errorln("[gui]" + "绑定错误")
return
}
selfID = int(data["self_id"].(float64))
}
bot := zero.GetBot(int64(selfID))
var resp []interface{}
list := bot.GetFriendList().String()
err = json.Unmarshal([]byte(list), &resp)
if err != nil {
log.Errorln("[gui]" + err.Error())
log.Errorln("[gui]" + "解析json错误")
}
context.JSON(200, resp)
}
// getGroupList
/**
* @Description: 获取群列表
* @param context
* example
*/
func getGroupList(context *gin.Context) {
selfID, err := strconv.Atoi(context.PostForm("self_id"))
if err != nil {
var data map[string]interface{}
err := context.BindJSON(&data)
if err != nil {
log.Errorln("[gui]" + err.Error())
return
}
selfID = int(data["self_id"].(float64))
}
bot := zero.GetBot(int64(selfID))
var resp []interface{}
list := bot.GetGroupList().String()
err = json.Unmarshal([]byte(list), &resp)
if err != nil {
log.Errorln("[gui]" + err.Error())
}
context.JSON(200, resp)
}
// getBots
/**
* @Description: 获取机器人qq号
* @param context
* example
*/
func getBots(context *gin.Context) {
var bots []int64
zero.RangeBot(func(id int64, ctx *zero.Ctx) bool {
bots = append(bots, id)
return true
})
context.JSON(200, bots)
}
// MessageHandle
/**
* @Description: 定义一个向前端发送信息的handle
* example
*/
func messageHandle() {
defer func() {
err := recover()
if err != nil {
log.Errorln("[gui]" + "bot-manager出现不可恢复的错误")
log.Errorln("[gui] ", err)
}
}()
matcher := zero.OnMessage().SetBlock(false).SetPriority(1)
matcher.Handle(func(ctx *zero.Ctx) {
if conn != nil {
err := conn.WriteJSON(ctx.Event)
if err != nil {
log.Debugln("[gui] " + "向发送错误")
return
}
}
})
// 直接注册一个request请求监听器优先级设置为最高设置不阻断事件传播
zero.OnRequest(func(ctx *zero.Ctx) bool {
if ctx.Event.RequestType == "friend" {
ctx.State["type_name"] = "好友添加"
} else {
if ctx.Event.SubType == "add" {
ctx.State["type_name"] = "加群请求"
} else {
ctx.State["type_name"] = "群邀请"
}
}
return true
}).SetBlock(false).FirstPriority().Handle(func(ctx *zero.Ctx) {
r := &request{
RequestType: ctx.Event.RequestType,
SubType: ctx.Event.SubType,
Type: ctx.State["type_name"].(string),
GroupID: ctx.Event.GroupID,
UserID: ctx.Event.UserID,
Flag: ctx.Event.Flag,
Comment: ctx.Event.Comment,
SelfID: ctx.Event.SelfID,
}
requestData.Store(ctx.Event.Flag, r)
})
}
// upgrade
/**
* @Description: 连接ws向前端推送message
* @param context
* example
*/
func upgrade(context *gin.Context) {
con, err := upGrader.Upgrade(context.Writer, context.Request, nil)
if err != nil {
return
}
conn = con
}
// sendMsg
/**
* @Description: 前端调用发送信息
* @param context
* example
*/
func sendMsg(context *gin.Context) {
var data map[string]interface{}
err := context.BindJSON(&data)
if err != nil {
context.JSON(404, nil)
return
}
selfID := int64(data["self_id"].(float64))
id := int64(data["id"].(float64))
message1 := data["message"].(string)
messageType := data["message_type"].(string)
bot := zero.GetBot(selfID)
var msgID int64
if messageType == "group" {
msgID = bot.SendGroupMessage(id, message.ParseMessageFromString(message1))
} else {
msgID = bot.SendPrivateMessage(id, message.ParseMessageFromString(message1))
}
context.JSON(200, msgID)
}
// cors
/**
* @Description: 支持跨域访问
* @return gin.HandlerFunc
* example
*/
func cors() gin.HandlerFunc {
return func(c *gin.Context) {
method := c.Request.Method
origin := c.Request.Header.Get("Origin") // 请求头部
if origin != "" {
// 接收客户端发送的origin (重要!)
c.Writer.Header().Set("Access-Control-Allow-Origin", origin)
// 服务器支持的所有跨域请求的方法
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
// 允许跨域设置可以返回其他子段,可以自定义字段
c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session, Content-Type")
// 允许浏览器(客户端)可以解析的头部 (重要)
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
// 设置缓存时间
c.Header("Access-Control-Max-Age", "172800")
// 允许客户端传递校验信息比如 cookie (重要)
c.Header("Access-Control-Allow-Credentials", "true")
}
// 允许类型校验
if method == "OPTIONS" {
c.JSON(http.StatusOK, "ok!")
}
defer func() {
if err := recover(); err != nil {
log.Printf("Panic info is: %v", err)
}
}()
c.Next()
}
}
// handle
/**
* @Description: 提交一个请求
* @receiver r
* @param approve 是否通过
* @param reason 拒绝的理由
*/
func (r *request) handle(approve bool, reason string) {
bot := zero.GetBot(r.SelfID)
if r.RequestType == "friend" {
bot.SetFriendAddRequest(r.Flag, approve, "")
} else {
bot.SetGroupAddRequest(r.Flag, r.SubType, approve, reason)
}
log.Debugln("[gui] ", "已处理", r.UserID, "的"+r.Type)
}
func (l logWriter) Write(p []byte) (n int, err error) {
if logConn != nil {
err := logConn.WriteMessage(websocket.TextMessage, p)
if err != nil {
return len(p), nil
}
}
return len(p), nil
}

25
go.mod
View File

@ -4,8 +4,9 @@ go 1.17
require (
github.com/FloatTech/AnimeAPI v1.1.12
github.com/FloatTech/ZeroBot-Plugin-Gif v0.2.4
github.com/FloatTech/bot-manager v1.0.1-0.20211112011524-85b9895271ed
github.com/FloatTech/ZeroBot-Plugin-Gif v0.2.5
github.com/FloatTech/zbpctrl v1.2.3
github.com/FloatTech/zbputils v1.2.3
github.com/antchfx/htmlquery v1.2.4
github.com/corona10/goimagehash v1.0.3
github.com/fogleman/gg v1.3.0
@ -14,18 +15,14 @@ require (
github.com/fumiama/go-registry v0.0.2
github.com/fumiama/gofastTEA v0.0.6
github.com/fumiama/gotracemoe v0.0.3
github.com/gin-gonic/gin v1.7.7
github.com/gorilla/websocket v1.4.2
github.com/jinzhu/gorm v1.9.16
github.com/logoove/sqlite v1.13.0
github.com/mattn/go-runewidth v0.0.13
github.com/mroth/weightedrand v0.4.1
github.com/shirou/gopsutil/v3 v3.21.12
github.com/sirupsen/logrus v1.8.1
github.com/tidwall/gjson v1.12.1
github.com/wdvxdr1123/ZeroBot v1.4.1
golang.org/x/image v0.0.0-20211028202545-6944b10bf410
golang.org/x/text v0.3.7
)
require (
@ -33,23 +30,16 @@ require (
github.com/antchfx/xpath v1.2.0 // indirect
github.com/disintegration/imaging v1.6.2 // indirect
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-playground/validator/v10 v10.10.0 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
@ -58,16 +48,15 @@ require (
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tklauser/go-sysconf v0.3.9 // indirect
github.com/tklauser/numcpus v0.3.0 // indirect
github.com/ugorji/go/codec v1.2.6 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
golang.org/x/mod v0.5.1 // indirect
golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 // indirect
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.8 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
lukechampine.com/uint128 v1.1.1 // indirect
modernc.org/cc/v3 v3.35.22 // indirect
modernc.org/ccgo/v3 v3.14.0 // indirect

75
go.sum
View File

@ -1,20 +1,17 @@
github.com/FloatTech/AnimeAPI v1.1.9/go.mod h1:CC+vF30UGBlcIUxwFOcXIEHoJ4r7c5x2iLQsnUCVdDI=
github.com/FloatTech/AnimeAPI v1.1.11 h1:uuV4v5qweh0mI0E2KMiG5XGt0pKboV/EFAlIfSJxIi8=
github.com/FloatTech/AnimeAPI v1.1.11/go.mod h1:CC+vF30UGBlcIUxwFOcXIEHoJ4r7c5x2iLQsnUCVdDI=
github.com/FloatTech/AnimeAPI v1.1.12 h1:tEIAYumjti+FXYw5dhANU9lpoHY7i/sLm96Ly6kPeLE=
github.com/FloatTech/AnimeAPI v1.1.12/go.mod h1:CC+vF30UGBlcIUxwFOcXIEHoJ4r7c5x2iLQsnUCVdDI=
github.com/FloatTech/ZeroBot-Plugin v1.1.5/go.mod h1:kWuUARvU7gs4xLggi8Sy37ja2GRL6k0X6kewe5TiZRs=
github.com/FloatTech/ZeroBot-Plugin-Gif v0.2.4 h1:WW0BmmLLqAg+m6qGkrKbsfSIm91fkj3/udt3R7Myodo=
github.com/FloatTech/ZeroBot-Plugin-Gif v0.2.4/go.mod h1:W7ag6hml1pZTNzRXKU74OMr6rS8awQKSU+o2g7Gj4O0=
github.com/FloatTech/ZeroBot-Plugin-Timer v1.4.3/go.mod h1:MVOQQ4e6AVGFm993blXXU4Sd6bAsLY2+Zb+/HMrEeEc=
github.com/FloatTech/bot-manager v1.0.1-0.20211112011524-85b9895271ed h1:GEOgDVbvaxXqZxgWE/y5JOlbMXrmq7n0M+m9g3md2To=
github.com/FloatTech/bot-manager v1.0.1-0.20211112011524-85b9895271ed/go.mod h1:8YYRJ16oroGHQGD2En0oVnmcKJkxR9O/jd5BPSfWfOQ=
github.com/FloatTech/ZeroBot-Plugin-Gif v0.2.5 h1:9Xn0DI81OjCsKCvknmKB/hXyPXX0l9xj5vdlD9wppBw=
github.com/FloatTech/ZeroBot-Plugin-Gif v0.2.5/go.mod h1:rECiTB88W5hMYggb6zMKNLcHBEMWT7TFvlwJRQfWnhM=
github.com/FloatTech/bot-manager v1.0.0/go.mod h1:8YYRJ16oroGHQGD2En0oVnmcKJkxR9O/jd5BPSfWfOQ=
github.com/FloatTech/imgfactory v0.1.1 h1:ooL2+fV8yrMhv1ShGGKsN0Rm/flWoKnvqXaUD+dC3DQ=
github.com/FloatTech/imgfactory v0.1.1/go.mod h1:ThDALab8aOuU6KVYESVWFqmjcqtm03e0SvGlTw6s+aw=
github.com/FloatTech/zbpctrl v1.2.3 h1:/QZoakrgZupmWONed+kyEOoC+UKXu7actKSb2GHHW/Y=
github.com/FloatTech/zbpctrl v1.2.3/go.mod h1:uHZ5i0/CUqYLuqza9uDUUc5tCyX+Rn3wtmLdRo6tdhA=
github.com/FloatTech/zbputils v1.2.3 h1:c6CkfeFN2gFyHtK4kZnVH6ATOtIcuVbtNK7/l37Std4=
github.com/FloatTech/zbputils v1.2.3/go.mod h1:+NZ6tqt9lR2ilyiIh/+90tZlSW2pXx0IyOFlpOiqadE=
github.com/Mrs4s/MiraiGo v0.0.0-20211120033824-43b23f4e6fcb h1:Rkj28fqIwGx/EgBzRYtpmJRfH6wqVn7cNdc7aJ0QE4M=
github.com/Mrs4s/MiraiGo v0.0.0-20211120033824-43b23f4e6fcb/go.mod h1:imVKbfKqqeit+C/eaWGb4MKQ3z3gN6pRpBU5RMtp5so=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/antchfx/htmlquery v1.2.3/go.mod h1:B0ABL+F5irhhMWg54ymEZinzMSi0Kt3I2if0BLYa3V0=
github.com/antchfx/htmlquery v1.2.4 h1:qLteofCMe/KGovBI6SQgmou2QNyedFUW+pE+BpeZ494=
@ -24,7 +21,6 @@ github.com/antchfx/xpath v1.2.0 h1:mbwv7co+x0RwgeGAOHdrKy89GvHaGvxxBtPK0uF9Zr8=
github.com/antchfx/xpath v1.2.0/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
github.com/corona10/goimagehash v1.0.3 h1:NZM518aKLmoNluluhfHGxT3LGOnrojrxhGn63DR/CZA=
github.com/corona10/goimagehash v1.0.3/go.mod h1:VkvE0mLn84L4aF8vCb6mafVajEb6QYMHl2ZJLn0mOGI=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -51,24 +47,14 @@ github.com/fumiama/gofastTEA v0.0.6 h1:Yni3MXDbJVa/c4CecgdZDgCJK+fLdvGph+OBqY2mt
github.com/fumiama/gofastTEA v0.0.6/go.mod h1:+sBZ05nCA2skZkursHNvyr8kULlEetrYTM2y5kA4rQc=
github.com/fumiama/gotracemoe v0.0.3 h1:iI5EbE9A3UUbfukG6+/soYPjp1S31eCNYf4tw7s6/Jc=
github.com/fumiama/gotracemoe v0.0.3/go.mod h1:tyqahdUzHf0bQIAVY/GYmDWvYYe5ik1ZbhnGYh+zl40=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0=
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
@ -81,8 +67,6 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4er
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@ -94,7 +78,6 @@ github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imroc/req v0.3.0/go.mod h1:F+NZ+2EFSo6EFXdeIbpfE9hcC233id70kf0byW97Caw=
github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
@ -103,23 +86,11 @@ github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/logoove/sqlite v1.13.0 h1:XM7QKK9R3tm8o7bI75R3zmwYBFQ5S3Jqg+XCaqsAMQQ=
@ -136,12 +107,8 @@ github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A
github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA=
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2-0.20210109003243-333559e1834b/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mroth/weightedrand v0.4.1 h1:rHcbUBopmi/3x4nnrvwGJBhX9d0vk+KgoLUZeDP6YyI=
github.com/mroth/weightedrand v0.4.1/go.mod h1:3p2SIcC8al1YMzGhAIoXD+r9olo/g/cdJgAD905gyNE=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
@ -149,7 +116,6 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@ -160,12 +126,6 @@ github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6O
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/shirou/gopsutil v3.21.8+incompatible h1:sh0foI8tMRlCidUJR+KzqWYWxrkuuPIGiO6Vp+KXdCU=
github.com/shirou/gopsutil v3.21.8+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil/v3 v3.21.12 h1:VoGxEW2hpmz0Vt3wUvHIl9fquzYLNpVpgNNB7pGJimA=
github.com/shirou/gopsutil/v3 v3.21.12/go.mod h1:BToYZVTlSVlfazpDDYFnsVZLaoRG+g8ufT6fPQLdJzA=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@ -176,15 +136,11 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816/go.mod h1:tzym/CEb5jnFI+Q0k4Qq3+LvRF4gO3E2pxS8fHP8jcA=
github.com/tdf1939/ZeroBot-Plugin-Gif v0.0.0-20210828060956-389b1dc33652/go.mod h1:bkxKi7un9gCDvUUZAiIJF6k90pyj8rmxiXLJkiHcsMY=
github.com/tdf1939/img v0.0.0-20210827153520-90cb4e9580a3/go.mod h1:FgTEOcosTWrkOr7++gbtPSj1rX5loRWrf/AL+hm3Cnw=
github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
github.com/tidwall/gjson v1.9.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
github.com/tidwall/gjson v1.11.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.12.1 h1:ikuZsLdhr8Ws0IdROXUS1Gi4v9Z4pGqpX/CvJkxvfpo=
github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
@ -199,14 +155,8 @@ github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ
github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ=
github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E=
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
github.com/wdvxdr1123/ZeroBot v1.2.2/go.mod h1:83nHtG8V5TAxPwH/LCDxLpZk4khIgs29dkr5TBWf7fc=
github.com/wdvxdr1123/ZeroBot v1.2.3/go.mod h1:83nHtG8V5TAxPwH/LCDxLpZk4khIgs29dkr5TBWf7fc=
github.com/wdvxdr1123/ZeroBot v1.2.4/go.mod h1:83nHtG8V5TAxPwH/LCDxLpZk4khIgs29dkr5TBWf7fc=
github.com/wdvxdr1123/ZeroBot v1.3.2/go.mod h1:i2DIqQjtjE+3gvVi9r9sc+QpNaUuyTXx/HNXXayIpwI=
github.com/wdvxdr1123/ZeroBot v1.4.1 h1:fk/8RH2D1gB3YeC1eI/SZi/kG31Rh7Z8lAiDc60VZFM=
github.com/wdvxdr1123/ZeroBot v1.4.1/go.mod h1:7t9m4vDZPwWAmzKlhP6IvUoisOIiqNdm/3AJgiY3+ew=
@ -219,7 +169,6 @@ golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@ -237,7 +186,6 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 h1:+6WJMRLHlD7X7frgp7TUZ36RnQzSf9wVVTNakEp+nqY=
@ -261,7 +209,6 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -287,21 +234,13 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -10,7 +10,7 @@ import (
// 下列插件可与 wdvxdr1123/ZeroBot v1.1.2 以上配合单独使用
// 插件控制
// webctrl "github.com/FloatTech/ZeroBot-Plugin/control/web" // web 后端控制
// webctrl "github.com/FloatTech/zbpctrl/web" // web 后端控制
// 词库类
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_ai_reply" // 人工智能回复

View File

@ -12,8 +12,8 @@ import (
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/web"
control "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/web"
)
const (

View File

@ -7,12 +7,11 @@ import (
"os"
"time"
control "github.com/FloatTech/zbpctrl"
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/disk"
"github.com/shirou/gopsutil/v3/mem"
"github.com/FloatTech/ZeroBot-Plugin/control"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)

View File

@ -6,12 +6,11 @@ import (
"math/rand"
"time"
control "github.com/FloatTech/zbpctrl"
log "github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
var (

View File

@ -6,10 +6,9 @@ import (
"math/rand"
"time"
control "github.com/FloatTech/zbpctrl"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
const (

View File

@ -12,8 +12,8 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
control "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/process"
)
const (

View File

@ -4,13 +4,12 @@ package b14coder
import (
"unsafe"
control "github.com/FloatTech/zbpctrl"
base14 "github.com/fumiama/go-base16384"
tea "github.com/fumiama/gofastTEA"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
func init() {

View File

@ -5,11 +5,10 @@ import (
"net/http"
"time"
control "github.com/FloatTech/zbpctrl"
"github.com/fumiama/cron"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
type follower struct {

View File

@ -5,11 +5,10 @@ import (
"io/ioutil"
"net/http"
control "github.com/FloatTech/zbpctrl"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
var engine = control.Register("bilibili", &control.Options{

View File

@ -7,8 +7,8 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/txt2img"
control "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/txt2img"
)
func init() {

View File

@ -5,9 +5,9 @@ import (
log "github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/process"
"github.com/FloatTech/zbputils/sql"
)
const dbpath = "data/BookReview/"

View File

@ -9,13 +9,12 @@ import (
"net/url"
"strings"
control "github.com/FloatTech/zbpctrl"
"github.com/antchfx/htmlquery"
log "github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
const (

View File

@ -6,11 +6,10 @@ import (
"strconv"
"time"
control "github.com/FloatTech/zbpctrl"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
const (

View File

@ -6,8 +6,8 @@ import (
"github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/process"
)
type kimo = map[string]*[]string

View File

@ -6,10 +6,9 @@ import (
"strconv"
"strings"
control "github.com/FloatTech/zbpctrl"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
func init() {

View File

@ -2,10 +2,9 @@
package chouxianghua
import (
control "github.com/FloatTech/zbpctrl"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
const prio = 10

View File

@ -5,9 +5,9 @@ import (
log "github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/process"
"github.com/FloatTech/zbputils/sql"
)
const (

View File

@ -12,8 +12,8 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/web"
control "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/web"
)
var (

View File

@ -7,9 +7,9 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/ctxext"
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
control "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/math"
)
const (

View File

@ -5,9 +5,9 @@ import (
log "github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/process"
"github.com/FloatTech/zbputils/sql"
)
const (

View File

@ -8,8 +8,8 @@ import (
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
control "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/process"
)
const (

View File

@ -5,9 +5,9 @@ import (
"github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/process"
"github.com/FloatTech/zbputils/sql"
)
const (

View File

@ -8,8 +8,8 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/plugin_diana/data"
control "github.com/FloatTech/zbpctrl"
)
var engine *zero.Engine

View File

@ -9,9 +9,9 @@ import (
log "github.com/sirupsen/logrus"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/process"
"github.com/FloatTech/zbputils/sql"
)
const (

View File

@ -21,9 +21,9 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
control "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/math"
)
var (

View File

@ -5,8 +5,8 @@ import (
"github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/process"
)
type joke struct {

View File

@ -7,7 +7,7 @@ import (
"strings"
"testing"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
"github.com/FloatTech/zbputils/sql"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
)

View File

@ -9,9 +9,9 @@ import (
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/ctxext"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
control "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/sql"
)
var (

View File

@ -9,11 +9,10 @@ import (
"net/url"
"strings"
control "github.com/FloatTech/zbpctrl"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/tidwall/gjson"
)

View File

@ -12,9 +12,9 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/web"
control "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/web"
)
var (

View File

@ -8,10 +8,9 @@ import (
"net/http"
"time"
control "github.com/FloatTech/zbpctrl"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
type resultjson struct {

View File

@ -8,14 +8,13 @@ import (
"strings"
"time"
control "github.com/FloatTech/zbpctrl"
log "github.com/sirupsen/logrus"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
const (

View File

@ -11,8 +11,8 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
control "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/math"
)
const (

View File

@ -10,8 +10,8 @@ import (
"github.com/sirupsen/logrus"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
"github.com/FloatTech/ZeroBot-Plugin/utils/web"
"github.com/FloatTech/zbputils/math"
"github.com/FloatTech/zbputils/web"
)
// user hash file

View File

@ -15,12 +15,12 @@ import (
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/plugin_manager/timer"
"github.com/FloatTech/ZeroBot-Plugin/utils/ctxext"
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
control "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/math"
"github.com/FloatTech/zbputils/process"
"github.com/FloatTech/zbputils/sql"
)
const (

View File

@ -1,7 +1,7 @@
package timer
import (
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
"github.com/FloatTech/zbputils/sql"
)
// Timer 计时器

View File

@ -12,7 +12,7 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
"github.com/FloatTech/zbputils/sql"
)
// Clock 时钟

View File

@ -4,7 +4,7 @@ import (
"testing"
"time"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
"github.com/FloatTech/zbputils/sql"
"github.com/sirupsen/logrus"
)

View File

@ -6,11 +6,10 @@ import (
"io/ioutil"
"net/http"
control "github.com/FloatTech/zbpctrl"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
// 此功能实现依赖MCSManager项目对服务器的管理apimc服务器如果没有在该管理平台部署此功能无效

View File

@ -5,8 +5,8 @@ import (
"github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/process"
)
// 加载数据库

View File

@ -18,10 +18,10 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
aireply "github.com/FloatTech/ZeroBot-Plugin/plugin_ai_reply"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/web"
control "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/web"
)
const (

View File

@ -4,11 +4,10 @@ package moyu
import (
"time"
control "github.com/FloatTech/zbpctrl"
"github.com/fumiama/cron"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
func init() { // 插件主体

View File

@ -11,12 +11,11 @@ import (
"strings"
"time"
control "github.com/FloatTech/zbpctrl"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
var limit = rate.NewManager(time.Minute*3, 5)

View File

@ -13,9 +13,9 @@ import (
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"golang.org/x/image/webp"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/process"
"github.com/FloatTech/zbputils/sql"
)
// setuclass holds setus in a folder, which is the class name.

View File

@ -10,8 +10,8 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/rule"
control "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/rule"
)
const (

View File

@ -17,9 +17,9 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/ctxext"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
control "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
)
const base = "data/nwife"

View File

@ -18,9 +18,9 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
ub "github.com/FloatTech/ZeroBot-Plugin/utils/binary"
"github.com/FloatTech/ZeroBot-Plugin/utils/txt2img"
control "github.com/FloatTech/zbpctrl"
ub "github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/txt2img"
)
const (

View File

@ -5,9 +5,9 @@ import (
log "github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/process"
"github.com/FloatTech/zbputils/sql"
)
const (

View File

@ -12,8 +12,8 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/txt2img"
control "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/txt2img"
)
const (

View File

@ -7,8 +7,8 @@ import (
wr "github.com/mroth/weightedrand"
log "github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/process"
)
const (

View File

@ -6,10 +6,9 @@ import (
"math/rand"
"time"
control "github.com/FloatTech/zbpctrl"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
func init() {

View File

@ -9,12 +9,11 @@ import (
"strings"
"time"
control "github.com/FloatTech/zbpctrl"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/tidwall/gjson"
)

View File

@ -14,8 +14,8 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
control "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/file"
)
var (

View File

@ -5,7 +5,7 @@ import (
log "github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/zbputils/process"
)
const (

View File

@ -15,11 +15,11 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/ctxext"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/txt2img"
"github.com/FloatTech/ZeroBot-Plugin/utils/web"
control "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/txt2img"
"github.com/FloatTech/zbputils/web"
)
const (

View File

@ -14,12 +14,12 @@ import (
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
fileutil "github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/ZeroBot-Plugin/utils/rule"
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
control "github.com/FloatTech/zbpctrl"
fileutil "github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/math"
"github.com/FloatTech/zbputils/process"
"github.com/FloatTech/zbputils/rule"
"github.com/FloatTech/zbputils/sql"
)
// Pools 图片缓冲池

View File

@ -5,7 +5,7 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/utils/web"
"github.com/FloatTech/zbputils/web"
)
func init() {

View File

@ -5,7 +5,7 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/utils/web"
"github.com/FloatTech/zbputils/web"
)
func init() {

View File

@ -5,7 +5,7 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/utils/web"
"github.com/FloatTech/zbputils/web"
)
func init() {

View File

@ -4,9 +4,8 @@ package shadiao
import (
"time"
control "github.com/FloatTech/zbpctrl"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
const (

View File

@ -6,7 +6,7 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/utils/web"
"github.com/FloatTech/zbputils/web"
)
func init() {

View File

@ -8,7 +8,7 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/utils/web"
"github.com/FloatTech/zbputils/web"
)
func init() {

View File

@ -11,9 +11,9 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/ctxext"
"github.com/FloatTech/ZeroBot-Plugin/utils/txt2img"
control "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/txt2img"
)
var (

View File

@ -6,7 +6,7 @@ import (
log "github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/plugin_sleep_manage/model"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/zbputils/process"
)
func init() {

View File

@ -9,8 +9,8 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/plugin_sleep_manage/model"
control "github.com/FloatTech/zbpctrl"
)
const dbpath = "data/sleep/"

View File

@ -5,11 +5,10 @@ import (
"fmt"
"github.com/FloatTech/AnimeAPI/picture"
control "github.com/FloatTech/zbpctrl"
trmoe "github.com/fumiama/gotracemoe"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
var (

View File

@ -13,8 +13,8 @@ import (
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
control "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/process"
)
var (

View File

@ -5,7 +5,7 @@ import (
log "github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/plugin_vtb_quotation/model"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/zbputils/process"
)
func init() {

View File

@ -3,8 +3,8 @@ package vtbquotation
import (
"os"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/process"
)
// 加载数据库

View File

@ -14,9 +14,9 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/plugin_vtb_quotation/model"
"github.com/FloatTech/ZeroBot-Plugin/utils/txt2img"
control "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/txt2img"
)
const (

View File

@ -6,11 +6,10 @@ import (
"strconv"
"time"
control "github.com/FloatTech/zbpctrl"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control"
)
var (

View File

@ -1,30 +0,0 @@
// Package binary 数据处理
package binary
import (
"bytes"
"io/ioutil"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
)
// GBK2UTF8 GBK 转 UTF-8
func GBK2UTF8(s []byte) ([]byte, error) {
reader := transform.NewReader(bytes.NewReader(s), simplifiedchinese.GBK.NewDecoder())
d, e := ioutil.ReadAll(reader)
if e != nil {
return nil, e
}
return d, nil
}
// UTF82GBK UTF-8 转 GBK
func UTF82GBK(s []byte) ([]byte, error) {
reader := transform.NewReader(bytes.NewReader(s), simplifiedchinese.GBK.NewEncoder())
d, e := ioutil.ReadAll(reader)
if e != nil {
return nil, e
}
return d, nil
}

View File

@ -1,29 +0,0 @@
// Package ctxext zero ctx 扩展
package ctxext
import (
"strconv"
zero "github.com/wdvxdr1123/ZeroBot"
)
// NickName 从 args 获取名字
func NickName(ctx *zero.Ctx) (name string) {
name = ctx.State["args"].(string)
if len(ctx.Event.Message) > 1 && ctx.Event.Message[1].Type == "at" {
qq, _ := strconv.ParseInt(ctx.Event.Message[1].Data["qq"], 10, 64)
name = ctx.GetGroupMemberInfo(ctx.Event.GroupID, qq, false).Get("nickname").Str
} else if name == "" {
name = ctx.Event.Sender.NickName
}
return
}
// CardOrNickName 从 uid 获取名字
func CardOrNickName(ctx *zero.Ctx, uid int64) (name string) {
name = ctx.GetGroupMemberInfo(ctx.Event.GroupID, uid, false).Get("card").String()
if name == "" {
name = ctx.GetStrangerInfo(uid, false).Get("nickname").String()
}
return
}

View File

@ -1,12 +0,0 @@
//go:build !windows
// +build !windows
package file
import "os"
// Pwd 获取当前路径
func Pwd() (path string) {
path, _ = os.Getwd()
return
}

View File

@ -1,15 +0,0 @@
//go:build windows
// +build windows
package file
import (
"os"
"strings"
)
// Pwd 获取当前路径的正斜杠表示
func Pwd() string {
path, _ := os.Getwd()
return strings.ReplaceAll(path, "\\", "/")
}

View File

@ -1,38 +0,0 @@
// Package file 文件实用工具
package file
import (
"crypto/tls"
"io"
"net/http"
"os"
)
var (
tr = &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
nochkcrtcli = &http.Client{Transport: tr}
)
// DownloadTo 下载到路径
//nolint: bodyclose
func DownloadTo(url, file string, chkcrt bool) error {
var resp *http.Response
var err error
if chkcrt {
resp, err = http.Get(url)
} else {
resp, err = nochkcrtcli.Get(url)
}
if err == nil {
var f *os.File
f, err = os.Create(file)
if err == nil {
_, err = io.Copy(f, resp.Body)
f.Close()
}
resp.Body.Close()
}
return err
}

View File

@ -1,18 +0,0 @@
package file
import "os"
// BOTPATH BOT当前路径
var BOTPATH = Pwd()
// IsExist 文件/路径存在
func IsExist(path string) bool {
_, err := os.Stat(path)
return err == nil || os.IsExist(err)
}
// IsNotExist 文件/路径不存在
func IsNotExist(path string) bool {
_, err := os.Stat(path)
return err != nil && os.IsNotExist(err)
}

View File

@ -1,137 +0,0 @@
package file
import (
"crypto/md5"
"encoding/hex"
"errors"
"io"
"net/http"
"os"
"sync"
"time"
"unsafe"
reg "github.com/fumiama/go-registry"
"github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
)
const (
dataurl = "https://gitcode.net/u011570312/zbpdata/-/raw/main/"
)
var (
registry = reg.NewRegReader("reilia.fumiama.top:32664", "fumiama")
connmu, getmu sync.Mutex
processes sync.WaitGroup
connerr error
isconnected bool
)
// GetLazyData 获取懒加载数据
// 传入的 path 的前缀 data/
// 在验证完 md5 后将被删去
// 以便进行下载
func GetLazyData(path string, isReturnDataBytes, isDataMustEqual bool) ([]byte, error) {
var data []byte
var resp *http.Response
var filemd5 *[16]byte
var ms string
var err error
u := dataurl + path[5:]
if !isconnected {
connmu.Lock()
if !isconnected && connerr == nil {
logrus.Infoln("[file]连接md5验证服务器...")
connerr = registry.ConnectIn(time.Second * 4)
if connerr == nil {
isconnected = true
go func() {
process.SleepAbout1sTo2s()
processes.Wait()
_ = registry.Close()
isconnected = false
logrus.Infoln("[file]关闭到md5验证服务器的连接")
}()
} else {
logrus.Warnln("[file]连接md5验证服务器失败:", connerr)
}
}
connmu.Unlock()
}
if connerr != nil {
logrus.Warnln("[file]无法连接到md5验证服务器请自行确保下载文件", path, "的正确性")
} else {
processes.Add(1)
getmu.Lock()
ms, err = registry.Get(path)
getmu.Unlock()
processes.Done()
if err != nil || len(ms) != 16 {
logrus.Warnln("[file]获取md5失败请自行确保下载文件", path, "的正确性:", err)
} else {
filemd5 = (*[16]byte)(*(*unsafe.Pointer)(unsafe.Pointer(&ms)))
logrus.Infoln("[file]从验证服务器获得文件", path, "md5:", hex.EncodeToString(filemd5[:]))
}
}
if IsExist(path) {
data, err = os.ReadFile(path)
if err != nil {
return nil, err
}
if filemd5 != nil {
if md5.Sum(data) == *filemd5 {
logrus.Infoln("[file]文件md5匹配文件已存在且为最新")
goto ret
} else if !isDataMustEqual {
logrus.Warnln("[file]文件", path, "md5不匹配但不主动更新")
goto ret
}
logrus.Infoln("[file]文件md5不匹配开始更新文件")
} else {
logrus.Warnln("[file]文件", path, "存在已跳过md5检查")
goto ret
}
}
// 下载
resp, err = http.Get(u)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.ContentLength <= 0 {
return nil, errors.New("resp body len <= 0")
}
logrus.Printf("[file]从镜像下载数据%d字节...", resp.ContentLength)
// 读取数据
data, err = io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if len(data) == 0 {
return nil, errors.New("read body len <= 0")
}
if filemd5 != nil {
if md5.Sum(data) == *filemd5 {
logrus.Infoln("[file]文件下载完成md5匹配开始保存")
} else {
logrus.Errorln("[file]文件", path, "md5不匹配下载失败")
return nil, errors.New("file md5 mismatch")
}
} else {
logrus.Warnln("[file]文件", path, "下载完成已跳过md5检查开始保存")
}
// 写入数据
err = os.WriteFile(path, data, 0644)
ret:
if isReturnDataBytes {
return data, err
}
return nil, err
}

View File

@ -1,9 +0,0 @@
package math
import "strconv"
// Str2Int64 string to int64
func Str2Int64(str string) int64 {
val, _ := strconv.ParseInt(str, 10, 64)
return val
}

View File

@ -1,47 +0,0 @@
// Package math 计算实用工具
package math
// Max 返回两数最大值,该函数将被内联
func Max(a, b int) int {
if a > b {
return a
}
return b
}
// Min 返回两数最小值,该函数将被内联
func Min(a, b int) int {
if a > b {
return b
}
return a
}
// intSize is either 32 or 64.
const intSize = 32 << (^uint(0) >> 63)
// Abs 返回绝对值,该函数将被内联
func Abs(x int) int {
// m := -1 if x < 0. m := 0 otherwise.
m := x >> (intSize - 1)
// In two's complement representation, the negative number
// of any number (except the smallest one) can be computed
// by flipping all the bits and add 1. This is faster than
// code with a branch.
// See Hacker's Delight, section 2-4.
return (x ^ m) - m
}
// Abs64 返回绝对值,该函数将被内联
func Abs64(x int64) int64 {
// m := -1 if x < 0. m := 0 otherwise.
m := x >> (64 - 1)
// In two's complement representation, the negative number
// of any number (except the smallest one) can be computed
// by flipping all the bits and add 1. This is faster than
// code with a branch.
// See Hacker's Delight, section 2-4.
return (x ^ m) - m
}

View File

@ -1,12 +0,0 @@
// Package process 流程控制相关
package process
import (
"math/rand"
"time"
)
// SleepAbout1sTo2s 随机阻塞等待 1 ~ 2s
func SleepAbout1sTo2s() {
time.Sleep(time.Second + time.Millisecond*time.Duration(rand.Intn(1000)))
}

View File

@ -1,17 +0,0 @@
// Package rule zb 规则扩展
package rule
import zero "github.com/wdvxdr1123/ZeroBot"
// FirstValueInList 判断正则匹配的第一个参数是否在列表中
func FirstValueInList(list []string) zero.Rule {
return func(ctx *zero.Ctx) bool {
first := ctx.State["regex_matched"].([]string)[1]
for _, v := range list {
if first == v {
return true
}
}
return false
}
}

View File

@ -1,450 +0,0 @@
// Package sql 数据库/数据处理相关工具
package sql
import (
"database/sql"
"errors"
"reflect"
"strings"
_ "github.com/logoove/sqlite" // 引入sqlite
)
// Sqlite 数据库对象
type Sqlite struct {
DB *sql.DB
DBPath string
}
// Open 打开数据库
func (db *Sqlite) Open() (err error) {
if db.DB == nil {
database, err := sql.Open("sqlite3", db.DBPath)
if err != nil {
return err
}
db.DB = database
}
return
}
// Close 关闭数据库
func (db *Sqlite) Close() (err error) {
if db.DB != nil {
err = db.DB.Close()
db.DB = nil
}
return
}
// Create 生成数据库
// 默认结构体的第一个元素为主键
// 返回错误
func (db *Sqlite) Create(table string, objptr interface{}) (err error) {
if db.DB == nil {
database, err := sql.Open("sqlite3", db.DBPath)
if err != nil {
return err
}
db.DB = database
}
var (
tags = tags(objptr)
kinds = kinds(objptr)
top = len(tags) - 1
cmd = []string{}
)
cmd = append(cmd, "CREATE TABLE IF NOT EXISTS")
cmd = append(cmd, table)
cmd = append(cmd, "(")
for i := range tags {
cmd = append(cmd, tags[i])
cmd = append(cmd, kinds[i])
switch i {
default:
cmd = append(cmd, "NULL,")
case 0:
cmd = append(cmd, "PRIMARY KEY")
cmd = append(cmd, "NOT NULL,")
case top:
cmd = append(cmd, "NULL);")
}
}
_, err = db.DB.Exec(strings.Join(cmd, " ") + ";")
return
}
// Insert 插入数据集
// 如果 PK 存在会覆盖
// 默认结构体的第一个元素为主键
// 返回错误
func (db *Sqlite) Insert(table string, objptr interface{}) error {
rows, err := db.DB.Query("SELECT * FROM " + table + " limit 1;")
if err != nil {
return err
}
if rows.Err() != nil {
return rows.Err()
}
tags, _ := rows.Columns()
rows.Close()
var (
vals = values(objptr)
top = len(tags) - 1
cmd = []string{}
)
cmd = append(cmd, "REPLACE INTO")
cmd = append(cmd, table)
for i := range tags {
switch i {
default:
cmd = append(cmd, tags[i])
cmd = append(cmd, ",")
case 0:
cmd = append(cmd, "(")
cmd = append(cmd, tags[i])
cmd = append(cmd, ",")
case top:
cmd = append(cmd, tags[i])
cmd = append(cmd, ")")
}
}
for i := range tags {
switch i {
default:
cmd = append(cmd, "?")
cmd = append(cmd, ",")
case 0:
cmd = append(cmd, "VALUES (")
cmd = append(cmd, "?")
cmd = append(cmd, ",")
case top:
cmd = append(cmd, "?")
cmd = append(cmd, ")")
}
}
stmt, err := db.DB.Prepare(strings.Join(cmd, " ") + ";")
if err != nil {
return err
}
_, err = stmt.Exec(vals...)
if err != nil {
return err
}
return stmt.Close()
}
// InsertUnique 插入数据集
// 如果 PK 存在会报错
// 默认结构体的第一个元素为主键
// 返回错误
func (db *Sqlite) InsertUnique(table string, objptr interface{}) error {
rows, err := db.DB.Query("SELECT * FROM " + table + " limit 1;")
if err != nil {
return err
}
if rows.Err() != nil {
return rows.Err()
}
tags, _ := rows.Columns()
rows.Close()
var (
vals = values(objptr)
top = len(tags) - 1
cmd = []string{}
)
cmd = append(cmd, "INSERT INTO")
cmd = append(cmd, table)
for i := range tags {
switch i {
default:
cmd = append(cmd, tags[i])
cmd = append(cmd, ",")
case 0:
cmd = append(cmd, "(")
cmd = append(cmd, tags[i])
cmd = append(cmd, ",")
case top:
cmd = append(cmd, tags[i])
cmd = append(cmd, ")")
}
}
for i := range tags {
switch i {
default:
cmd = append(cmd, "?")
cmd = append(cmd, ",")
case 0:
cmd = append(cmd, "VALUES (")
cmd = append(cmd, "?")
cmd = append(cmd, ",")
case top:
cmd = append(cmd, "?")
cmd = append(cmd, ")")
}
}
stmt, err := db.DB.Prepare(strings.Join(cmd, " ") + ";")
if err != nil {
return err
}
_, err = stmt.Exec(vals...)
if err != nil {
return err
}
return stmt.Close()
}
// Find 查询数据库,写入最后一条结果到 objptr
// condition 可为"WHERE id = 0"
// 默认字段与结构体元素顺序一致
// 返回错误
func (db *Sqlite) Find(table string, objptr interface{}, condition string) error {
var cmd = []string{}
cmd = append(cmd, "SELECT * FROM ")
cmd = append(cmd, table)
cmd = append(cmd, condition)
rows, err := db.DB.Query(strings.Join(cmd, " ") + ";")
if err != nil {
return err
}
if rows.Err() != nil {
return rows.Err()
}
defer rows.Close()
if !rows.Next() {
return errors.New("sql.Find: null result")
}
err = rows.Scan(addrs(objptr)...)
for rows.Next() {
if err != nil {
return err
}
err = rows.Scan(addrs(objptr)...)
}
return err
}
// CanFind 查询数据库是否有 condition
// condition 可为"WHERE id = 0"
// 默认字段与结构体元素顺序一致
// 返回错误
func (db *Sqlite) CanFind(table string, condition string) bool {
var cmd = []string{}
cmd = append(cmd, "SELECT * FROM")
cmd = append(cmd, table)
cmd = append(cmd, condition)
rows, err := db.DB.Query(strings.Join(cmd, " ") + ";")
if err != nil {
return false
}
if rows.Err() != nil {
return false
}
defer rows.Close()
if !rows.Next() {
return false
}
_ = rows.Close()
return true
}
// FindFor 查询数据库,用函数 f 遍历结果
// condition 可为"WHERE id = 0"
// 默认字段与结构体元素顺序一致
// 返回错误
func (db *Sqlite) FindFor(table string, objptr interface{}, condition string, f func() error) error {
var cmd = []string{}
cmd = append(cmd, "SELECT * FROM")
cmd = append(cmd, table)
cmd = append(cmd, condition)
rows, err := db.DB.Query(strings.Join(cmd, " ") + ";")
if err != nil {
return err
}
if rows.Err() != nil {
return rows.Err()
}
defer rows.Close()
if !rows.Next() {
return errors.New("sql.FindFor: null result")
}
err = rows.Scan(addrs(objptr)...)
if err == nil {
err = f()
}
for rows.Next() {
if err != nil {
return err
}
err = rows.Scan(addrs(objptr)...)
if err == nil {
err = f()
}
}
return err
}
// Pick 从 table 随机一行
func (db *Sqlite) Pick(table string, objptr interface{}) error {
return db.Find(table, objptr, "ORDER BY RANDOM() limit 1")
}
// ListTables 列出所有表名
// 返回所有表名+错误
func (db *Sqlite) ListTables() (s []string, err error) {
rows, err := db.DB.Query("SELECT name FROM sqlite_master where type='table' order by name;")
if err != nil {
return
}
if rows.Err() != nil {
return nil, rows.Err()
}
defer rows.Close()
for rows.Next() {
if err != nil {
return
}
objptr := new(string)
err = rows.Scan(objptr)
if err == nil {
s = append(s, *objptr)
}
}
return
}
// Del 删除数据库表项
// condition 可为"WHERE id = 0"
// 返回错误
func (db *Sqlite) Del(table string, condition string) error {
var cmd = []string{}
cmd = append(cmd, "DELETE FROM")
cmd = append(cmd, table)
cmd = append(cmd, condition)
stmt, err := db.DB.Prepare(strings.Join(cmd, " ") + ";")
if err != nil {
return err
}
_, err = stmt.Exec()
if err != nil {
return err
}
return stmt.Close()
}
// Truncate 清空数据库表
func (db *Sqlite) Truncate(table string) error {
var cmd = []string{}
cmd = append(cmd, "TRUNCATE TABLE")
cmd = append(cmd, table)
stmt, err := db.DB.Prepare(strings.Join(cmd, " ") + ";")
if err != nil {
return err
}
_, err = stmt.Exec()
if err != nil {
return err
}
return stmt.Close()
}
// Count 查询数据库行数
// 返回行数以及错误
func (db *Sqlite) Count(table string) (num int, err error) {
var cmd = []string{}
cmd = append(cmd, "SELECT COUNT(1) FROM")
cmd = append(cmd, table)
rows, err := db.DB.Query(strings.Join(cmd, " ") + ";")
if err != nil {
return num, err
}
if rows.Err() != nil {
return num, rows.Err()
}
if rows.Next() {
err = rows.Scan(&num)
}
rows.Close()
return num, err
}
// tags 反射 返回结构体对象的 tag 数组
func tags(objptr interface{}) []string {
var tags []string
elem := reflect.ValueOf(objptr).Elem()
// 判断第一个元素是否为匿名字段
if elem.Type().Field(0).Anonymous {
elem = elem.Field(0)
}
for i, flen := 0, elem.Type().NumField(); i < flen; i++ {
tags = append(tags, elem.Type().Field(i).Tag.Get("db"))
}
return tags
}
// kinds 反射 返回结构体对象的 kinds 数组
func kinds(objptr interface{}) []string {
var kinds []string
elem := reflect.ValueOf(objptr).Elem()
// 判断第一个元素是否为匿名字段
if elem.Type().Field(0).Anonymous {
elem = elem.Field(0)
}
for i, flen := 0, elem.Type().NumField(); i < flen; i++ {
switch elem.Field(i).Type().String() {
case "int8":
kinds = append(kinds, "TINYINT")
case "uint8", "byte":
kinds = append(kinds, "UNSIGNED TINYINT")
case "int16":
kinds = append(kinds, "SMALLINT")
case "uint16":
kinds = append(kinds, "UNSIGNED SMALLINT")
case "int32":
kinds = append(kinds, "INT")
case "uint32":
kinds = append(kinds, "UNSIGNED INT")
case "int64":
kinds = append(kinds, "BIGINT")
case "uint64":
kinds = append(kinds, "UNSIGNED BIGINT")
case "string":
kinds = append(kinds, "TEXT")
default:
kinds = append(kinds, "TEXT")
}
}
return kinds
}
// values 反射 返回结构体对象的 values 数组
func values(objptr interface{}) []interface{} {
var values []interface{}
elem := reflect.ValueOf(objptr).Elem()
// 判断第一个元素是否为匿名字段
if elem.Type().Field(0).Anonymous {
elem = elem.Field(0)
}
for i, flen := 0, elem.Type().NumField(); i < flen; i++ {
values = append(values, elem.Field(i).Interface())
}
return values
}
// addrs 反射 返回结构体对象的 addrs 数组
func addrs(objptr interface{}) []interface{} {
var addrs []interface{}
elem := reflect.ValueOf(objptr).Elem()
// 判断第一个元素是否为匿名字段
if elem.Type().Field(0).Anonymous {
elem = elem.Field(0)
}
for i, flen := 0, elem.Type().NumField(); i < flen; i++ {
addrs = append(addrs, elem.Field(i).Addr().Interface())
}
return addrs
}

View File

@ -1,105 +0,0 @@
// Package txt2img 文字转图片
package txt2img
import (
"bytes"
"encoding/base64"
"image/jpeg"
"os"
"strings"
"github.com/fogleman/gg"
"github.com/mattn/go-runewidth"
log "github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
)
const (
whitespace = "\t\n\r\x0b\x0c"
// FontPath 通用字体路径
FontPath = "data/Font/"
// FontFile 苹方字体
FontFile = FontPath + "regular.ttf"
// BoldFontFile 粗体苹方字体
BoldFontFile = FontPath + "regular-bold.ttf"
)
// 加载数据库
func init() {
go func() {
process.SleepAbout1sTo2s()
_ = os.MkdirAll(FontPath, 0755)
_, _ = file.GetLazyData(FontFile, false, true)
_, _ = file.GetLazyData(BoldFontFile, false, true)
}()
}
// RenderToBase64 文字转base64
func RenderToBase64(text string, width, fontSize int) (base64Bytes []byte, err error) {
canvas, err := Render(text, width, fontSize)
if err != nil {
log.Println("[txt2img]:", err)
return nil, err
}
base64Bytes, err = CanvasToBase64(canvas)
if err != nil {
log.Println("[txt2img]:", err)
return nil, err
}
return
}
// Render 文字转图片
func Render(text string, width, fontSize int) (canvas *gg.Context, err error) {
buff := make([]string, 0)
line := ""
count := 0
for _, v := range text {
c := string(v)
if strings.Contains(whitespace, c) {
buff = append(buff, strings.TrimSpace(line))
count = 0
line = ""
continue
}
if count <= width {
line += c
count += runewidth.StringWidth(c)
} else {
buff = append(buff, line)
line = c
count = runewidth.StringWidth(c)
}
}
canvas = gg.NewContext((fontSize+4)*width/2, (len(buff)+2)*fontSize)
canvas.SetRGB(1, 1, 1)
canvas.Clear()
canvas.SetRGB(0, 0, 0)
if err = canvas.LoadFontFace(FontFile, float64(fontSize)); err != nil {
log.Println("[txt2img]:", err)
return nil, err
}
for i, v := range buff {
if v != "" {
canvas.DrawString(v, float64(width/2), float64((i+2)*fontSize))
}
}
return
}
// CanvasToBase64 gg内容转为base64
func CanvasToBase64(canvas *gg.Context) (base64Bytes []byte, err error) {
buffer := new(bytes.Buffer)
encoder := base64.NewEncoder(base64.StdEncoding, buffer)
var opt jpeg.Options
opt.Quality = 70
if err = jpeg.Encode(encoder, canvas.Image(), &opt); err != nil {
return nil, err
}
encoder.Close()
base64Bytes = buffer.Bytes()
return
}

View File

@ -1,44 +0,0 @@
// Package web 网络处理相关
package web
import (
"errors"
"io"
"net/http"
)
// ReqWith 使用自定义请求头获取数据
func ReqWith(url string, method string, referer string, ua string) (data []byte, err error) {
client := &http.Client{}
// 提交请求
var request *http.Request
request, err = http.NewRequest(method, url, nil)
if err == nil {
// 增加header选项
request.Header.Add("Referer", referer)
request.Header.Add("User-Agent", ua)
var response *http.Response
response, err = client.Do(request)
if err == nil {
data, err = io.ReadAll(response.Body)
response.Body.Close()
}
}
return
}
// GetData 获取数据
func GetData(url string) (data []byte, err error) {
var response *http.Response
response, err = http.Get(url)
if err == nil {
if response.ContentLength <= 0 {
err = errors.New("web.GetData: empty body")
response.Body.Close()
return
}
data, err = io.ReadAll(response.Body)
response.Body.Close()
}
return
}

View File

@ -1,21 +0,0 @@
package web
import (
"io"
"net/http"
"github.com/sirupsen/logrus"
)
// IsSupportIPv6 检查本机是否支持 ipv6
var IsSupportIPv6 = func() bool {
resp, err := http.Get("http://v6.ipv6-test.com/json/widgetdata.php?callback=?")
if err != nil {
logrus.Infoln("[web] 本机不支持ipv6")
return false
}
_, _ = io.ReadAll(resp.Body)
_ = resp.Body.Close()
logrus.Infoln("[web] 本机支持ipv6")
return true
}()