+

+
ZeroBot-Plugin
+ ZeroBot-Plugin 是 ZeroBot 的 实用插件合集
+
+[](https://github.com/Yiwen-Chan/OneBot-YaYa)
+[](https://github.com/Mrs4s/go-cqhttp)
+[](https://github.com/takayama-lily/node-onebot)
+[](https://github.com/yyuueexxiinngg/onebot-kotlin)
+
+[](https://goreportcard.com/report/github.com/github.com/Yiwen-Chan/ZeroBot-Plugin)
+[](https://github.com/howmanybots/onebot)
+[](https://github.com/wdvxdr1123/ZeroBot)
+[](https://raw.githubusercontent.com/Yiwen-Chan/ZeroBot-Plugin/master/LICENSE)
+[](https://jq.qq.com/?_wv=1027&k=QMb7x1mM)
+
+
+
+
+### 功能
+- 群管
+ - [x] 禁言[@xxx][分钟]
+ - [x] 解除禁言[@xxx]
+ - [x] 我要自闭 [分钟]
+ - [x] 开启全员禁言
+ - [x] 解除全员禁言
+ - [x] 升为管理[@xxx]
+ - [x] 取消管理[@xxx]
+ - [x] 修改名片[@xxx][xxx]
+ - [x] 修改头衔[@xxx][xxx]
+ - [x] 申请头衔[xxx]
+ - [x] 踢出群聊[@xxx]
+ - [x] 退出群聊[群号]
+ - [x] *入群欢迎
+ - [x] *退群通知
+ - [ ] 同意入群请求
+ - [ ] 同意好友请求
+ - [ ] 撤回[@xxx] [xxx]
+ - [ ] 警告[@xxx]
+ - [x] run[xxx]
+- 涩图
+ - [x] 来份[涩图/二次元/风景]
+ - [x] 添加[涩图/二次元/风景][P站图片ID]
+ - [x] 删除[涩图/二次元/风景][P站图片ID]
+ - [x] setu -s
+ - [x] setu -x
+ - [x] setu -p
+- 点歌
+ - [x] 点歌[xxx]
+- TODO...
+
+### 使用方法
+
+本项目符合 [OneBot](https://github.com/howmanybots/onebot) 标准,可基于以下项目与机器人框架/平台进行交互
+| 项目地址 | 平台 | 核心作者 | 备注 |
+| --- | --- | --- | --- |
+| [Yiwen-Chan/OneBot-YaYa](https://github.com/Yiwen-Chan/OneBot-YaYa) | [先驱](https://www.xianqubot.com/) | kanri | |
+| [richardchien/coolq-http-api](https://github.com/richardchien/coolq-http-api) | CKYU | richardchien | 可在 Mirai 平台使用 [mirai-native](https://github.com/iTXTech/mirai-native) 加载 |
+| [Mrs4s/go-cqhttp](https://github.com/Mrs4s/go-cqhttp) | [MiraiGo](https://github.com/Mrs4s/MiraiGo) | Mrs4s | |
+| [yyuueexxiinngg/cqhttp-mirai](https://github.com/yyuueexxiinngg/cqhttp-mirai) | [Mirai](https://github.com/mamoe/mirai) | yyuueexxiinngg | |
+| [takayama-lily/onebot](https://github.com/takayama-lily/onebot) | [OICQ](https://github.com/takayama-lily/oicq) | takayama | |
+
+#### 本地编译
+1. 下载安装 [Go](https://studygolang.com/dl/golang/go1.16.2.windows-amd64.msi) 环境
+2. 下载安装 [TDM-GCC](https://github.com/jmeubank/tdm-gcc/releases),并添加到环境变量
+3. [clone](https://github.com/Yiwen-Chan/ZeroBot-Plugin/archive/master.zip) 本项目,本地解压
+4. 编辑 main.go 文件,内容按需修改
+5. 双击点击 build.bat 文件
+6. 运行框架,并同时运行本插件
+
+#### 利用 Actions 编译 (推荐)
+1. 点击右上角 Fork 本项目,并转跳到自己 Fork 的仓库
+2. 点击仓库上方的 Actions 按钮,确认使用 Actions
+3. 编辑 main.go 文件,内容按需修改,返回仓库
+4. 点击 Actions 按钮,等待编译完成,在 Actions 里下载编译好的文件
+5. 运行框架,并同时运行本插件
+
diff --git a/app.go b/app.go
deleted file mode 100644
index 4e4f8109ae..0000000000
--- a/app.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package main
-
-import (
- "fmt"
-
- m "gm/modules"
- "gm/utils"
-
- zero "github.com/wdvxdr1123/ZeroBot"
-)
-
-var Conf = &utils.YamlConfig{}
-
-func main() {
- zero.Run(zero.Option{
- Host: Conf.Host,
- Port: Conf.Port,
- AccessToken: Conf.AccessToken,
- NickName: []string{"GroupManager"},
- CommandPrefix: "/",
- SuperUsers: Conf.Master,
- })
- select {}
-}
-
-func init() {
- fmt.Println(`
-====================[GroupManager]====================
-* Mirai + ZeroBot + Golang
-* Copyright © 2018-2020 Kanri, All Rights Reserved
-* Project: https://github.com/Yiwen-Chan/GroupManager
-=======================================================
-`)
- Conf = utils.Load("./data/config.yml")
- m.Conf = Conf
- fmt.Println("[GroupManager] 有需要请按 GitHub 项目上描述的方法修改配置文件")
-}
diff --git a/build.bat b/build.bat
new file mode 100644
index 0000000000..4ea29e5924
--- /dev/null
+++ b/build.bat
@@ -0,0 +1,6 @@
+go version
+gcc -v
+go env -w GOPROXY=https://goproxy.cn,direct
+go env -w GO111MODULE=auto
+go build -ldflags="-s -w" -o ZeroBot-Plugin-windows.exe
+pause
diff --git a/chat/chat.go b/chat/chat.go
new file mode 100644
index 0000000000..b9820c6ee1
--- /dev/null
+++ b/chat/chat.go
@@ -0,0 +1,17 @@
+package chat
+
+import (
+ "time"
+
+ zero "github.com/wdvxdr1123/ZeroBot"
+)
+
+func init() { // 插件主体
+ // 戳一戳
+ zero.On("notice/notify/poke", zero.OnlyToMe).SetBlock(false).SetPriority(0).
+ Handle(func(ctx *zero.Ctx) {
+ time.Sleep(time.Second * 1)
+ ctx.Send("请不要戳我 >_<")
+ return
+ })
+}
diff --git a/chat/learn.go b/chat/learn.go
new file mode 100644
index 0000000000..ce7919f682
--- /dev/null
+++ b/chat/learn.go
@@ -0,0 +1,56 @@
+package chat
+
+import (
+ zero "github.com/wdvxdr1123/ZeroBot"
+ yaml "gopkg.in/yaml.v2"
+ "io/ioutil"
+ "math/rand"
+ "os"
+ "strings"
+ "time"
+)
+
+func init() {
+ botName := "小沫" //填写机器人的名称
+ myData := map[string][]string{}
+ yaml.Unmarshal(FileRead("chat\\myData.yaml"),&myData)
+
+ zero.OnRegex("^(.+?)$").Handle(func(ctx *zero.Ctx) {
+
+ text := ctx.State["regex_matched"].([]string)[1]
+ if strings.Index(text,botName+"跟我学")==0{
+ kv := strings.Split(text[len(botName+"跟我学 "):len(text)]," ")
+ if len(kv)>1 && kv[1]!=""{
+ myData[kv[0]] = kv[1:len(kv)]
+ content,_ := yaml.Marshal(myData)
+ FileWrite("chat\\myData.yaml",content)
+ ctx.Send(botName + "学会了奇怪的新知识["+kv[0]+"]:\n- "+strings.Join(kv[1:len(kv)],"\n- "))
+ }else {
+ ctx.Send("你想让"+botName+"学些什么呀?")
+ }
+ return
+ }
+
+ for k,vs := range myData{
+ if strings.Index(text,k) != -1{
+ rand.Seed(time.Now().Unix())
+ ctx.Send(vs[rand.Intn(len(vs))])
+ return
+ }
+ }
+ })
+}
+
+func FileRead(path string) []byte {
+ //读取文件数据
+ file,_ := os.Open(path)
+ defer file.Close()
+ data,_ := ioutil.ReadAll(file)
+ return data
+}
+
+func FileWrite(path string,content []byte) int {
+ //写入文件数据
+ ioutil.WriteFile(path,content,0644)
+ return len(content)
+}
diff --git a/github/repo_searcher.go b/github/repo_searcher.go
new file mode 100644
index 0000000000..d67f5d7fe6
--- /dev/null
+++ b/github/repo_searcher.go
@@ -0,0 +1,78 @@
+package github
+
+import (
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "strings"
+
+ "github.com/tidwall/gjson"
+ zero "github.com/wdvxdr1123/ZeroBot"
+)
+
+func init() { // 插件主体
+ zero.OnRegex(`>G\s(.*)`).SetBlock(true).SetPriority(0).
+ Handle(func(ctx *zero.Ctx) {
+ api, _ := url.Parse("https://api.github.com/search/repositories")
+ params := url.Values{}
+ params.Set("q", ctx.State["regex_matched"].([]string)[1])
+ api.RawQuery = params.Encode()
+ link := api.String()
+
+ client := &http.Client{}
+
+ req, err := http.NewRequest("GET", link, nil)
+ if err != nil {
+ ctx.Send(fmt.Sprintf("ERROR: %v", err))
+ return
+ }
+ req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36")
+ resp, err := client.Do(req)
+ if err != nil {
+ ctx.Send(fmt.Sprintf("ERROR: %v", err))
+ return
+ }
+ defer resp.Body.Close()
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ ctx.Send(fmt.Sprintf("ERROR: %v", err))
+ return
+ }
+
+ if code := resp.StatusCode; code != 200 {
+ // 如果返回不是200则立刻抛出错误
+ ctx.Send(fmt.Sprintf("ERROR: code %d", code))
+ return
+ }
+ count := gjson.ParseBytes(body).Get("total_count").Int()
+ if count == 0 {
+ ctx.Send("没有找到这样的仓库")
+ return
+ }
+ repo := gjson.ParseBytes(body).Get("items.0")
+ language := repo.Get("language").Str
+ if language == "" {
+ language = "None"
+ }
+ license := strings.ToUpper(repo.Get("license.key").Str)
+ if license == "" {
+ license = "None"
+ }
+ id := ctx.Send(fmt.Sprintf(
+ "%s: \nDescription: %s\nStar/Fork/Issue: %d/%d/%d\nLanguage: %s\nLicense: %s\nLast pushed: %s\nJump: %s",
+ repo.Get("full_name").Str,
+ repo.Get("description").Str,
+ repo.Get("watchers").Int(),
+ repo.Get("forks").Int(),
+ repo.Get("open_issues").Int(),
+ language,
+ license,
+ repo.Get("updated_at").Str,
+ repo.Get("html_url").Str,
+ ))
+ if id == 0 {
+ ctx.Send("ERROR: 可能被风控,发送失败")
+ }
+ })
+}
diff --git a/go.mod b/go.mod
index 8131e6c931..6b9fd7be9c 100644
--- a/go.mod
+++ b/go.mod
@@ -1,9 +1,12 @@
-module gm
+module github.com/Yiwen-Chan/ZeroBot-Plugin
-go 1.14
+go 1.15
require (
- github.com/wdvxdr1123/ZeroBot v0.0.0-20201129064504-07d9e1b5400f
- gopkg.in/yaml.v2 v2.4.0
- gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
+ github.com/antchfx/htmlquery v1.2.3
+ github.com/mattn/go-sqlite3 v1.14.6
+ github.com/sirupsen/logrus v1.8.0
+ github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816
+ github.com/tidwall/gjson v1.7.4
+ github.com/wdvxdr1123/ZeroBot v1.0.3-0.20210407015205-7cb1b23c5417
)
diff --git a/go.sum b/go.sum
index f7cef80532..5e3cf825f5 100644
--- a/go.sum
+++ b/go.sum
@@ -1,35 +1,76 @@
+github.com/antchfx/htmlquery v1.2.3 h1:sP3NFDneHx2stfNXCKbhHFo8XgNjCACnU/4AO5gWz6M=
+github.com/antchfx/htmlquery v1.2.3/go.mod h1:B0ABL+F5irhhMWg54ymEZinzMSi0Kt3I2if0BLYa3V0=
+github.com/antchfx/xpath v1.1.6 h1:6sVh6hB5T6phw1pFpHRQ+C4bd8sNI+O58flqtg7h0R0=
+github.com/antchfx/xpath v1.1.6/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk=
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=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
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/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
+github.com/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
+github.com/magefile/mage v1.11.0 h1:C/55Ywp9BpgVVclD3lRnSYCwXTYxmSppIgLeDYlNuls=
+github.com/magefile/mage v1.11.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
+github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
+github.com/mattn/go-sqlite3 v1.14.6/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/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
+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 h1:6Xjqolv/0DDdUqlpnsTomXQvjvvkz7Ux7TcMALvozEw=
+github.com/modern-go/reflect2 v1.0.2-0.20210109003243-333559e1834b/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
-github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
-github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/sirupsen/logrus v1.8.0 h1:nfhvjKcUMhBMVqbKHJlk5RPrrfYr/NMo3692g0dwfWU=
+github.com/sirupsen/logrus v1.8.0/go.mod h1:4GuYW9TZmE769R5STWrRakJc4UqQ3+QQ95fyz7ENv1A=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 h1:J6v8awz+me+xeb/cUTotKgceAYouhIB3pjzgRd6IlGk=
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816/go.mod h1:tzym/CEb5jnFI+Q0k4Qq3+LvRF4gO3E2pxS8fHP8jcA=
-github.com/tidwall/gjson v1.6.1 h1:LRbvNuNuvAiISWg6gxLEFuCe72UKy5hDqhxW/8183ws=
-github.com/tidwall/gjson v1.6.1/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0=
-github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc=
-github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
-github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU=
+github.com/tidwall/gjson v1.6.8/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI=
+github.com/tidwall/gjson v1.7.4 h1:19cchw8FOxkG5mdLRkGf9jqIqEyqdZhPqW60XfyFxk8=
+github.com/tidwall/gjson v1.7.4/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
+github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
+github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
-github.com/wdvxdr1123/ZeroBot v0.0.0-20201129064504-07d9e1b5400f h1:06qEGANaKnXdJShXGEbD70F77C7AQAXA0nkQVdyORHc=
-github.com/wdvxdr1123/ZeroBot v0.0.0-20201129064504-07d9e1b5400f/go.mod h1:e92qGONnOry8XSfaUUlG7OhT9gyD839P8oZ2wfPe60w=
+github.com/tidwall/pretty v1.0.5/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8=
+github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+github.com/wdvxdr1123/ZeroBot v1.0.3-0.20210407015205-7cb1b23c5417 h1:L0yqzJ6c6Uh8ZStkMjO5G30SY5ZjD5t2d6KvXWDT2h4=
+github.com/wdvxdr1123/ZeroBot v1.0.3-0.20210407015205-7cb1b23c5417/go.mod h1:BZQGqjw0PX8Aojj3QnVHTXIH9YOEc8ZvLLUosM39Gho=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20200421231249-e086a090c8fd h1:QPwSajcTUrFriMF1nJ3XzgoqakqQEsnZf9LdXdi2nkI=
+golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201029080932-201ba4db2418 h1:HlFl4V6pEMziuLXyRkm5BIYq1y1GAbb02pRlWvI54OM=
-golang.org/x/sys v0.0.0-20201029080932-201ba4db2418/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
\ No newline at end of file
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43 h1:SgQ6LNaYJU0JIuEHv9+s6EbhSCwYeAf5Yvj6lpYlqAE=
+golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+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=
diff --git a/main.go b/main.go
new file mode 100644
index 0000000000..3fca8b5148
--- /dev/null
+++ b/main.go
@@ -0,0 +1,46 @@
+package main
+
+import (
+ "fmt"
+
+ log "github.com/sirupsen/logrus"
+ easy "github.com/t-tomalak/logrus-easy-formatter"
+ zero "github.com/wdvxdr1123/ZeroBot"
+ "github.com/wdvxdr1123/ZeroBot/driver"
+
+ _ "github.com/Yiwen-Chan/ZeroBot-Plugin/chat"
+ _ "github.com/Yiwen-Chan/ZeroBot-Plugin/github"
+ _ "github.com/Yiwen-Chan/ZeroBot-Plugin/manager"
+ _ "github.com/Yiwen-Chan/ZeroBot-Plugin/music"
+ setutime "github.com/Yiwen-Chan/ZeroBot-Plugin/setutime"
+)
+
+func init() {
+ log.SetFormatter(&easy.Formatter{
+ TimestampFormat: "2006-01-02 15:04:05",
+ LogFormat: "[zero][%time%][%lvl%]: %msg% \n",
+ })
+ log.SetLevel(log.DebugLevel)
+
+ setutime.CACHEGROUP = 868047498 // 涩图缓冲群,必须修改
+ setutime.PoolList = []string{"涩图", "二次元", "风景", "车万"} // 涩图类型,可以不修改
+}
+
+func main() {
+ fmt.Printf(`
+====================[ZeroBot-Plugin]====================
+* OneBot + ZeroBot + Golang
+* Copyright © 2018-2020 Kanri, All Rights Reserved
+* Project: https://github.com/Yiwen-Chan/ZeroBot-Plugin
+========================================================
+`)
+ zero.Run(zero.Config{
+ NickName: []string{"bot"},
+ CommandPrefix: "/",
+ SuperUsers: []string{"825111790", "213864964"}, // 必须修改,否则无权限
+ Driver: []zero.Driver{
+ driver.NewWebSocketClient("127.0.0.1", "6700", ""),
+ },
+ })
+ select {}
+}
diff --git a/manager/manager.go b/manager/manager.go
new file mode 100644
index 0000000000..7c6bda4641
--- /dev/null
+++ b/manager/manager.go
@@ -0,0 +1,254 @@
+package manager
+
+import (
+ "strings"
+
+ "github.com/Yiwen-Chan/ZeroBot-Plugin/manager/utils"
+ zero "github.com/wdvxdr1123/ZeroBot"
+)
+
+func init() { // 插件主体
+ // 菜单
+ zero.OnFullMatch("群管系统").SetBlock(true).SetPriority(40).
+ Handle(func(ctx *zero.Ctx) {
+ ctx.Send(`====群管====
+- 禁言@QQ 1
+- 解除禁言 @QQ
+- 我要自闭 1
+- 开启全员禁言
+- 解除全员禁言
+- 升为管理@QQ
+- 取消管理@QQ
+- 修改名片@QQ XXX
+- 修改头衔@QQ XXX
+- 申请头衔 XXX
+- 踢出群聊@QQ
+- 退出群聊 1234
+- 群聊转发 1234 XXX
+- 私聊转发 0000 XXX`)
+ return
+ })
+ // 升为管理
+ zero.OnRegex(`^升为管理.*?(\d+)`, zero.OnlyGroup, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
+ Handle(func(ctx *zero.Ctx) {
+ ctx.SetGroupAdmin(
+ ctx.Event.GroupID,
+ utils.Str2Int(ctx.State["regex_matched"].([]string)[1]), // 被升为管理的人的qq
+ true,
+ )
+ nickname := ctx.GetGroupMemberInfo( // 被升为管理的人的昵称
+ ctx.Event.GroupID,
+ utils.Str2Int(ctx.State["regex_matched"].([]string)[1]), // 被升为管理的人的qq
+ false,
+ ).Get("nickname").Str
+ ctx.Send(nickname + " 升为了管理~")
+ return
+ })
+ // 取消管理
+ zero.OnRegex(`^取消管理.*?(\d+)`, zero.OnlyGroup, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
+ Handle(func(ctx *zero.Ctx) {
+ ctx.SetGroupAdmin(
+ ctx.Event.GroupID,
+ utils.Str2Int(ctx.State["regex_matched"].([]string)[1]), // 被取消管理的人的qq
+ false,
+ )
+ nickname := ctx.GetGroupMemberInfo( // 被取消管理的人的昵称
+ ctx.Event.GroupID,
+ utils.Str2Int(ctx.State["regex_matched"].([]string)[1]), // 被取消管理的人的qq
+ false,
+ ).Get("nickname").Str
+ ctx.Send("残念~ " + nickname + " 暂时失去了管理员的资格")
+ return
+ })
+ // 踢出群聊
+ zero.OnRegex(`^踢出群聊.*?(\d+)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
+ Handle(func(ctx *zero.Ctx) {
+ ctx.SetGroupKick(
+ ctx.Event.GroupID,
+ utils.Str2Int(ctx.State["regex_matched"].([]string)[1]), // 被踢出群聊的人的qq
+ false,
+ )
+ nickname := ctx.GetGroupMemberInfo( // 被踢出群聊的人的昵称
+ ctx.Event.GroupID,
+ utils.Str2Int(ctx.State["regex_matched"].([]string)[1]), // 被踢出群聊的人的qq
+ false,
+ ).Get("nickname").Str
+ ctx.Send("残念~ " + nickname + " 被放逐")
+ return
+ })
+ // 退出群聊
+ zero.OnRegex(`^退出群聊.*?(\d+)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
+ Handle(func(ctx *zero.Ctx) {
+ ctx.SetGroupLeave(
+ utils.Str2Int(ctx.State["regex_matched"].([]string)[1]), // 要退出的群的群号
+ true,
+ )
+ return
+ })
+ // 开启全体禁言
+ zero.OnRegex(`^开启全员禁言$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
+ Handle(func(ctx *zero.Ctx) {
+ ctx.SetGroupWholeBan(
+ ctx.Event.GroupID,
+ true,
+ )
+ ctx.Send("全员自闭开始~")
+ return
+ })
+ // 解除全员禁言
+ zero.OnRegex(`^解除全员禁言$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
+ Handle(func(ctx *zero.Ctx) {
+ ctx.SetGroupWholeBan(
+ ctx.Event.GroupID,
+ false,
+ )
+ ctx.Send("全员自闭结束~")
+ return
+ })
+ // 禁言
+ zero.OnRegex(`^禁言.*?(\d+).*?\s(\d+)(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
+ Handle(func(ctx *zero.Ctx) {
+ duration := utils.Str2Int(ctx.State["regex_matched"].([]string)[2])
+ switch ctx.State["regex_matched"].([]string)[3] {
+ case "分钟":
+ //
+ case "小时":
+ duration = duration * 60
+ case "天":
+ duration = duration * 60 * 24
+ default:
+ //
+ }
+ if duration >= 43200 {
+ duration = 43199 // qq禁言最大时长为一个月
+ }
+ ctx.SetGroupBan(
+ ctx.Event.GroupID,
+ utils.Str2Int(ctx.State["regex_matched"].([]string)[1]), // 要禁言的人的qq
+ duration*60, // 要禁言的时间(分钟)
+ )
+ ctx.Send("小黑屋收留成功~")
+ return
+ })
+ // 解除禁言
+ zero.OnRegex(`^解除禁言.*?(\d+)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
+ Handle(func(ctx *zero.Ctx) {
+ ctx.SetGroupBan(
+ ctx.Event.GroupID,
+ utils.Str2Int(ctx.State["regex_matched"].([]string)[1]), // 要解除禁言的人的qq
+ 0,
+ )
+ ctx.Send("小黑屋释放成功~")
+ return
+ })
+ // 自闭禁言
+ zero.OnRegex(`^我要自闭.*?(\d+)(.*)`, zero.OnlyGroup).SetBlock(true).SetPriority(40).
+ Handle(func(ctx *zero.Ctx) {
+ duration := utils.Str2Int(ctx.State["regex_matched"].([]string)[1])
+ switch ctx.State["regex_matched"].([]string)[2] {
+ case "分钟":
+ //
+ case "小时":
+ duration = duration * 60
+ case "天":
+ duration = duration * 60 * 24
+ default:
+ //
+ }
+ if duration >= 43200 {
+ duration = 43199 // qq禁言最大时长为一个月
+ }
+ ctx.SetGroupBan(
+ ctx.Event.GroupID,
+ ctx.Event.UserID,
+ duration*60, // 要自闭的时间(分钟)
+ )
+ ctx.Send("那我就不手下留情了~")
+ return
+ })
+ // 修改名片
+ zero.OnRegex(`^修改名片.*?(\d+).*?\s(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
+ Handle(func(ctx *zero.Ctx) {
+ ctx.SetGroupCard(
+ ctx.Event.GroupID,
+ utils.Str2Int(ctx.State["regex_matched"].([]string)[1]), // 被修改群名片的人
+ ctx.State["regex_matched"].([]string)[2], // 修改成的群名片
+ )
+ ctx.Send("嗯!已经修改了")
+ return
+ })
+ // 修改头衔
+ zero.OnRegex(`^修改头衔.*?(\d+).*?\s(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
+ Handle(func(ctx *zero.Ctx) {
+ ctx.SetGroupSpecialTitle(
+ ctx.Event.GroupID,
+ utils.Str2Int(ctx.State["regex_matched"].([]string)[1]), // 被修改群头衔的人
+ ctx.State["regex_matched"].([]string)[2], // 修改成的群头衔
+ )
+ ctx.Send("嗯!已经修改了")
+ return
+ })
+ // 申请头衔
+ zero.OnRegex(`^申请头衔(.*)`, zero.OnlyGroup).SetBlock(true).SetPriority(40).
+ Handle(func(ctx *zero.Ctx) {
+ ctx.SetGroupSpecialTitle(
+ ctx.Event.GroupID,
+ ctx.Event.UserID, // 被修改群头衔的人
+ ctx.State["regex_matched"].([]string)[1], // 修改成的群头衔
+ )
+ ctx.Send("嗯!不错的头衔呢~")
+ return
+ })
+ // 群聊转发
+ zero.OnRegex(`^群聊转发.*?(\d+)\s(.*)`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
+ Handle(func(ctx *zero.Ctx) {
+ // 对CQ码进行反转义
+ content := ctx.State["regex_matched"].([]string)[2]
+ content = strings.ReplaceAll(content, "[", "[")
+ content = strings.ReplaceAll(content, "]", "]")
+ ctx.SendGroupMessage(
+ utils.Str2Int(ctx.State["regex_matched"].([]string)[1]), // 需要发送的群
+ content, // 需要发送的信息
+ )
+ ctx.Send("📧 --> " + ctx.State["regex_matched"].([]string)[1])
+ return
+ })
+ // 私聊转发
+ zero.OnRegex(`^私聊转发.*?(\d+)\s(.*)`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
+ Handle(func(ctx *zero.Ctx) {
+ // 对CQ码进行反转义
+ content := ctx.State["regex_matched"].([]string)[2]
+ content = strings.ReplaceAll(content, "[", "[")
+ content = strings.ReplaceAll(content, "]", "]")
+ ctx.SendPrivateMessage(
+ utils.Str2Int(ctx.State["regex_matched"].([]string)[1]), // 需要发送的人的qq
+ content, // 需要发送的信息
+ )
+ ctx.Send("📧 --> " + ctx.State["regex_matched"].([]string)[1])
+ return
+ })
+ // 入群欢迎
+ zero.OnNotice().SetBlock(false).SetPriority(40).
+ Handle(func(ctx *zero.Ctx) {
+ if ctx.Event.NoticeType == "group_increase" {
+ ctx.Send("欢迎~")
+ }
+ return
+ })
+ // 退群提醒
+ zero.OnNotice().SetBlock(false).SetPriority(40).
+ Handle(func(ctx *zero.Ctx) {
+ if ctx.Event.NoticeType == "group_decrease" {
+ ctx.Send("有人跑路了~")
+ }
+ return
+ })
+ // 运行 CQ 码
+ zero.OnRegex(`^run(.*)$`, zero.SuperUserPermission).SetBlock(true).SetPriority(0).
+ Handle(func(ctx *zero.Ctx) {
+ var cmd = ctx.State["regex_matched"].([]string)[1]
+ cmd = strings.ReplaceAll(cmd, "[", "[")
+ cmd = strings.ReplaceAll(cmd, "]", "]")
+ ctx.Send(cmd)
+ })
+}
diff --git a/manager/utils/utils.go b/manager/utils/utils.go
new file mode 100644
index 0000000000..b55ffa7bc7
--- /dev/null
+++ b/manager/utils/utils.go
@@ -0,0 +1,15 @@
+package utils
+
+import (
+ "strconv"
+)
+
+func Int2Str(val int64) string {
+ str := strconv.FormatInt(val, 10)
+ return str
+}
+
+func Str2Int(str string) int64 {
+ val, _ := strconv.ParseInt(str, 10, 64)
+ return val
+}
diff --git a/modules/main.go b/modules/main.go
deleted file mode 100644
index 6491dc03eb..0000000000
--- a/modules/main.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package modules
-
-import "gm/utils"
-
-var Conf = &utils.YamlConfig{}
diff --git a/modules/manage.go b/modules/manage.go
deleted file mode 100644
index 6532368e5e..0000000000
--- a/modules/manage.go
+++ /dev/null
@@ -1,67 +0,0 @@
-package modules
-
-import (
- zero "github.com/wdvxdr1123/ZeroBot"
-)
-
-func init() {
- zero.RegisterPlugin(manage{})
-}
-
-type manage struct{}
-
-func (manage) GetPluginInfo() zero.PluginInfo { // 返回插件信息
- return zero.PluginInfo{
- Author: "kanri",
- PluginName: "manage",
- Version: "0.0.1",
- Details: "设置群名片群头衔",
- }
-}
-
-func (manage) Start() { // 插件主体
- promoteManager := zero.OnRegex("^升为管理.*?(\\d+)", zero.OnlyGroup, zero.AdminPermission).
- Handle(
- func(matcher *zero.Matcher, event zero.Event, state zero.State) zero.Response {
- zero.SetGroupAdmin(event.GroupID, GetInt(state, 1), true)
- zero.Send(event, "恭喜~")
- return zero.SuccessResponse
- },
- )
- promoteManager.Priority = 20
- promoteManager.Block = true
-
- cancleManager := zero.OnRegex("^取消管理.*?(\\d+)", zero.OnlyGroup, zero.AdminPermission).
- Handle(
- func(matcher *zero.Matcher, event zero.Event, state zero.State) zero.Response {
- zero.SetGroupAdmin(event.GroupID, GetInt(state, 1), false)
- zero.Send(event, "残念~")
- return zero.SuccessResponse
- },
- )
- cancleManager.Priority = 21
- cancleManager.Block = true
-
- kick := zero.OnRegex("^踢出群聊.*?(\\d+)", zero.OnlyGroup, zero.AdminPermission).
- Handle(
- func(matcher *zero.Matcher, event zero.Event, state zero.State) zero.Response {
- zero.SetGroupKick(event.GroupID, GetInt(state, 1), false)
- zero.Send(event, "残念~")
- return zero.SuccessResponse
- },
- )
- kick.Priority = 22
- kick.Block = true
-
- leave := zero.OnRegex("^退出群聊.*?(\\d+)", zero.OnlyGroup, zero.AdminPermission).
- Handle(
- func(matcher *zero.Matcher, event zero.Event, state zero.State) zero.Response {
- zero.SetGroupLeave(event.GroupID, true)
- zero.Send(event, "明白了!")
- return zero.SuccessResponse
- },
- )
- leave.Priority = 23
- leave.Block = true
-
-}
diff --git a/modules/mute.go b/modules/mute.go
deleted file mode 100644
index f265636eb3..0000000000
--- a/modules/mute.go
+++ /dev/null
@@ -1,77 +0,0 @@
-package modules
-
-import (
- zero "github.com/wdvxdr1123/ZeroBot"
-)
-
-func init() {
- zero.RegisterPlugin(mute{})
-}
-
-type mute struct{}
-
-func (mute) GetPluginInfo() zero.PluginInfo { // 返回插件信息
- return zero.PluginInfo{
- Author: "kanri",
- PluginName: "mute",
- Version: "0.0.1",
- Details: "禁言",
- }
-}
-
-func (mute) Start() { // 插件主体
- unWholeBan := zero.OnRegex("^解除全体禁言$", zero.OnlyGroup, zero.AdminPermission).
- Handle(
- func(matcher *zero.Matcher, event zero.Event, state zero.State) zero.Response {
- zero.SetGroupWholeBan(event.GroupID, false)
- zero.Send(event, "小黑屋收留成功~")
- return zero.SuccessResponse
- },
- )
- unWholeBan.Priority = 1
- unWholeBan.Block = true
-
- wholeBan := zero.OnRegex("^开启全体禁言$", zero.OnlyGroup, zero.AdminPermission).
- Handle(
- func(matcher *zero.Matcher, event zero.Event, state zero.State) zero.Response {
- zero.SetGroupWholeBan(event.GroupID, true)
- zero.Send(event, "小黑屋收留成功~")
- return zero.SuccessResponse
- },
- )
- wholeBan.Priority = 2
- wholeBan.Block = true
-
- unban := zero.OnRegex("^解除禁言.*?(\\d+)", zero.OnlyGroup, zero.AdminPermission).
- Handle(
- func(matcher *zero.Matcher, event zero.Event, state zero.State) zero.Response {
- zero.SetGroupBan(event.GroupID, GetInt(state, 1), 0)
- zero.Send(event, "小黑屋释放成功~")
- return zero.SuccessResponse
- },
- )
- unban.Priority = 3
- unban.Block = true
-
- ban := zero.OnRegex("^禁言.*?(\\d+).*?\\s(\\d+)", zero.OnlyGroup, zero.AdminPermission).
- Handle(
- func(matcher *zero.Matcher, event zero.Event, state zero.State) zero.Response {
- zero.SetGroupBan(event.GroupID, GetInt(state, 1), GetInt(state, 2)*1000)
- zero.Send(event, "小黑屋收留成功~")
- return zero.SuccessResponse
- },
- )
- ban.Priority = 4
- ban.Block = true
-
- selfBan := zero.OnRegex("^我要自闭.*?(\\d+)分钟", zero.OnlyGroup, zero.AdminPermission).
- Handle(
- func(matcher *zero.Matcher, event zero.Event, state zero.State) zero.Response {
- zero.SetGroupBan(event.GroupID, event.UserID, GetInt(state, 1)*1000)
- zero.Send(event, "那我就不手下留情了")
- return zero.SuccessResponse
- },
- )
- selfBan.Priority = 5
- selfBan.Block = true
-}
diff --git a/modules/notice.go b/modules/notice.go
deleted file mode 100644
index 52d48e20c7..0000000000
--- a/modules/notice.go
+++ /dev/null
@@ -1,61 +0,0 @@
-package modules
-
-import (
- "time"
-
- zero "github.com/wdvxdr1123/ZeroBot"
-)
-
-func init() {
- zero.RegisterPlugin(notice{})
-}
-
-type notice struct{}
-
-func (notice) GetPluginInfo() zero.PluginInfo { // 返回插件信息
- return zero.PluginInfo{
- Author: "kanri",
- PluginName: "notice",
- Version: "0.0.1",
- Details: "设置群名片群头衔",
- }
-}
-
-func (notice) Start() { // 插件主体
- notify := zero.OnNotice().
- Handle(
- func(matcher *zero.Matcher, event zero.Event, state zero.State) zero.Response {
- if event.NoticeType == "notify" {
- time.Sleep(time.Second * 1)
- zero.Send(event, "请不要戳我 >_<")
- }
- return zero.SuccessResponse
- },
- )
- notify.Priority = 40
- notify.Block = true
-
- increase := zero.OnNotice().
- Handle(
- func(matcher *zero.Matcher, event zero.Event, state zero.State) zero.Response {
- if event.NoticeType == "group_increase" {
- zero.Send(event, "欢迎~")
- }
- return zero.SuccessResponse
- },
- )
- increase.Priority = 41
- increase.Block = true
-
- decrease := zero.OnNotice().
- Handle(
- func(matcher *zero.Matcher, event zero.Event, state zero.State) zero.Response {
- if event.NoticeType == "group_decrease" {
- zero.Send(event, "有人跑路了")
- }
- return zero.SuccessResponse
- },
- )
- decrease.Priority = 42
- decrease.Block = true
-}
diff --git a/modules/request.go b/modules/request.go
deleted file mode 100644
index a4b17af9c3..0000000000
--- a/modules/request.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package modules
-
-import (
- "gm/utils"
-
- zero "github.com/wdvxdr1123/ZeroBot"
-)
-
-func init() {
- zero.RegisterPlugin(request{})
-}
-
-type request struct{}
-
-func (request) GetPluginInfo() zero.PluginInfo { // 返回插件信息
- return zero.PluginInfo{
- Author: "kanri",
- PluginName: "request",
- Version: "0.0.1",
- Details: "设置群名片群头衔",
- }
-}
-
-func (request) Start() { // 插件主体
- friendAdd := zero.OnNotice().
- Handle(
- func(matcher *zero.Matcher, event zero.Event, state zero.State) zero.Response {
- if event.RequestType == "friend" {
- zero.SendPrivateMessage(utils.Str2Int(Conf.Master[0]), "有人想加我")
- }
- return zero.SuccessResponse
- },
- )
- friendAdd.Priority = 50
- friendAdd.Block = true
-
- groupAdd := zero.OnNotice().
- Handle(
- func(matcher *zero.Matcher, event zero.Event, state zero.State) zero.Response {
- if event.RequestType == "friend" {
- if event.SubType == "add" {
- zero.Send(event, "有人申请加群")
- } else {
- zero.SendPrivateMessage(utils.Str2Int(Conf.Master[0]), "有人想拉我入群")
- }
- }
- return zero.SuccessResponse
- },
- )
- groupAdd.Priority = 51
- groupAdd.Block = true
-}
diff --git a/modules/sender.go b/modules/sender.go
deleted file mode 100644
index 9268e7fb95..0000000000
--- a/modules/sender.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package modules
-
-import (
- zero "github.com/wdvxdr1123/ZeroBot"
-)
-
-func init() {
- zero.RegisterPlugin(sender{})
-}
-
-type sender struct{}
-
-func (sender) GetPluginInfo() zero.PluginInfo { // 返回插件信息
- return zero.PluginInfo{
- Author: "kanri",
- PluginName: "sender",
- Version: "0.0.1",
- Details: "设置群名片群头衔",
- }
-}
-
-func (sender) Start() { // 插件主体
- promoteManager := zero.OnRegex("^群聊转发.*?(\\d+)\\s(.*)", zero.OnlyGroup, zero.AdminPermission).
- Handle(
- func(matcher *zero.Matcher, event zero.Event, state zero.State) zero.Response {
- zero.SendGroupMessage(GetInt(state, 1), GetStr(state, 2))
- zero.Send(event, "complete!")
- return zero.SuccessResponse
- },
- )
- promoteManager.Priority = 30
- promoteManager.Block = true
-
- cancleManager := zero.OnRegex("^私聊转发.*?(\\d+)\\s(.*)", zero.OnlyGroup, zero.AdminPermission).
- Handle(
- func(matcher *zero.Matcher, event zero.Event, state zero.State) zero.Response {
- zero.SendPrivateMessage(GetInt(state, 1), GetStr(state, 2))
- zero.Send(event, "complete!")
- return zero.SuccessResponse
- },
- )
- cancleManager.Priority = 31
- cancleManager.Block = true
-}
diff --git a/modules/title.go b/modules/title.go
deleted file mode 100644
index 1c7eed709f..0000000000
--- a/modules/title.go
+++ /dev/null
@@ -1,55 +0,0 @@
-package modules
-
-import (
- zero "github.com/wdvxdr1123/ZeroBot"
-)
-
-func init() {
- zero.RegisterPlugin(title{})
-}
-
-type title struct{}
-
-func (title) GetPluginInfo() zero.PluginInfo { // 返回插件信息
- return zero.PluginInfo{
- Author: "kanri",
- PluginName: "title",
- Version: "0.0.1",
- Details: "设置群名片群头衔",
- }
-}
-
-func (title) Start() { // 插件主体
- setCard := zero.OnRegex("^修改名片.*?(\\d+).*?\\s(.*)", zero.OnlyGroup, zero.AdminPermission).
- Handle(
- func(matcher *zero.Matcher, event zero.Event, state zero.State) zero.Response {
- zero.SetGroupCard(event.GroupID, GetInt(state, 1), GetStr(state, 2))
- zero.Send(event, "嗯!已经修改了")
- return zero.SuccessResponse
- },
- )
- setCard.Priority = 10
- setCard.Block = true
-
- setTitle := zero.OnRegex("^修改头衔.*?(\\d+).*?\\s(.*)", zero.OnlyGroup, zero.AdminPermission).
- Handle(
- func(matcher *zero.Matcher, event zero.Event, state zero.State) zero.Response {
- zero.SetGroupSpecialTitle(event.GroupID, GetInt(state, 1), GetStr(state, 2))
- zero.Send(event, "嗯!已经修改了")
- return zero.SuccessResponse
- },
- )
- setTitle.Priority = 11
- setTitle.Block = true
-
- setSelfTitle := zero.OnRegex("^申请头衔(.*)").
- Handle(
- func(matcher *zero.Matcher, event zero.Event, state zero.State) zero.Response {
- zero.SetGroupSpecialTitle(event.GroupID, event.UserID, GetStr(state, 2))
- zero.Send(event, "嗯!不错的头衔呢~")
- return zero.SuccessResponse
- },
- )
- setSelfTitle.Priority = 12
- setSelfTitle.Block = true
-}
diff --git a/modules/utils.go b/modules/utils.go
deleted file mode 100644
index 57530c3cf8..0000000000
--- a/modules/utils.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package modules
-
-import (
- "fmt"
- "gm/utils"
-
- zero "github.com/wdvxdr1123/ZeroBot"
-)
-
-func GetInt(state zero.State, index int64) int64 {
- fmt.Println(state["regex_matched"].([]string))
- return utils.Str2Int(state["regex_matched"].([]string)[index])
-}
-
-func GetStr(state zero.State, index int64) string {
- return state["regex_matched"].([]string)[index]
-}
diff --git a/music/music_selecter.go b/music/music_selecter.go
new file mode 100644
index 0000000000..d6d95ba246
--- /dev/null
+++ b/music/music_selecter.go
@@ -0,0 +1,170 @@
+package music
+
+import (
+ "crypto/md5"
+ "encoding/hex"
+ "fmt"
+ "github.com/tidwall/gjson"
+ zero "github.com/wdvxdr1123/ZeroBot"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "strings"
+ "time"
+)
+
+func init() {
+ zero.OnRegex("^酷我点歌(.+?)$").SetBlock(true).SetPriority(50).Handle(func(ctx *zero.Ctx) {
+ ctx.Send(KuWo(ctx.State["regex_matched"].([]string)[1]))
+ return
+ })
+
+ zero.OnRegex("^酷狗点歌(.+?)$").SetBlock(true).SetPriority(50).Handle(func(ctx *zero.Ctx) {
+ ctx.Send(KuGou(ctx.State["regex_matched"].([]string)[1]))
+ return
+ })
+
+ zero.OnRegex("^网易点歌(.+?)$").SetBlock(true).SetPriority(50).Handle(func(ctx *zero.Ctx) {
+ ctx.Send(WyCloud(ctx.State["regex_matched"].([]string)[1]))
+ return
+ })
+
+ zero.OnRegex("^点歌(.+?)$").SetBlock(true).SetPriority(50).Handle(func(ctx *zero.Ctx) {
+ ctx.Send(QQMusic(ctx.State["regex_matched"].([]string)[1]))
+ return
+ })
+}
+
+//-----------------------------------------------------------------------
+
+func KuWo(KeyWord string) string {
+ headers := map[string]string{
+ "Cookie": "Hm_lvt_cdb524f42f0ce19b169a8071123a4797=1610284708,1610699237; _ga=GA1.2.1289529848.1591618534; kw_token=LWKACV45JSQ; Hm_lpvt_cdb524f42f0ce19b169a8071123a4797=1610699468; _gid=GA1.2.1868980507.1610699238; _gat=1",
+ "csrf": "LWKACV45JSQ",
+ "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0",
+ "Referer": "https://www.kuwo.cn/search/list?key=",
+ }
+ api := "https://www.kuwo.cn/api/www/search/searchMusicBykeyWord?key="+url.QueryEscape(KeyWord)+"&pn=1&rn=1&httpsStatus=1"
+ info := gjson.ParseBytes(NetGet(api,headers)).Get("data.list.0")
+ return fmt.Sprintf("[CQ:music,type=custom,url=%s,audio=%s,title=%s,content=%s,image=%s]",
+ fmt.Sprintf("https://www.kuwo.cn/play_detail/%d",info.Get("rid").Int()),
+ gjson.ParseBytes(
+ NetGet(fmt.Sprintf(
+ "http://www.kuwo.cn/url?format=mp3&rid=%d&response=url&type=convert_url3&br=128kmp3&from=web&httpsStatus=1", info.Get("rid").Int()),headers)).Get("url").Str,
+ info.Get("name").Str,
+ info.Get("artist").Str,
+ info.Get("pic").Str,
+ )
+}
+
+func KuGou(KeyWord string) string {
+ stamp := time.Now().UnixNano()/1e6
+ api := fmt.Sprintf(
+ "https://complexsearch.kugou.com/v2/search/song?callback=callback123&keyword=%s&page=1&pagesize=30&bitrate=0&isfuzzy=0&tag=em&inputtype=0&platform=WebFilter&userid=-1&clientver=2000&iscorrection=1&privilege_filter=0&srcappid=2919&clienttime=%d&mid=%d&uuid=%d&dfid=-&signature=%s",
+ KeyWord,stamp,stamp,stamp,GetMd5(fmt.Sprintf(
+ "NVPh5oo715z5DIWAeQlhMDsWXXQV4hwtbitrate=0callback=callback123clienttime=%dclientver=2000dfid=-inputtype=0iscorrection=1isfuzzy=0keyword=%smid=%dpage=1pagesize=30platform=WebFilterprivilege_filter=0srcappid=2919tag=emuserid=-1uuid=%dNVPh5oo715z5DIWAeQlhMDsWXXQV4hwt",
+ stamp,KeyWord,stamp,stamp)),
+ )
+ res := NetGet(api, map[string]string{"User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0"})
+ info := gjson.ParseBytes(res[12:len(res)-2]).Get("data.lists.0")
+ res = NetGet(
+ fmt.Sprintf("https://wwwapi.kugou.com/yy/index.php?r=play/getdata&hash=%s&album_id=%s",info.Get("FileHash").Str,info.Get("AlbumID").Str),
+ map[string]string{
+ "Cookie": "kg_mid=d8e70a262c93d47599c6196c612d6f4f; Hm_lvt_aedee6983d4cfc62f509129360d6bb3d=1610278505,1611631363,1611722252; kg_dfid=33ZWee1kircl0jcJ1h0WF1fX; Hm_lpvt_aedee6983d4cfc62f509129360d6bb3d=1611727348; kg_dfid_collect=d41d8cd98f00b204e9800998ecf8427e",
+ "Host": "wwwapi.kugou.com",
+ "TE": "Trailers",
+ "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0",
+ })
+ jump_url := fmt.Sprintf("https://www.kugou.com/song/#hash=%s&album_id=%s",info.Get("FileHash").Str,info.Get("AlbumID").Str)
+ info = gjson.ParseBytes(res).Get("data")
+ return fmt.Sprintf("[CQ:music,type=custom,url=%s,audio=%s,title=%s,content=%s,image=%s]",
+ jump_url,
+ strings.Replace(info.Get("play_backup_url").Str,"\\/","/",-1),
+ info.Get("song_name").Str,
+ info.Get("author_name").Str,
+ info.Get("img").Str,
+ )
+}
+
+func WyCloud(KeyWord string) string {
+ res := NetPost(
+ "http://music.163.com/api/search/pc",
+ map[string]string{"offset": "0", "total": "true", "limit": "9", "type": "1", "s": KeyWord},
+ map[string]string{
+ "Content-Type": "application/x-www-form-urlencoded",
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36",
+ },
+ )
+ info := gjson.ParseBytes(res).Get("result.songs.0")
+ return fmt.Sprintf(
+ "[CQ:music,type=custom,url=%s,audio=%s,title=%s,content=%s,image=%s]",
+ fmt.Sprintf("http://y.music.163.com/m/song?id=%d", info.Get("id").Int()),
+ fmt.Sprintf("http://music.163.com/song/media/outer/url?id=%d.mp3", info.Get("id").Int()),
+ info.Get("name").Str,
+ info.Get("artists.0.name").Str,
+ info.Get("album.blurPicUrl").Str,
+ )
+}
+
+func QQMusic(KeyWord string) string {
+ params := `https://u.y.qq.com/cgi-bin/musicu.fcg?data=%7B%22req%22%3A+%7B%22module%22%3A+%22CDN.SrfCdnDispatchServer%22%2C+%22method%22%3A+%22GetCdnDispatch%22%2C+%22param%22%3A+%7B%22guid%22%3A+%223982823384%22%2C+%22calltype%22%3A+0%2C+%22userip%22%3A+%22%22%7D%7D%2C+%22req_0%22%3A+%7B%22module%22%3A+%22vkey.GetVkeyServer%22%2C+%22method%22%3A+%22CgiGetVkey%22%2C+%22param%22%3A+%7B%22guid%22%3A+%223982823384%22%2C+%22songmid%22%3A+%5B%22{}%22%5D%2C+%22songtype%22%3A+%5B0%5D%2C+%22uin%22%3A+%220%22%2C+%22loginflag%22%3A+1%2C+%22platform%22%3A+%2220%22%7D%7D%2C+%22comm%22%3A+%7B%22uin%22%3A+0%2C+%22format%22%3A+%22json%22%2C+%22ct%22%3A+24%2C+%22cv%22%3A+0%7D%7D`
+ res := NetGet(
+ "https://c.y.qq.com/soso/fcgi-bin/client_search_cp?w="+KeyWord,
+ map[string]string{"User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0"},
+ )
+ info := gjson.ParseBytes(res[9:len(res)-1]).Get("data.song.list.0")
+ return fmt.Sprintf(
+ "[CQ:music,type=custom,url=%s,audio=%s,title=%s,content=%s,image=%s]",
+ "https://y.qq.com/n/yqq/song/"+info.Get("songmid").Str+".html",
+ "https://isure.stream.qqmusic.qq.com/" + gjson.ParseBytes(
+ NetGet(
+ strings.Replace(params,"{}",info.Get("songmid").Str,-1),
+ map[string]string{
+ "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1",
+ "referer": "http://y.qq.com",
+ })).Get("req_0.data.midurlinfo.0.purl").Str,
+ info.Get("songname").Str,
+ info.Get("singer.0.name").Str,
+ "https://y.gtimg.cn/music/photo_new"+StrMidGet("//y.gtimg.cn/music/photo_new","?max_age",string(NetGet("https://y.qq.com/n/yqq/song/"+info.Get("songmid").Str+".html", map[string]string{}))),
+ )
+}
+
+//-----------------------------------------------------------------------
+
+func StrMidGet(pre string,suf string,str string) string {
+ n := strings.Index(str, pre)
+ if n == -1 {n = 0} else {n = n + len(pre)}
+ str = string([]byte(str)[n:])
+ m := strings.Index(str, suf)
+ if m == -1 {m = len(str)}
+ return string([]byte(str)[:m])
+}
+
+func GetMd5(s string) string {
+ h := md5.New()
+ h.Write([]byte(s))
+ result := strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
+ return result
+}
+
+func NetGet(get_url string,headers map[string]string) []byte {
+ client := &http.Client{}
+ request,_ := http.NewRequest("GET",get_url,nil)
+ for key,value := range headers{request.Header.Add(key,value)}
+ res,_ := client.Do(request)
+ defer res.Body.Close()
+ result,_ := ioutil.ReadAll(res.Body)
+ return result
+}
+
+func NetPost(post_url string,data map[string]string,headers map[string]string) []byte {
+ client := &http.Client{}
+ param := url.Values{}
+ for key,value := range data{param.Set(key,value)}
+ request,_ := http.NewRequest("POST",post_url,strings.NewReader(param.Encode()))
+ for key,value := range headers{request.Header.Add(key,value)}
+ res,_ := client.Do(request)
+ defer res.Body.Close()
+ result,_ := ioutil.ReadAll(res.Body)
+ return result
+}
diff --git a/setutime/pic_searcher.go b/setutime/pic_searcher.go
new file mode 100644
index 0000000000..259aca44c1
--- /dev/null
+++ b/setutime/pic_searcher.go
@@ -0,0 +1,138 @@
+package setutime
+
+import (
+ "fmt"
+
+ utils "github.com/Yiwen-Chan/ZeroBot-Plugin/setutime/utils"
+ zero "github.com/wdvxdr1123/ZeroBot"
+)
+
+func init() { // 插件主体
+ // 根据PID搜图
+ zero.OnRegex(`^搜图(\d+)$`).SetBlock(true).SetPriority(30).
+ Handle(func(ctx *zero.Ctx) {
+ id := utils.Str2Int(ctx.State["regex_matched"].([]string)[1])
+ ctx.Send("少女祈祷中......")
+ // 获取P站插图信息
+ illust := &utils.Illust{}
+ if err := illust.IllustInfo(id); err != nil {
+ ctx.Send(fmt.Sprintf("ERROR: %v", err))
+ return
+ }
+ // 下载P站插图
+ if _, err := illust.PixivPicDown(CACHEPATH); err != nil {
+ ctx.Send(fmt.Sprintf("ERROR: %v", err))
+ return
+ }
+ // 发送搜索结果
+ ctx.Send(illust.DetailPic)
+ return
+ })
+ // 通过回复以图搜图
+ zero.OnRegex(`\[CQ:reply,id=(.*?)\](.*)搜索图片`).SetBlock(true).SetPriority(32).
+ Handle(func(ctx *zero.Ctx) {
+ var pics []string // 图片搜索池子
+ // 获取回复的上文图片链接
+ id := utils.Str2Int(ctx.State["regex_matched"].([]string)[1])
+ for _, elem := range ctx.GetMessage(id).Elements {
+ if elem.Type == "image" {
+ pics = append(pics, elem.Data["url"])
+ }
+ }
+ // 没有收到图片则向用户索取
+ if len(pics) == 0 {
+ ctx.Send("请发送多张图片!")
+ next := ctx.FutureEvent("message", ctx.CheckSession())
+ recv, cancel := next.Repeat()
+ for e := range recv { // 循环获取channel发来的信息
+ if len(e.Message) == 1 && e.Message[0].Type == "text" {
+ cancel() // 如果是纯文本则退出索取
+ break
+ }
+ for _, elem := range e.Message {
+ if elem.Type == "image" { // 将信息中的图片添加到搜索池子
+ pics = append(pics, elem.Data["url"])
+ }
+ }
+ if len(pics) >= 5 {
+ cancel() // 如果是图片数量大于等于5则退出索取
+ break
+ }
+ }
+ }
+ if len(pics) == 0 {
+ ctx.Send("没有收到图片,搜图结束......")
+ return
+ }
+ // 开始搜索图片
+ ctx.Send("少女祈祷中......")
+ for _, pic := range pics {
+ if text, err := utils.SauceNaoSearch(pic); err == nil {
+ ctx.Send(text) // 返回SauceNAO的结果
+ continue
+ } else {
+ ctx.Send(fmt.Sprintf("ERROR: %v", err))
+ }
+ if text, err := utils.Ascii2dSearch(pic); err == nil {
+ ctx.Send(text) // 返回Ascii2d的结果
+ continue
+ } else {
+ ctx.Send(fmt.Sprintf("ERROR: %v", err))
+ }
+ }
+ return
+ })
+ // 通过命令以图搜图
+ zero.OnKeywordGroup([]string{"以图识图", "以图搜图", "搜索图片"}).SetBlock(true).SetPriority(33).
+ Handle(func(ctx *zero.Ctx) {
+ var pics []string // 图片搜索池子
+ // 获取信息中图片链接
+ for _, elem := range ctx.Event.Message {
+ if elem.Type == "image" {
+ pics = append(pics, elem.Data["url"])
+ }
+ }
+ // 没有收到图片则向用户索取
+ if len(pics) == 0 {
+ ctx.Send("请发送多张图片!")
+ next := ctx.FutureEvent("message", zero.CheckUser(ctx.Event.UserID))
+ recv, cancel := next.Repeat()
+ for e := range recv { // 循环获取channel发来的信息
+ if len(e.Message) == 1 && e.Message[0].Type == "text" {
+ cancel() // 如果是纯文本则退出索取
+ break
+ }
+ for _, elem := range e.Message {
+ if elem.Type == "image" { // 将信息中的图片添加到搜索池子
+ pics = append(pics, elem.Data["url"])
+ }
+ }
+ if len(pics) >= 5 {
+ cancel() // 如果是图片数量大于等于5则退出索取
+ break
+ }
+ }
+ }
+ if len(pics) == 0 {
+ ctx.Send("没有收到图片,搜图结束......")
+ return
+ }
+ // 开始搜索图片
+ ctx.Send("少女祈祷中......")
+ for _, pic := range pics {
+ if text, err := utils.SauceNaoSearch(pic); err == nil {
+ ctx.Send(text) // 返回SauceNAO的结果
+ continue
+ } else {
+ ctx.Send(fmt.Sprintf("ERROR: %v", err))
+ }
+ if text, err := utils.Ascii2dSearch(pic); err == nil {
+ ctx.Send(text) // 返回Ascii2d的结果
+ continue
+ } else {
+ ctx.Send(fmt.Sprintf("ERROR: %v", err))
+ }
+ }
+ return
+ })
+}
diff --git a/setutime/setu_geter.go b/setutime/setu_geter.go
new file mode 100644
index 0000000000..fb94e254fa
--- /dev/null
+++ b/setutime/setu_geter.go
@@ -0,0 +1,189 @@
+package setutime
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+ "time"
+
+ "github.com/Yiwen-Chan/ZeroBot-Plugin/setutime/utils"
+ zero "github.com/wdvxdr1123/ZeroBot"
+ "github.com/wdvxdr1123/ZeroBot/extension/rate"
+)
+
+var limit = rate.NewManager(time.Minute*1, 5)
+
+var (
+ BOTPATH = utils.PathExecute() // 当前bot运行目录
+ DATAPATH = BOTPATH + "data/SetuTime/" // 数据目录
+ DBPATH = DATAPATH + "SetuTime.db" // 数据库路径
+
+ CACHEPATH = DATAPATH + "cache/" // 缓冲图片路径
+ CACHEGROUP int64 = 868047498 // 缓冲图片群,不修改无法缓存
+ PoolList = []string{"涩图", "二次元", "风景", "车万"} // 可自定义
+
+ DB = utils.Sqlite{DBPath: DBPATH} // 新建涩图数据库对象
+ PoolsCache = utils.NewPoolsCache() // 新建一个缓冲池对象
+
+ FORM = "PIC" // 默认 PIC 格式
+)
+
+func init() {
+ PoolsCache.Group = CACHEGROUP // 图片缓冲群
+ PoolsCache.Path = CACHEPATH // 缓冲图片路径
+
+ utils.CreatePath(DBPATH)
+ utils.CreatePath(CACHEPATH)
+
+ for i := range PoolList {
+ if err := DB.Create(PoolList[i], &utils.Illust{}); err != nil {
+ panic(err)
+ }
+ }
+}
+
+func init() { // 插件主体
+ zero.OnRegex(`^来份(.*)$`, FirstValueInList(PoolList)).SetBlock(true).SetPriority(20).
+ Handle(func(ctx *zero.Ctx) {
+ if limit.Load(ctx.Event.UserID).Acquire() == false {
+ ctx.Send("请稍后重试0x0...")
+ return
+ }
+ var type_ = ctx.State["regex_matched"].([]string)[1]
+ // 补充池子
+ go func() {
+ times := utils.Min(PoolsCache.Max-PoolsCache.Size(type_), 2)
+ for i := 0; i < times; i++ {
+ illust := &utils.Illust{}
+ // 查询出一张图片
+ if err := DB.Select(type_, illust, "ORDER BY RANDOM() limit 1"); err != nil {
+ ctx.Send(fmt.Sprintf("ERROR: %v", err))
+ continue
+ }
+ ctx.SendGroupMessage(PoolsCache.Group, "正在下载"+illust.ImageUrls)
+ file, err := illust.PixivPicDown(PoolsCache.Path)
+ if err != nil {
+ ctx.Send(fmt.Sprintf("ERROR: %v", err))
+ continue
+ }
+ if id := ctx.SendGroupMessage(PoolsCache.Group, illust.NormalPic(file)); id == 0 {
+ ctx.Send(fmt.Sprintf("ERROR: %v", "发送到缓存群失败,请确认缓存群群号"))
+ continue
+ }
+ // 向缓冲池添加一张图片
+ if err := PoolsCache.Push(type_, illust); err != nil {
+ ctx.Send(fmt.Sprintf("ERROR: %v", err))
+ continue
+ }
+ time.Sleep(time.Second * 1)
+ }
+ }()
+ // 如果没有缓存,阻塞5秒
+ if PoolsCache.Size(type_) == 0 {
+ ctx.Send("[SetuTime] 正在填充弹药......")
+ <-time.After(time.Second * 5)
+ if PoolsCache.Size(type_) == 0 {
+ ctx.Send("[SetuTime] 等待填充,请稍后再试......")
+ return
+ }
+ }
+ // 从缓冲池里抽一张
+ if id := ctx.Send(PoolsCache.GetOnePic(type_, FORM)); id == 0 {
+ ctx.Send(fmt.Sprintf("ERROR: %v", errors.New("可能被风控了")))
+ }
+ return
+ })
+
+ zero.OnRegex(`^添加(.*?)(\d+)$`, FirstValueInList(PoolList), zero.SuperUserPermission).SetBlock(true).SetPriority(21).
+ Handle(func(ctx *zero.Ctx) {
+ var (
+ type_ = ctx.State["regex_matched"].([]string)[1]
+ id = utils.Str2Int(ctx.State["regex_matched"].([]string)[2])
+ illust = &utils.Illust{}
+ )
+ ctx.Send("少女祈祷中......")
+ // 查询P站插图信息
+
+ if err := illust.IllustInfo(id); err != nil {
+ ctx.Send(fmt.Sprintf("ERROR: %v", err))
+ return
+ }
+ // 下载插画
+ if _, err := illust.PixivPicDown(PoolsCache.Path); err != nil {
+ ctx.Send(fmt.Sprintf("ERROR: %v", err))
+ return
+ }
+ file := fmt.Sprintf("%s%d.jpg", PoolsCache.Path, illust.Pid)
+ if id := ctx.Send(illust.DetailPic(file)); id == 0 {
+ ctx.Send(fmt.Sprintf("ERROR: %v", "可能被风控,发送失败"))
+ return
+ }
+ // 添加插画到对应的数据库table
+ if err := DB.Insert(type_, illust); err != nil {
+ ctx.Send(fmt.Sprintf("ERROR: %v", err))
+ return
+ }
+ ctx.Send("添加成功")
+ return
+ })
+
+ zero.OnRegex(`^删除(.*?)(\d+)$`, FirstValueInList(PoolList), zero.SuperUserPermission).SetBlock(true).SetPriority(22).
+ Handle(func(ctx *zero.Ctx) {
+ var (
+ type_ = ctx.State["regex_matched"].([]string)[1]
+ id = utils.Str2Int(ctx.State["regex_matched"].([]string)[2])
+ )
+ // 查询数据库
+ if err := DB.Delete(type_, fmt.Sprintf("WHERE pid=%d", id)); err != nil {
+ ctx.Send(fmt.Sprintf("ERROR: %v", err))
+ return
+ }
+ ctx.Send("删除成功")
+ return
+ })
+
+ // 查询数据库涩图数量
+ zero.OnFullMatchGroup([]string{"setu -s", "setu --status"}).SetBlock(true).SetPriority(23).
+ Handle(func(ctx *zero.Ctx) {
+ state := []string{"[SetuTime]"}
+ for i := range PoolList {
+ num, err := DB.Num(PoolList[i])
+ if err != nil {
+ num = 0
+ }
+ state = append(state, "\n")
+ state = append(state, PoolList[i])
+ state = append(state, ": ")
+ state = append(state, fmt.Sprintf("%d", num))
+ }
+ ctx.Send(strings.Join(state, ""))
+ return
+ })
+ // 开xml模式
+ zero.OnFullMatchGroup([]string{"setu -x", "setu --xml"}).SetBlock(true).SetPriority(24).
+ Handle(func(ctx *zero.Ctx) {
+ FORM = "XML"
+ ctx.Send("[SetuTime] XML->ON")
+ return
+ })
+ // 关xml模式
+ zero.OnFullMatchGroup([]string{"setu -p", "setu --pic"}).SetBlock(true).SetPriority(24).
+ Handle(func(ctx *zero.Ctx) {
+ FORM = "PIC"
+ ctx.Send("[SetuTime] XML->OFF")
+ return
+ })
+}
+
+// FirstValueInList 判断正则匹配的第一个参数是否在列表中
+func FirstValueInList(list []string) zero.Rule {
+ return func(ctx *zero.Ctx) bool {
+ first := ctx.State["regex_matched"].([]string)[1]
+ for i := range list {
+ if first == list[i] {
+ return true
+ }
+ }
+ return false
+ }
+}
diff --git a/setutime/utils/ascii2d.go b/setutime/utils/ascii2d.go
new file mode 100644
index 0000000000..986adae6ab
--- /dev/null
+++ b/setutime/utils/ascii2d.go
@@ -0,0 +1,100 @@
+package utils
+
+import (
+ "errors"
+ "fmt"
+ "net/http"
+ "net/url"
+ "strings"
+
+ xpath "github.com/antchfx/htmlquery"
+)
+
+// Ascii2dSearch Ascii2d 以图搜图
+// 第一个参数 返回错误
+// 第二个参数 返回的信息
+func Ascii2dSearch(pic string) (text string, err error) {
+ var (
+ api = "https://ascii2d.net/search/uri"
+ )
+ transport := http.Transport{
+ DisableKeepAlives: true,
+ }
+ client := &http.Client{
+ Transport: &transport,
+ }
+
+ // 包装请求参数
+ data := url.Values{}
+ data.Set("uri", pic) // 图片链接
+ fromData := strings.NewReader(data.Encode())
+
+ // 网络请求
+ req, _ := http.NewRequest("POST", api, fromData)
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ req.Header.Set("Accept", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0")
+ resp, err := client.Do(req)
+ if err != nil {
+ return "", err
+ }
+ // 色合检索改变到特征检索
+ var bovwUrl = strings.ReplaceAll(resp.Request.URL.String(), "color", "bovw")
+ bovwReq, _ := http.NewRequest("POST", bovwUrl, nil)
+ bovwReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ bovwReq.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36")
+ bovwResp, err := client.Do(bovwReq)
+ if err != nil {
+ return "", err
+ }
+ defer bovwResp.Body.Close()
+ // 解析XPATH
+ doc, err := xpath.Parse(resp.Body)
+ if err != nil {
+ return "", err
+ }
+ // 取出每个返回的结果
+ list := xpath.Find(doc, `//div[@class="row item-box"]`)
+ var link string
+ // 遍历取出第一个返回的PIXIV结果
+ for _, n := range list {
+ linkPath := xpath.Find(n, `//div[2]/div[3]/h6/a[1]`)
+ picPath := xpath.Find(n, `//div[1]/img`)
+ if len(linkPath) != 0 && len(picPath) != 0 {
+ link = xpath.SelectAttr(linkPath[0], "href")
+ if strings.Contains(link, "www.pixiv.net") {
+ break
+ }
+ }
+ }
+ // 链接取出PIXIV id
+ var index = strings.LastIndex(link, "/")
+ if link == "" || index == -1 {
+ return "", errors.New("Ascii2d not found")
+ }
+ var id = Str2Int(link[index+1:])
+ if id == 0 {
+ return "", errors.New("convert to pid error")
+ }
+ // 根据PID查询插图信息
+ var illust = &Illust{}
+ if err := illust.IllustInfo(id); err != nil {
+ return "", err
+ }
+ if illust.AgeLimit != "all-age" {
+ return "", errors.New("Ascii2d not found")
+ }
+ // 返回插图信息文本
+ return fmt.Sprintf(
+ `[SetuTime] emmm大概是这个?
+标题:%s
+插画ID:%d
+画师:%s
+画师ID:%d
+直链:https://pixivel.moe/detail?id=%d`,
+ illust.Title,
+ illust.Pid,
+ illust.UserName,
+ illust.UserId,
+ illust.Pid,
+ ), nil
+}
diff --git a/setutime/utils/download.go b/setutime/utils/download.go
new file mode 100644
index 0000000000..3093484999
--- /dev/null
+++ b/setutime/utils/download.go
@@ -0,0 +1,74 @@
+package utils
+
+import (
+ "crypto/md5"
+ "crypto/tls"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "net"
+ "net/http"
+ "os"
+ "strings"
+)
+
+// urlCache 缓存并返回缓存路径
+func (this *Illust) PixivPicDown(path string) (savePath string, err error) {
+ url := this.ImageUrls
+ pid := this.Pid
+ url = strings.ReplaceAll(url, "img-original", "img-master")
+ url = strings.ReplaceAll(url, "_p0", "_p0_master1200")
+ url = strings.ReplaceAll(url, ".png", ".jpg")
+ // 文件名为url的hash值
+ savePath = path + Int2Str(pid) + ".jpg"
+ // 文件存在或文件大小大于10kb
+ if PathExists(savePath) && FileSize(savePath) > 10240 {
+ return savePath, nil
+ }
+
+ // 模拟QQ客户端请求
+ client := &http.Client{
+ Transport: &http.Transport{
+ DisableKeepAlives: true,
+ // 绕过sni审查
+ TLSClientConfig: &tls.Config{
+ ServerName: "-",
+ InsecureSkipVerify: true,
+ },
+ // 更改dns
+ Dial: func(network, addr string) (net.Conn, error) {
+ return net.Dial("tcp", "210.140.92.140:443")
+ },
+ },
+ }
+ reqest, _ := http.NewRequest("GET", url, nil)
+ reqest.Header.Set("Referer", "https://www.pixiv.net/")
+ reqest.Header.Set("Host", "i.pximg.net")
+ reqest.Header.Set("User-Agent", "QQ/8.2.0.1296 CFNetwork/1126")
+
+ resp, err := client.Do(reqest)
+ if err != nil {
+ return "", err
+ }
+ fmt.Println(resp.StatusCode)
+ if code := resp.StatusCode; code != 200 {
+ return "", errors.New(fmt.Sprintf("Download failed, code %d", code))
+ }
+ defer resp.Body.Close()
+ // 写入文件
+ data, _ := ioutil.ReadAll(resp.Body)
+ f, _ := os.OpenFile(savePath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
+ defer f.Close()
+ f.Write(data)
+
+ return savePath, err
+}
+
+// PicHash 返回图片的 md5 值
+func PicHash(path string) string {
+ data, err := ioutil.ReadFile(path)
+ if err != nil {
+ return ""
+ }
+ return strings.ToUpper(fmt.Sprintf("%x", md5.Sum(data)))
+}
diff --git a/setutime/utils/pic_pool.go b/setutime/utils/pic_pool.go
new file mode 100644
index 0000000000..dbd71b150f
--- /dev/null
+++ b/setutime/utils/pic_pool.go
@@ -0,0 +1,113 @@
+package utils
+
+import (
+ "fmt"
+ "sync"
+)
+
+// PoolsCache 图片缓冲池
+type PoolsCache struct {
+ Lock sync.Mutex
+ Max int
+ Path string
+ Group int64
+ Pool map[string][]*Illust
+}
+
+// NewPoolsCache 返回一个缓冲池对象
+func NewPoolsCache() *PoolsCache {
+ return &PoolsCache{
+ Max: 10,
+ Path: "./data/SetuTime/cache/",
+ Group: 1048452984,
+ Pool: map[string][]*Illust{},
+ }
+}
+
+// Size 返回缓冲池指定类型的现有大小
+func (p *PoolsCache) Size(type_ string) int {
+ return len(p.Pool[type_])
+}
+
+// IsFull 返回缓冲池指定类型是否已满
+func (p *PoolsCache) IsFull(type_ string) bool {
+ return len(p.Pool[type_]) >= p.Max
+}
+
+// Push 向缓冲池插入一张图片,返回错误
+func (p *PoolsCache) Push(type_ string, illust *Illust) (err error) {
+ p.Lock.Lock()
+ defer p.Lock.Unlock()
+ p.Pool[type_] = append(p.Pool[type_], illust)
+ return nil
+}
+
+// Push 在缓冲池拿出一张图片,返回错误
+func (p *PoolsCache) Pop(type_ string) (illust *Illust) {
+ p.Lock.Lock()
+ defer p.Lock.Unlock()
+ if p.Size(type_) == 0 {
+ return
+ }
+ illust = p.Pool[type_][0]
+ p.Pool[type_] = p.Pool[type_][1:]
+ return
+}
+
+// Push 在缓冲池拿出一张图片,返回指定格式CQ码
+func (p *PoolsCache) GetOnePic(type_ string, form string) string {
+ var (
+ illust = p.Pop(type_)
+ file = fmt.Sprintf("%s%d.jpg", p.Path, illust.Pid)
+ )
+ switch form {
+ case "XML":
+ return illust.BigPic(file)
+ case "DETAIL":
+ return illust.DetailPic(file)
+ default:
+ return illust.NormalPic(file)
+ }
+}
+
+// BigPic 返回一张XML大图CQ码
+func (i *Illust) BigPic(file string) string {
+ var hash = PicHash(file)
+ return fmt.Sprintf(`[CQ:xml,data=