mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2025-12-20 06:20:08 +08:00
✨ job可获取网页信息,可代表执行
This commit is contained in:
parent
183be05d82
commit
a27132f907
21
README.md
21
README.md
@ -67,16 +67,16 @@ zerobot [-h] [-t token] [-u url] [-n nickname] [-p prefix] [-d|w] [-g 监听地
|
|||||||
- [x] /服务详情
|
- [x] /服务详情
|
||||||
- [x] @Bot 插件冲突检测 (会在本群发送一条消息并在约 1s 后撤回以检测其它同类 bot 中已启用的插件并禁用)
|
- [x] @Bot 插件冲突检测 (会在本群发送一条消息并在约 1s 后撤回以检测其它同类 bot 中已启用的插件并禁用)
|
||||||
- **定时指令触发器** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/job"`
|
- **定时指令触发器** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/job"`
|
||||||
- [x] 记录以"完全匹配关键词"触发的指令
|
- [x] 记录以"完全匹配关键词"触发的(代表我执行的)指令
|
||||||
- [x] 取消以"完全匹配关键词"触发的指令
|
- [x] 取消以"完全匹配关键词"触发的(代表我执行的)指令
|
||||||
- [x] 记录在"cron"触发的指令
|
- [x] 记录在"cron"触发的指令
|
||||||
- [x] 取消在"cron"触发的指令
|
- [x] 取消在"cron"触发的指令
|
||||||
- [x] 查看所有触发指令
|
- [x] 查看所有触发指令
|
||||||
- [x] 查看在"cron"触发的指令
|
- [x] 查看在"cron"触发的指令
|
||||||
- [x] 查看以"完全匹配关键词"触发的指令
|
- [x] 查看以"完全匹配关键词"触发的(代表我执行的)指令
|
||||||
- [x] 注入指令结果:任意指令
|
- [x] 注入指令结果:任意指令
|
||||||
- [x] 执行指令:任意指令
|
- [x] 执行指令:任意指令
|
||||||
- 注:任意指令可以使用形如`?::参数1提示语::1!`,`?::参数2提示语::2!`,`?::?可选参数3提示语,不回答将填入空值::2!`的未定参数,在注入时一一匹配
|
- 注:任意指令可以使用形如`?::参数1提示语::1!`,`?::参数2提示语::2!`,`?::?可选参数3提示语,不回答将填入空值::3!`,`!::从url获取的参数::4!`,`!::?可选的从url获取的参数,出错将填入空值::5!`的未定参数,在注入时一一匹配
|
||||||
- 一些示例
|
- 一些示例
|
||||||
> 每日9:30推送摸鱼人日历
|
> 每日9:30推送摸鱼人日历
|
||||||
```
|
```
|
||||||
@ -107,8 +107,17 @@ if random() > 0.5: print('您最终会选?::请输入您的选择1::1!')
|
|||||||
else: print('您最终会选?::请输入您的选择2::2!')
|
else: print('您最终会选?::请输入您的选择2::2!')
|
||||||
简易的选择困难症助手
|
简易的选择困难症助手
|
||||||
```
|
```
|
||||||

|
> 自行编写随机b站404页趣图插件
|
||||||

|
```python
|
||||||
|
记录以"随机b站404页趣图"触发的代表我执行的指令
|
||||||
|
注入指令结果:>runcoderaw py
|
||||||
|
import json
|
||||||
|
j = json.loads(r'''!::https://api.iyk0.com/bili_chart::1!''')
|
||||||
|
print("run[CQ:image,file="+j["img"]+"]")
|
||||||
|
随机b站404页趣图
|
||||||
|
```
|
||||||
|

|
||||||
|
|
||||||
- **聊天** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/chat"`
|
- **聊天** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/chat"`
|
||||||
- [x] [BOT名字]
|
- [x] [BOT名字]
|
||||||
- [x] [戳一戳BOT]
|
- [x] [戳一戳BOT]
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/FloatTech/zbputils/ctxext"
|
"github.com/FloatTech/zbputils/ctxext"
|
||||||
"github.com/FloatTech/zbputils/process"
|
"github.com/FloatTech/zbputils/process"
|
||||||
"github.com/FloatTech/zbputils/vevent"
|
"github.com/FloatTech/zbputils/vevent"
|
||||||
|
"github.com/FloatTech/zbputils/web"
|
||||||
"github.com/fumiama/cron"
|
"github.com/fumiama/cron"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
@ -65,6 +66,12 @@ func init() {
|
|||||||
matchers[c.ID] = getmatcher(m)
|
matchers[c.ID] = getmatcher(m)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if strings.HasPrefix(c.Cron, "sm:") {
|
||||||
|
m := en.OnFullMatch(c.Cron[3:] /* skip fm: */).SetBlock(true)
|
||||||
|
m.Handle(superuserhandler(c))
|
||||||
|
matchers[c.ID] = getmatcher(m)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
eid, err := process.CronTab.AddFunc(c.Cron, inject(id, []byte(c.Cmd)))
|
eid, err := process.CronTab.AddFunc(c.Cron, inject(id, []byte(c.Cmd)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -107,6 +114,22 @@ func init() {
|
|||||||
}
|
}
|
||||||
ctx.SendChain(message.Text("成功!"))
|
ctx.SendChain(message.Text("成功!"))
|
||||||
})
|
})
|
||||||
|
en.OnRegex(`^记录以"(.*)"触发的代表我执行的指令$`, zero.SuperUserPermission, islonotnil, isfirstregmatchnotnil, logevent).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||||
|
cron := "sm:" + ctx.State["regex_matched"].([]string)[1]
|
||||||
|
command := ctx.State["job_raw_event"].(string)
|
||||||
|
logrus.Debugln("[job] get cmd:", command)
|
||||||
|
c := &cmd{
|
||||||
|
ID: idof(cron, command),
|
||||||
|
Cron: cron,
|
||||||
|
Cmd: command,
|
||||||
|
}
|
||||||
|
err := registercmd(ctx.Event.SelfID, c)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("ERROR:", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.SendChain(message.Text("成功!"))
|
||||||
|
})
|
||||||
en.OnRegex(`^取消在"(.*)"触发的指令$`, ctxext.UserOrGrpAdmin, islonotnil, isfirstregmatchnotnil).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
en.OnRegex(`^取消在"(.*)"触发的指令$`, ctxext.UserOrGrpAdmin, islonotnil, isfirstregmatchnotnil).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||||
cron := ctx.State["regex_matched"].([]string)[1]
|
cron := ctx.State["regex_matched"].([]string)[1]
|
||||||
err := rmcmd(ctx.Event.SelfID, ctx.Event.UserID, cron)
|
err := rmcmd(ctx.Event.SelfID, ctx.Event.UserID, cron)
|
||||||
@ -116,8 +139,15 @@ func init() {
|
|||||||
}
|
}
|
||||||
ctx.SendChain(message.Text("成功!"))
|
ctx.SendChain(message.Text("成功!"))
|
||||||
})
|
})
|
||||||
en.OnRegex(`^取消以"(.*)"触发的指令$`, zero.SuperUserPermission, islonotnil, isfirstregmatchnotnil).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
en.OnRegex(`^取消以"(.*)"触发的(代表我执行的)?指令$`, zero.SuperUserPermission, islonotnil, isfirstregmatchnotnil).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||||
cron := "fm:" + ctx.State["regex_matched"].([]string)[1]
|
issu := ctx.State["regex_matched"].([]string)[2] != ""
|
||||||
|
cron := ""
|
||||||
|
if issu {
|
||||||
|
cron = "sm:"
|
||||||
|
} else {
|
||||||
|
cron = "fm:"
|
||||||
|
}
|
||||||
|
cron += ctx.State["regex_matched"].([]string)[1]
|
||||||
err := delcmd(ctx.Event.SelfID, cron)
|
err := delcmd(ctx.Event.SelfID, cron)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.SendChain(message.Text("ERROR:", err))
|
ctx.SendChain(message.Text("ERROR:", err))
|
||||||
@ -168,10 +198,17 @@ func init() {
|
|||||||
}
|
}
|
||||||
ctx.SendChain(message.Text(lst))
|
ctx.SendChain(message.Text(lst))
|
||||||
})
|
})
|
||||||
en.OnRegex(`^查看以"(.*)"触发的指令$`, zero.SuperUserPermission, islonotnil, isfirstregmatchnotnil).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
en.OnRegex(`^查看以"(.*)"触发的(代表我执行的)?指令$`, zero.SuperUserPermission, islonotnil, isfirstregmatchnotnil).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||||
c := &cmd{}
|
c := &cmd{}
|
||||||
ids := strconv.FormatInt(ctx.Event.SelfID, 36)
|
ids := strconv.FormatInt(ctx.Event.SelfID, 36)
|
||||||
cron := "fm:" + ctx.State["regex_matched"].([]string)[1]
|
issu := ctx.State["regex_matched"].([]string)[2] != ""
|
||||||
|
cron := ""
|
||||||
|
if issu {
|
||||||
|
cron = "sm:"
|
||||||
|
} else {
|
||||||
|
cron = "fm:"
|
||||||
|
}
|
||||||
|
cron += ctx.State["regex_matched"].([]string)[1]
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
defer mu.Unlock()
|
defer mu.Unlock()
|
||||||
n, err := db.Count(ids)
|
n, err := db.Count(ids)
|
||||||
@ -193,7 +230,9 @@ func init() {
|
|||||||
en.OnPrefix("执行指令:", ctxext.UserOrGrpAdmin, islonotnil, func(ctx *zero.Ctx) bool {
|
en.OnPrefix("执行指令:", ctxext.UserOrGrpAdmin, islonotnil, func(ctx *zero.Ctx) bool {
|
||||||
return ctx.State["args"].(string) != ""
|
return ctx.State["args"].(string) != ""
|
||||||
}, parseArgs).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
}, parseArgs).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||||
inject(ctx.Event.SelfID, binary.StringToBytes(strings.ReplaceAll(ctx.Event.RawEvent.Raw, "执行指令:", "")))()
|
ev := strings.ReplaceAll(ctx.Event.RawEvent.Raw, "执行指令:", "")
|
||||||
|
logrus.Debugln("[job] inject:", ev)
|
||||||
|
inject(ctx.Event.SelfID, binary.StringToBytes(ev))()
|
||||||
})
|
})
|
||||||
en.OnPrefix("注入指令结果:", ctxext.UserOrGrpAdmin, islonotnil, func(ctx *zero.Ctx) bool {
|
en.OnPrefix("注入指令结果:", ctxext.UserOrGrpAdmin, islonotnil, func(ctx *zero.Ctx) bool {
|
||||||
return ctx.State["args"].(string) != ""
|
return ctx.State["args"].(string) != ""
|
||||||
@ -263,8 +302,12 @@ func addcmd(bot int64, c *cmd) error {
|
|||||||
func registercmd(bot int64, c *cmd) error {
|
func registercmd(bot int64, c *cmd) error {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
defer mu.Unlock()
|
defer mu.Unlock()
|
||||||
m := en.OnFullMatch(c.Cron[3:] /* skip fm: */).SetBlock(true)
|
m := en.OnFullMatch(c.Cron[3:] /* skip fm: or sm: */).SetBlock(true)
|
||||||
m.Handle(generalhandler(c))
|
if strings.HasPrefix(c.Cron, "sm:") {
|
||||||
|
m.Handle(superuserhandler(c))
|
||||||
|
} else {
|
||||||
|
m.Handle(generalhandler(c))
|
||||||
|
}
|
||||||
matchers[c.ID] = getmatcher(m)
|
matchers[c.ID] = getmatcher(m)
|
||||||
return db.Insert(strconv.FormatInt(bot, 36), c)
|
return db.Insert(strconv.FormatInt(bot, 36), c)
|
||||||
}
|
}
|
||||||
@ -288,6 +331,32 @@ func generalhandler(c *cmd) zero.Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func superuserhandler(c *cmd) zero.Handler {
|
||||||
|
e := &zero.Event{Sender: new(zero.User)}
|
||||||
|
err := json.Unmarshal(binary.StringToBytes(c.Cmd), e)
|
||||||
|
return func(ctx *zero.Ctx) {
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("ERROR:", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Event.UserID = e.UserID
|
||||||
|
ctx.Event.RawMessage = e.RawMessage
|
||||||
|
ctx.Event.Sender = e.Sender
|
||||||
|
ctx.Event.NativeMessage = e.NativeMessage
|
||||||
|
vev, cl := binary.OpenWriterF(func(w *binary.Writer) {
|
||||||
|
err = json.NewEncoder(w).Encode(ctx.Event)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
cl()
|
||||||
|
ctx.SendChain(message.Text("ERROR:", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
logrus.Debugln("[job] inject:", binary.BytesToString(vev))
|
||||||
|
inject(ctx.Event.SelfID, vev)()
|
||||||
|
cl()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func rmcmd(bot, caller int64, cron string) error {
|
func rmcmd(bot, caller int64, cron string) error {
|
||||||
c := &cmd{}
|
c := &cmd{}
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
@ -345,7 +414,8 @@ func delcmd(bot int64, cron string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseArgs(ctx *zero.Ctx) bool {
|
func parseArgs(ctx *zero.Ctx) bool {
|
||||||
if !strings.Contains(ctx.State["args"].(string), "?::") {
|
cmds := ctx.State["args"].(string)
|
||||||
|
if !strings.Contains(cmds, "?::") && !strings.Contains(cmds, "!::") {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
args := make(map[int]string)
|
args := make(map[int]string)
|
||||||
@ -394,6 +464,66 @@ func parseArgs(ctx *zero.Ctx) bool {
|
|||||||
}
|
}
|
||||||
ctx.Event.RawEvent.Raw = ctx.Event.RawEvent.Raw[:start] + arr + ctx.Event.RawEvent.Raw[numend+1:]
|
ctx.Event.RawEvent.Raw = ctx.Event.RawEvent.Raw[:start] + arr + ctx.Event.RawEvent.Raw[numend+1:]
|
||||||
}
|
}
|
||||||
|
args = make(map[int]string)
|
||||||
|
for strings.Contains(ctx.Event.RawEvent.Raw, "!::") {
|
||||||
|
start := strings.Index(ctx.Event.RawEvent.Raw, "!::")
|
||||||
|
msgend := strings.Index(ctx.Event.RawEvent.Raw[start+3:], "::")
|
||||||
|
if msgend < 0 {
|
||||||
|
ctx.SendChain(message.Text("ERROR:找不到结束的::"))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
msgend += start + 3
|
||||||
|
numend := strings.Index(ctx.Event.RawEvent.Raw[msgend+2:], "!")
|
||||||
|
if numend <= 0 {
|
||||||
|
ctx.SendChain(message.Text("ERROR:找不到结束的!"))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
numend += msgend + 2
|
||||||
|
logrus.Debugln("[job]", start, msgend, numend)
|
||||||
|
u := ctx.Event.RawEvent.Raw[start+3 : msgend]
|
||||||
|
if u == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
arg, err := strconv.Atoi(ctx.Event.RawEvent.Raw[msgend+2 : numend])
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("ERROR:", err))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
arr, ok := args[arg]
|
||||||
|
if !ok {
|
||||||
|
isnilable := u[0] == '?'
|
||||||
|
if isnilable {
|
||||||
|
u = u[1:]
|
||||||
|
if u == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b, err := web.GetData(u)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("ERROR:", err))
|
||||||
|
if !isnilable {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(b) > 0 {
|
||||||
|
type fakejson struct {
|
||||||
|
Arg string `json:"arg"`
|
||||||
|
}
|
||||||
|
f := fakejson{Arg: binary.BytesToString(b)}
|
||||||
|
w := binary.SelectWriter()
|
||||||
|
defer binary.PutWriter(w)
|
||||||
|
json.NewEncoder(w).Encode(&f)
|
||||||
|
arr = w.String()[8 : w.Len()-3]
|
||||||
|
args[arg] = arr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w := binary.SelectWriter()
|
||||||
|
w.WriteString(ctx.Event.RawEvent.Raw[:start])
|
||||||
|
w.WriteString(arr)
|
||||||
|
w.WriteString(ctx.Event.RawEvent.Raw[numend+1:])
|
||||||
|
ctx.Event.RawEvent.Raw = string(w.Bytes())
|
||||||
|
binary.PutWriter(w)
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -512,11 +512,8 @@ func init() { // 插件主体
|
|||||||
// 运行 CQ 码
|
// 运行 CQ 码
|
||||||
engine.OnRegex(`^run(.*)$`, zero.SuperUserPermission).SetBlock(true).
|
engine.OnRegex(`^run(.*)$`, zero.SuperUserPermission).SetBlock(true).
|
||||||
Handle(func(ctx *zero.Ctx) {
|
Handle(func(ctx *zero.Ctx) {
|
||||||
var cmd = ctx.State["regex_matched"].([]string)[1]
|
|
||||||
cmd = strings.ReplaceAll(cmd, "[", "[")
|
|
||||||
cmd = strings.ReplaceAll(cmd, "]", "]")
|
|
||||||
// 可注入,权限为主人
|
// 可注入,权限为主人
|
||||||
ctx.Send(cmd)
|
ctx.Send(message.UnescapeCQCodeText(ctx.State["regex_matched"].([]string)[1]))
|
||||||
})
|
})
|
||||||
// 根据 gist 自动同意加群
|
// 根据 gist 自动同意加群
|
||||||
// 加群请在github新建一个gist,其文件名为本群群号的字符串的md5(小写),内容为一行,是当前unix时间戳(10分钟内有效)。
|
// 加群请在github新建一个gist,其文件名为本群群号的字符串的md5(小写),内容为一行,是当前unix时间戳(10分钟内有效)。
|
||||||
|
|||||||
@ -117,7 +117,7 @@ func init() {
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// 执行运行
|
// 执行运行
|
||||||
block := message.UnescapeCQCodeText(ctx.State["regex_matched"].([]string)[3])
|
block := message.UnescapeCQText(ctx.State["regex_matched"].([]string)[3])
|
||||||
switch block {
|
switch block {
|
||||||
case "help":
|
case "help":
|
||||||
ctx.SendChain(
|
ctx.SendChain(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user