mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2025-12-18 20:50:12 +08:00
🚧🎨⚡️ 重大重构中
This commit is contained in:
parent
0fe0a5e4e8
commit
7ca9f2158b
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,5 +1,2 @@
|
||||
data/chat
|
||||
data/SetuTime/cache
|
||||
data/manager
|
||||
main.exe
|
||||
.DS_Store
|
||||
data/SetuTime/search
|
||||
|
||||
@ -1,59 +0,0 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
)
|
||||
|
||||
// HasPicture 消息含有图片返回 true
|
||||
func HasPicture() zero.Rule {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
msg := ctx.Event.Message
|
||||
url := []string{}
|
||||
// 如果是回复信息则将信息替换成被回复的那条
|
||||
if msg[0].Type == "reply" {
|
||||
id, _ := strconv.Atoi(msg[0].Data["id"])
|
||||
msg = ctx.GetMessage(int64(id)).Elements
|
||||
}
|
||||
// 遍历信息中所有图片
|
||||
for _, elem := range msg {
|
||||
if elem.Type == "image" {
|
||||
url = append(url, elem.Data["url"])
|
||||
}
|
||||
}
|
||||
// 如果有图片就返回true
|
||||
if len(url) > 0 {
|
||||
ctx.State["image_url"] = url
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// MustHasPicture 消息不存在图片阻塞60秒至有图片,超时返回 false
|
||||
func MustHasPicture() zero.Rule {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
if HasPicture()(ctx) {
|
||||
return true
|
||||
}
|
||||
// 没有图片就索取
|
||||
ctx.Send("请发送一张图片")
|
||||
next := zero.NewFutureEvent("message", 999, false, zero.CheckUser(ctx.Event.UserID), HasPicture())
|
||||
recv, cancel := next.Repeat()
|
||||
select {
|
||||
case e := <-recv:
|
||||
cancel()
|
||||
newCtx := &zero.Ctx{Event: e, State: zero.State{}}
|
||||
if HasPicture()(newCtx) {
|
||||
ctx.State["image_url"] = newCtx.State["image_url"]
|
||||
ctx.Event.MessageID = newCtx.Event.MessageID
|
||||
return true
|
||||
}
|
||||
return false
|
||||
case <-time.After(time.Second * 60):
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
package msgext
|
||||
|
||||
import (
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
//@全体成员
|
||||
func AtAll() message.MessageSegment {
|
||||
return message.MessageSegment{
|
||||
Type: "at",
|
||||
Data: map[string]string{
|
||||
"qq": "all",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
//无缓存发送图片
|
||||
func ImageNoCache(url string) message.MessageSegment {
|
||||
return message.MessageSegment{
|
||||
Type: "image",
|
||||
Data: map[string]string{
|
||||
"file": url,
|
||||
"cache": "0",
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -1,92 +0,0 @@
|
||||
package pixiv
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/Yiwen-Chan/ZeroBot-Plugin/api/utils"
|
||||
)
|
||||
|
||||
// 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 + utils.Int2Str(pid) + ".jpg"
|
||||
// 文件存在或文件大小大于10kb
|
||||
if utils.PathExists(savePath) && utils.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.142: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
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
return "", errors.New(fmt.Sprintf("Download failed, code %d", resp.StatusCode))
|
||||
}
|
||||
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)))
|
||||
}
|
||||
|
||||
// urlCache 缓存并返回缓存路径
|
||||
func (this *Illust) RmPic(path 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 + utils.Int2Str(pid) + ".jpg"
|
||||
// 文件存在或文件大小大于10kb
|
||||
if utils.PathExists(savePath) {
|
||||
return os.Remove(savePath)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@ -1,137 +0,0 @@
|
||||
package pixiv
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
// Illust 插画信息
|
||||
type Illust struct {
|
||||
Pid int64 `db:"pid"`
|
||||
Title string `db:"title"`
|
||||
Caption string `db:"caption"`
|
||||
Tags string `db:"tags"`
|
||||
ImageUrls string `db:"image_urls"`
|
||||
AgeLimit string `db:"age_limit"`
|
||||
CreatedTime string `db:"created_time"`
|
||||
UserId int64 `db:"user_id"`
|
||||
UserName string `db:"user_name"`
|
||||
}
|
||||
|
||||
// IllustInfo 根据p站插画id返回插画信息Illust
|
||||
func (this *Illust) IllustInfo(id int64) (err error) {
|
||||
api := fmt.Sprintf("https://pixiv.net/ajax/illust/%d", id)
|
||||
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.131.223:443")
|
||||
},
|
||||
}
|
||||
client := &http.Client{
|
||||
Transport: &transport,
|
||||
}
|
||||
|
||||
// 网络请求
|
||||
req, err := http.NewRequest("GET", api, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Set("Host", "pixiv.net")
|
||||
req.Header.Set("Referer", "pixiv.net")
|
||||
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
|
||||
}
|
||||
if code := resp.StatusCode; code != 200 {
|
||||
return errors.New(fmt.Sprintf("Search illust's info failed, status %d", code))
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
json := gjson.ParseBytes(body).Get("body")
|
||||
|
||||
// 如果有"R-18"tag则判断为R-18(暂时)
|
||||
var ageLimit = "all-age"
|
||||
for _, tag := range json.Get("tags.tags.#.tag").Array() {
|
||||
if tag.Str == "R-18" {
|
||||
ageLimit = "r18"
|
||||
break
|
||||
}
|
||||
}
|
||||
// 解决json返回带html格式
|
||||
var caption = strings.ReplaceAll(json.Get("illustComment").Str, "<br />", "\n")
|
||||
if index := strings.Index(caption, "<"); index != -1 {
|
||||
caption = caption[:index]
|
||||
}
|
||||
// 解析返回插画信息
|
||||
this.Pid = json.Get("illustId").Int()
|
||||
this.Title = json.Get("illustTitle").Str
|
||||
this.Caption = caption
|
||||
this.Tags = fmt.Sprintln(json.Get("tags.tags.#.tag").Array())
|
||||
this.ImageUrls = json.Get("urls.original").Str
|
||||
this.AgeLimit = ageLimit
|
||||
this.CreatedTime = json.Get("createDate").Str
|
||||
this.UserId = json.Get("userId").Int()
|
||||
this.UserName = json.Get("userName").Str
|
||||
return nil
|
||||
}
|
||||
|
||||
// BigPic 返回一张XML大图CQ码
|
||||
func (i *Illust) BigPic(file string) string {
|
||||
var hash = PicHash(file)
|
||||
return fmt.Sprintf(`[CQ:xml,data=<?xml version='1.0'
|
||||
encoding='UTF-8' standalone='yes' ?><msg serviceID="5"
|
||||
templateID="12345" action="" brief="不够涩!"
|
||||
sourceMsgId="0" url="" flag="0" adverSign="0" multiMsgFlag="0">
|
||||
<item layout="0" advertiser_id="0" aid="0"><image uuid="%s.jpg" md5="%s"
|
||||
GroupFiledid="2235033681" filesize="81322" local_path="%s.jpg"
|
||||
minWidth="200" minHeight="200" maxWidth="500" maxHeight="1000" />
|
||||
</item><source name="%s⭐(id:%d author:%s)" icon=""
|
||||
action="" appid="-1" /></msg>]`,
|
||||
hash,
|
||||
hash,
|
||||
hash,
|
||||
i.Title,
|
||||
i.Pid,
|
||||
i.UserName,
|
||||
)
|
||||
}
|
||||
|
||||
// NormalPic 返回一张普通图CQ码
|
||||
func (i *Illust) NormalPic(file string) string {
|
||||
return fmt.Sprintf(`[CQ:image,file=file:///%s]`, file)
|
||||
}
|
||||
|
||||
// DetailPic 返回一张带详细信息的图片CQ码
|
||||
func (i *Illust) DetailPic(file string) string {
|
||||
return fmt.Sprintf(`[SetuTime] %s
|
||||
标题:%s
|
||||
插画ID:%d
|
||||
画师:%s
|
||||
画师ID:%d
|
||||
直链:https://pixivel.moe/detail?id=%d`,
|
||||
i.NormalPic(file),
|
||||
i.Title,
|
||||
i.Pid,
|
||||
i.UserName,
|
||||
i.UserId,
|
||||
i.Pid,
|
||||
)
|
||||
}
|
||||
@ -1,73 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Str2Int string --> int64
|
||||
func Str2Int(str string) int64 {
|
||||
val, _ := strconv.Atoi(str)
|
||||
return int64(val)
|
||||
}
|
||||
|
||||
// Int2Str int64 --> string
|
||||
func Int2Str(val int64) string {
|
||||
str := strconv.FormatInt(val, 10)
|
||||
return str
|
||||
}
|
||||
|
||||
// PathExecute 返回当前运行目录
|
||||
func PathExecute() string {
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return dir + "/"
|
||||
}
|
||||
|
||||
// CreatePath 生成路径或文件所对应的目录
|
||||
func CreatePath(path string) {
|
||||
length := len(path)
|
||||
switch {
|
||||
case path[length:] != "/":
|
||||
path = path[:strings.LastIndex(path, "/")]
|
||||
case path[length:] != "\\":
|
||||
path = path[:strings.LastIndex(path, "\\")]
|
||||
default:
|
||||
//
|
||||
}
|
||||
if !PathExists(path) {
|
||||
err := os.MkdirAll(path, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PathExists 判断路径或文件是否存在
|
||||
func PathExists(path string) bool {
|
||||
_, err := os.Stat(path)
|
||||
return err == nil || os.IsExist(err)
|
||||
}
|
||||
|
||||
// FileSize 获取文件大小
|
||||
func FileSize(file string) int64 {
|
||||
if fi, err := os.Stat(file); err == nil {
|
||||
return fi.Size()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Min 返回两数最小值
|
||||
func Min(a, b int) int {
|
||||
switch {
|
||||
default:
|
||||
return a
|
||||
case a > b:
|
||||
return b
|
||||
case a < b:
|
||||
return a
|
||||
}
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
go version
|
||||
go env -w GOPROXY=https://goproxy.cn,direct
|
||||
go env -w GO111MODULE=auto
|
||||
go mod tidy
|
||||
GOOS=linux GOARCH=arm GOARM=6 CGO_ENABLED=0 CC=${CCBIN} CXX=${CXXBIN} go build -ldflags "-s -w" -o zerobot
|
||||
@ -1,7 +0,0 @@
|
||||
go version
|
||||
go env -w GOPROXY=https://goproxy.cn,direct
|
||||
go env -w GO111MODULE=auto
|
||||
go mod tidy
|
||||
export CCBIN=~/openwrt_with_lean_packages/staging_dir/toolchain-mips_24kc_gcc-8.4.0_musl/bin/mips-openwrt-linux-musl-gcc
|
||||
export CXXBIN=~/openwrt_with_lean_packages/staging_dir/toolchain-mips_24kc_gcc-8.4.0_musl/bin/mips-openwrt-linux-musl-g++
|
||||
GOOS=linux GOARCH=mips GOMIPS=softfloat CGO_ENABLED=0 CC=${CCBIN} CXX=${CXXBIN} go build -ldflags "-s -w" -o zerobot
|
||||
343
chat/learn.go
343
chat/learn.go
@ -1,343 +0,0 @@
|
||||
package chat
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
type QA struct {
|
||||
Mutex sync.Mutex
|
||||
Data map[int64]map[string]string
|
||||
Path string
|
||||
}
|
||||
|
||||
var (
|
||||
BotPath = botPath()
|
||||
BotQQ = "0"
|
||||
ImagePath = "data/chat/image/"
|
||||
|
||||
Char = map[int64]string{} // 群对应角色
|
||||
CharIndex = map[string]int64{"椛椛": 0, "ATRI": 1} // 角色对应编号
|
||||
|
||||
// 角色问、有人问、我问 对象
|
||||
QACharPool = &QA{Data: map[int64]map[string]string{}, Path: BotPath + "data/chat/char.json"}
|
||||
QAGroupPool = &QA{Data: map[int64]map[string]string{}, Path: BotPath + "data/chat/group.json"}
|
||||
QAUserPool = &QA{Data: map[int64]map[string]string{}, Path: BotPath + "data/chat/user.json"}
|
||||
)
|
||||
|
||||
func init() {
|
||||
QACharPool.load()
|
||||
QAGroupPool.load()
|
||||
QAUserPool.load()
|
||||
zero.OnRegex(`切换角色(.*)`, zero.AdminPermission).SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if _, ok := CharIndex[ctx.State["regex_matched"].([]string)[1]]; !ok {
|
||||
ctx.SendChain(message.Text("???"))
|
||||
return
|
||||
}
|
||||
Char[ctx.Event.GroupID] = ctx.State["regex_matched"].([]string)[1]
|
||||
ctx.SendChain(message.Text("已经切换了哦~"))
|
||||
})
|
||||
zero.OnRegex(`(.{1,2})问(.*)你答\s?\s?([\s\S]*)`, QAMatch(), QAPermission()).SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
question := ctx.State["regex_matched"].([]string)[2]
|
||||
answer := ctx.State["regex_matched"].([]string)[3]
|
||||
// 根据匹配使用不同池子对象
|
||||
pool := ctx.State["qa_pool"].(*QA)
|
||||
user := ctx.State["qa_user"].(int64)
|
||||
// 重组艾特
|
||||
q := message.ParseMessageFromString(question)
|
||||
for i := range q {
|
||||
if q[i].Type == "at" && q[i].Data["qq"] == fmt.Sprint(ctx.Event.SelfID) {
|
||||
q[i].Data["qq"] = "BOT_QQ"
|
||||
}
|
||||
}
|
||||
question = q.CQString()
|
||||
|
||||
// 对 CQ码 的 "[" 进行正则转义
|
||||
question = strings.ReplaceAll(question, "[", "\\[")
|
||||
question = strings.ReplaceAll(question, "]", "\\]")
|
||||
question = message.UnescapeCQCodeText(question)
|
||||
|
||||
// 判断 question 是否符合正则表达式
|
||||
_, err := regexp.Compile("^" + question + "$")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
// 保存图片,重组图片信息
|
||||
r := message.ParseMessageFromString(answer)
|
||||
for i := range r {
|
||||
if r[i].Type == "image" {
|
||||
if filename, err := down(r[i].Data["url"], BotPath+ImagePath); err == nil {
|
||||
r[i].Data["file"] = "file:///BOT_PATH/" + ImagePath + filename
|
||||
delete(r[i].Data, "url")
|
||||
} else { // 下载图片发生错误
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
answer = r.CQString()
|
||||
|
||||
// 如果是BOT主人,则可以CQ码注入
|
||||
// 不存在CQ码也需要转义
|
||||
if !strings.Contains(answer, "CQ") || zero.SuperUserPermission(ctx) {
|
||||
answer = message.UnescapeCQCodeText(answer)
|
||||
}
|
||||
// 添加到池子
|
||||
pool.add(user, question, answer)
|
||||
ctx.SendChain(message.Text("好的我记住了~"))
|
||||
})
|
||||
zero.OnRegex(`删除(.{1,2})问(.*)`, QAMatch(), QAPermission()).SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
question := ctx.State["regex_matched"].([]string)[2]
|
||||
// 根据匹配使用不同池子对象
|
||||
pool := ctx.State["qa_pool"].(*QA)
|
||||
user := ctx.State["qa_user"].(int64)
|
||||
if !strings.Contains(question, "CQ") || zero.AdminPermission(ctx) {
|
||||
question = message.UnescapeCQCodeText(question)
|
||||
}
|
||||
// 重组艾特
|
||||
q := message.ParseMessageFromString(question)
|
||||
for i := range q {
|
||||
if q[i].Type == "at" && q[i].Data["qq"] == fmt.Sprint(ctx.Event.SelfID) {
|
||||
q[i].Data["qq"] = "BOT_QQ"
|
||||
}
|
||||
}
|
||||
question = q.CQString()
|
||||
if answer := pool.del(user, question); answer != "" {
|
||||
ctx.SendChain(message.Text("我不会再回答[", answer, "]了"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("啊咧[", question, "]是什么?"))
|
||||
}
|
||||
})
|
||||
zero.OnRegex(`看看(.{1,2})问`, QAMatch()).SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
title := ""
|
||||
r := []string{}
|
||||
switch ctx.State["regex_matched"].([]string)[1] {
|
||||
case "角色":
|
||||
char := "椛椛"
|
||||
if Char[ctx.Event.GroupID] != "" {
|
||||
char = Char[ctx.Event.GroupID]
|
||||
}
|
||||
title = "当前角色[" + char + "] 设置的关键词有:\n"
|
||||
case "有人":
|
||||
title = "本群设置的关键词有:\n"
|
||||
case "我":
|
||||
title = "你设置的关键词有:\n"
|
||||
}
|
||||
// 根据匹配使用不同池子对象
|
||||
pool := ctx.State["qa_pool"].(*QA)
|
||||
user := ctx.State["qa_user"].(int64)
|
||||
for question := range pool.Data[user] {
|
||||
r = append(r, question)
|
||||
}
|
||||
if len(r) == 0 {
|
||||
ctx.SendChain(message.Text("啊咧?我忘掉什么了吗"))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(
|
||||
title,
|
||||
strings.Join(r, " | "),
|
||||
))
|
||||
})
|
||||
zero.OnMessage().SetBlock(false).SetPriority(9999).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
BotQQ = fmt.Sprint(ctx.Event.SelfID)
|
||||
m := message.UnescapeCQCodeText(ctx.Event.RawEvent.Get("message").Str)
|
||||
// 角色问
|
||||
if answer := QACharPool.get(CharIndex[Char[ctx.Event.GroupID]], m); answer != "" {
|
||||
ctx.Send(answer)
|
||||
return
|
||||
}
|
||||
// 有人问
|
||||
if answer := QAGroupPool.get(ctx.Event.GroupID, m); answer != "" {
|
||||
ctx.Send(answer)
|
||||
return
|
||||
}
|
||||
// 我问
|
||||
if answer := QAUserPool.get(ctx.Event.UserID, m); answer != "" {
|
||||
ctx.Send(answer)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func botPath() string {
|
||||
dir, _ := os.Getwd()
|
||||
return dir + "/"
|
||||
}
|
||||
|
||||
func (qa *QA) load() {
|
||||
path := qa.Path
|
||||
idx := strings.LastIndex(qa.Path, "/")
|
||||
if idx != -1 {
|
||||
path = path[:idx]
|
||||
}
|
||||
_, err := os.Stat(path)
|
||||
if err != nil && !os.IsExist(err) {
|
||||
os.MkdirAll(path, 0644)
|
||||
}
|
||||
f, _ := os.Open(qa.Path)
|
||||
defer f.Close()
|
||||
data, _ := ioutil.ReadAll(f)
|
||||
qa.Mutex.Lock()
|
||||
defer qa.Mutex.Unlock()
|
||||
if data == nil {
|
||||
data = []byte("0: \n test: ok")
|
||||
}
|
||||
json.Unmarshal(data, &qa.Data)
|
||||
}
|
||||
|
||||
func (qa *QA) save() {
|
||||
path := qa.Path
|
||||
idx := strings.LastIndex(qa.Path, "/")
|
||||
if idx != -1 {
|
||||
path = path[:idx]
|
||||
}
|
||||
_, err := os.Stat(path)
|
||||
if err != nil && !os.IsExist(err) {
|
||||
os.MkdirAll(path, 0644)
|
||||
}
|
||||
data, _ := json.MarshalIndent(&qa.Data, "", "\t")
|
||||
ioutil.WriteFile(qa.Path, data, 0644)
|
||||
}
|
||||
|
||||
func (qa *QA) add(user int64, question, answer string) {
|
||||
qa.Mutex.Lock()
|
||||
defer qa.Mutex.Unlock()
|
||||
if qa.Data[user] == nil { // 防止未初始化
|
||||
qa.Data[user] = make(map[string]string)
|
||||
}
|
||||
qa.Data[user][question] = answer
|
||||
qa.save()
|
||||
}
|
||||
|
||||
func (qa *QA) del(user int64, question string) (answer string) {
|
||||
qa.Mutex.Lock()
|
||||
defer qa.Mutex.Unlock()
|
||||
if answer, ok := qa.Data[user][question]; ok {
|
||||
delete(qa.Data[user], question)
|
||||
qa.save()
|
||||
return answer
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (qa *QA) get(user int64, msg string) (answer string) {
|
||||
for question, answer := range qa.Data[user] {
|
||||
// 替换BOT
|
||||
question = strings.ReplaceAll(question, "BOT_QQ", BotQQ)
|
||||
r := regexp.MustCompile("^" + question + "$")
|
||||
if r.MatchString(msg) {
|
||||
match := r.FindStringSubmatch(msg)
|
||||
// 正则替换参数
|
||||
for i, p := range match {
|
||||
if p == "[" || p == "]" {
|
||||
continue
|
||||
}
|
||||
answer = strings.ReplaceAll(answer, fmt.Sprintf("$%d", i), p)
|
||||
}
|
||||
// 替换图片路径
|
||||
answer = strings.ReplaceAll(answer, "BOT_PATH", BotPath)
|
||||
// 随机回复
|
||||
if strings.Contains(answer, "|") {
|
||||
s := strings.Split(answer, "|")
|
||||
return s[rand.Intn(len(s))]
|
||||
}
|
||||
return answer
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func down(url, path string) (filename string, err error) {
|
||||
client := &http.Client{}
|
||||
reqest, _ := http.NewRequest("GET", url, nil)
|
||||
reqest.Header.Set("User-Agent", "QQ/8.2.0.1296 CFNetwork/1126")
|
||||
reqest.Header.Set("Net-Type", "Wifi")
|
||||
resp, err := client.Do(reqest)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", fmt.Errorf("code %d", resp.StatusCode)
|
||||
}
|
||||
data, _ := ioutil.ReadAll(resp.Body)
|
||||
// 获取文件MD5值
|
||||
m := md5.New()
|
||||
m.Write(data)
|
||||
filename = strings.ToUpper(hex.EncodeToString(m.Sum(nil)))
|
||||
// 判断文件类型
|
||||
switch resp.Header.Get("Content-Type") {
|
||||
case "image/jpeg":
|
||||
filename = filename + ".jpg"
|
||||
case "image/png":
|
||||
filename = filename + ".png"
|
||||
case "image/gif":
|
||||
filename = filename + ".gif"
|
||||
}
|
||||
// 保存文件
|
||||
_, err = os.Stat(path)
|
||||
if err != nil && !os.IsExist(err) {
|
||||
os.MkdirAll(path, 0644)
|
||||
}
|
||||
f, err := os.OpenFile(path+"/"+filename, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer f.Close()
|
||||
f.Write(data)
|
||||
return filename, nil
|
||||
}
|
||||
|
||||
// QAMatch 返回对应的权限
|
||||
func QAMatch() zero.Rule {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
switch ctx.State["regex_matched"].([]string)[1] {
|
||||
case "角色":
|
||||
ctx.State["qa_pool"] = QACharPool
|
||||
ctx.State["qa_user"] = CharIndex[Char[ctx.Event.GroupID]]
|
||||
return true
|
||||
case "有人":
|
||||
ctx.State["qa_pool"] = QAGroupPool
|
||||
ctx.State["qa_user"] = ctx.Event.GroupID
|
||||
return true
|
||||
case "我":
|
||||
ctx.State["qa_pool"] = QAUserPool
|
||||
ctx.State["qa_user"] = ctx.Event.UserID
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// QAPermission 返回对应的权限
|
||||
func QAPermission() zero.Rule {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
switch ctx.State["regex_matched"].([]string)[1] {
|
||||
case "角色":
|
||||
return zero.AdminPermission(ctx)
|
||||
case "有人":
|
||||
return zero.AdminPermission(ctx)
|
||||
case "我":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -8,9 +8,10 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
|
||||
15
go.mod
15
go.mod
@ -1,13 +1,18 @@
|
||||
module github.com/Yiwen-Chan/ZeroBot-Plugin
|
||||
module github.com/FloatTech/ZeroBot-Plugin
|
||||
|
||||
go 1.15
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/antchfx/htmlquery v1.2.3
|
||||
github.com/fumiama/ZeroBot-Plugin-Timer v0.0.0-20210616151841-d047372a50c2
|
||||
github.com/mattn/go-sqlite3 v1.14.7
|
||||
github.com/FloatTech/AnimeAPI v0.0.0-20210619082314-946db9a31a27
|
||||
github.com/antchfx/xpath v1.2.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816
|
||||
github.com/tidwall/gjson v1.8.0
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/wdvxdr1123/ZeroBot v1.2.0
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect
|
||||
golang.org/x/sys v0.0.0-20210603125802-9665404d3644 // indirect
|
||||
modernc.org/sqlite v1.10.8
|
||||
)
|
||||
|
||||
90
go.sum
90
go.sum
@ -1,5 +1,5 @@
|
||||
github.com/Yiwen-Chan/ZeroBot-Plugin v0.0.0-20210606065432-ce326ce97753/go.mod h1:54LOXRTKW0iR0BcKwRSUK46KfLPz7hiLcGMD5GGtL0k=
|
||||
github.com/Yiwen-Chan/ZeroBot-Plugin v0.0.0-20210606082630-29be1bd5eca6/go.mod h1:UfFAgNpRzp1N9HFmYoUlBJ4nvJOMJC9fMBBHQoaHmf8=
|
||||
github.com/FloatTech/AnimeAPI v0.0.0-20210619082314-946db9a31a27 h1:/KNwMUtZWOzQUZ6UhK3XlkLErH+233dmb6NmJw5UMi8=
|
||||
github.com/FloatTech/AnimeAPI v0.0.0-20210619082314-946db9a31a27/go.mod h1:GYrQD70HvBzry1XiZ1tHFNOsOqRkR+ao4XGYZqV4I9c=
|
||||
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/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk=
|
||||
@ -8,30 +8,29 @@ github.com/antchfx/xpath v1.2.0/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwq
|
||||
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/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fumiama/ZeroBot-Plugin-Timer v0.0.0-20210606064339-d55b94d71eee/go.mod h1:RN0gCtafWRu2d7lMg9/5UfZDhtsPgdeUovsyuSwl+oQ=
|
||||
github.com/fumiama/ZeroBot-Plugin-Timer v0.0.0-20210606075146-09f50acdb4de/go.mod h1:vG2ODqgJYFQobphBnhhmNv3TO+j/ZNYvN6FjUP/zkmA=
|
||||
github.com/fumiama/ZeroBot-Plugin-Timer v0.0.0-20210616151841-d047372a50c2 h1:8gJPxljHfnIFsE0ZfV8DJuI45Y+zTe/o2YtjKQRGYX8=
|
||||
github.com/fumiama/ZeroBot-Plugin-Timer v0.0.0-20210616151841-d047372a50c2/go.mod h1:/Tv1kgOdp76gvr1VoVmMG2Xu4c76vXngy6P8NFE4pA0=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
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.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
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.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
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/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/mattn/go-sqlite3 v1.14.7 h1:fxWBnXkxfM6sRiuH3bqJ4CfzZojMOLVc0UTsTglEghA=
|
||||
github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
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/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@ -43,6 +42,8 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
|
||||
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/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
@ -60,39 +61,88 @@ github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ
|
||||
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.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tidwall/pretty v1.1.1 h1:nt6/Ot5LtZnJCWwEFlelOixPo0xhPFsuZlKyOL3Xfnc=
|
||||
github.com/tidwall/pretty v1.1.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/wdvxdr1123/ZeroBot v1.2.0 h1:GmCkbzMMq3iugViKDtLbsL7joi29uG3/tp1554nboWI=
|
||||
github.com/wdvxdr1123/ZeroBot v1.2.0/go.mod h1:83nHtG8V5TAxPwH/LCDxLpZk4khIgs29dkr5TBWf7fc=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
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-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
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-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I=
|
||||
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78 h1:M8tBwCtWD/cZV9DZpFYRUgaymAYAr+aIUTWzDaM3uPs=
|
||||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/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 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
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=
|
||||
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=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
modernc.org/cc/v3 v3.32.4/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878=
|
||||
modernc.org/cc/v3 v3.33.5 h1:gfsIOmcv80EelyQyOHn/Xhlzex8xunhQxWiJRMYmPrI=
|
||||
modernc.org/cc/v3 v3.33.5/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878=
|
||||
modernc.org/ccgo/v3 v3.9.2/go.mod h1:gnJpy6NIVqkETT+L5zPsQFj7L2kkhfPMzOghRNv/CFo=
|
||||
modernc.org/ccgo/v3 v3.9.4 h1:mt2+HyTZKxva27O6T4C9//0xiNQ/MornL3i8itM5cCs=
|
||||
modernc.org/ccgo/v3 v3.9.4/go.mod h1:19XAY9uOrYnDhOgfHwCABasBvK69jgC4I8+rizbk3Bc=
|
||||
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
|
||||
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
|
||||
modernc.org/libc v1.7.13-0.20210308123627-12f642a52bb8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
|
||||
modernc.org/libc v1.9.5 h1:zv111ldxmP7DJ5mOIqzRbza7ZDl3kh4ncKfASB2jIYY=
|
||||
modernc.org/libc v1.9.5/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
|
||||
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/mathutil v1.2.2 h1:+yFk8hBprV+4c0U9GjFtL+dV3N8hOJ8JCituQcMShFY=
|
||||
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/memory v1.0.4 h1:utMBrFcpnQDdNsmM6asmyH/FM9TqLPS7XF7otpJmrwM=
|
||||
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc=
|
||||
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
|
||||
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sqlite v1.10.8 h1:tZzV+/FwlSBddiJAHLR+qxsw2nx7jpLMKOCVu6NTjxI=
|
||||
modernc.org/sqlite v1.10.8/go.mod h1:k45BYY2DU82vbS/dJ24OzHCtjPeMEcZ1DV2POiE8nRs=
|
||||
modernc.org/strutil v1.1.0 h1:+1/yCzZxY2pZwwrsbH+4T7BQMoLQ9QiBshRC9eicYsc=
|
||||
modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
|
||||
modernc.org/tcl v1.5.2 h1:sYNjGr4zK6cDH74USl8wVJRrvDX6UOLpG0j4lFvR0W0=
|
||||
modernc.org/tcl v1.5.2/go.mod h1:pmJYOLgpiys3oI4AeAafkcUfE+TKKilminxNyU/+Zlo=
|
||||
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
|
||||
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
|
||||
modernc.org/z v1.0.1 h1:WyIDpEpAIx4Hel6q/Pcgj/VhaQV5XPJ2I6ryIYbjnpc=
|
||||
modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
|
||||
|
||||
210
huahua/huahua.go
210
huahua/huahua.go
@ -1,210 +0,0 @@
|
||||
package huahua
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"strings"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var (
|
||||
PRIO = -1
|
||||
ENABLE = true
|
||||
RES = "https://raw.dihe.moe/Yiwen-Chan/ZeroBot-Plugin/master/huahua/"
|
||||
)
|
||||
|
||||
func init() {
|
||||
zero.OnFullMatch("椛椛醒醒", zero.AdminPermission).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ENABLE = true
|
||||
ctx.SendChain(randText("啊……好困啊……"))
|
||||
})
|
||||
zero.OnFullMatch("椛椛睡吧", zero.AdminPermission).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ENABLE = false
|
||||
ctx.SendChain(randText("那晚安咯……"))
|
||||
})
|
||||
zero.OnRegex("^。{1,6}$", HuaHuaSwitch(), HuaHuaChance(80)).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
count := strings.Count(ctx.Event.Message.CQString(), "。")
|
||||
ctx.SendChain(message.Text(
|
||||
[]string{
|
||||
"一个泡泡。。",
|
||||
"两个泡泡。",
|
||||
"三个泡泡",
|
||||
"四个泡泡。。",
|
||||
"五个泡泡",
|
||||
"六个泡泡",
|
||||
}[count-1],
|
||||
))
|
||||
})
|
||||
zero.OnFullMatchGroup([]string{"!", "!"}, HuaHuaSwitch(), HuaHuaChance(80)).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("一个感叹号"))
|
||||
})
|
||||
zero.OnFullMatchGroup([]string{"!?", "?!", "!?", "?!"}, HuaHuaSwitch(), HuaHuaChance(80)).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("惊讶"))
|
||||
})
|
||||
zero.OnFullMatch("…", HuaHuaSwitch(), HuaHuaChance(80)).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("不知道该说什么", "啊咧?"))
|
||||
})
|
||||
zero.OnKeyword("不记得", HuaHuaSwitch(), HuaHuaChance(80)).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("忘川河流淌而过"))
|
||||
})
|
||||
zero.OnKeywordGroup([]string{"可怜", "好累啊"}, HuaHuaSwitch(), HuaHuaChance(80)).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("给你抱抱", "摸摸头(๑•́ωก̀๑)"))
|
||||
})
|
||||
zero.OnKeyword("好冷", HuaHuaSwitch(), HuaHuaChance(80)).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("多穿点", "赶紧躺被窝"))
|
||||
})
|
||||
// 喊道椛椛
|
||||
zero.OnFullMatch("啾啾", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("啾啾"))
|
||||
})
|
||||
zero.OnFullMatch("乖", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("好饿……先请我吃饭饭"))
|
||||
})
|
||||
zero.OnKeyword("听话", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("我只听主人的话"))
|
||||
})
|
||||
zero.OnFullMatch("举高高", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("好重,举不动!"))
|
||||
})
|
||||
zero.OnKeyword("何在", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("我在二次元"))
|
||||
})
|
||||
zero.OnFullMatch("傲娇", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("哼"))
|
||||
})
|
||||
zero.OnFullMatch("卖萌", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("(´ฅω•ฅ`)チラッ"))
|
||||
})
|
||||
zero.OnFullMatch("变身", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("人家才不是马猴烧酒呐!"))
|
||||
})
|
||||
zero.OnFullMatch("可爱", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("٩(๑òωó๑)۶"))
|
||||
})
|
||||
zero.OnKeyword("吃饭了吗", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("等你投食"))
|
||||
})
|
||||
zero.OnKeyword("吃鱼", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("姬气人吃不得这些东西"))
|
||||
})
|
||||
zero.OnKeyword("唱歌", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("不唱"))
|
||||
})
|
||||
zero.OnKeyword("在不在", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("好啦好啦"))
|
||||
})
|
||||
zero.OnKeyword("坏掉了", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("我不是我没有"))
|
||||
})
|
||||
zero.OnKeyword("夸人", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("真是太厉害了呢"))
|
||||
})
|
||||
zero.OnKeyword("女仆模式", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("狗修金sama"))
|
||||
})
|
||||
zero.OnKeyword("抱抱", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("请不要乱摸"))
|
||||
})
|
||||
zero.OnKeyword("揉揉", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("不要不可以"))
|
||||
})
|
||||
zero.OnKeyword("摸头", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("不行,你摸不到"))
|
||||
})
|
||||
zero.OnKeyword("摸摸", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("lsp走开"))
|
||||
})
|
||||
zero.OnKeyword("放屁", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("我只是个姬气人,你想多了"))
|
||||
})
|
||||
zero.OnKeyword("数数", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("就不数"))
|
||||
})
|
||||
zero.OnKeyword("爱我", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("才不爱你呢"))
|
||||
})
|
||||
zero.OnKeyword("被玩坏了", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("你才被玩坏了"))
|
||||
})
|
||||
zero.OnKeyword("跳舞", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("跳你妹,我只是姬气人"))
|
||||
})
|
||||
zero.OnKeyword("过肩摔", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("椛椛不会"))
|
||||
})
|
||||
zero.OnKeyword("还能塞得下", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("凑不要脸"))
|
||||
})
|
||||
zero.OnKeyword("钉宫三连", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("八嘎hentai无路赛"))
|
||||
})
|
||||
zero.OnKeyword("攻略", HuaHuaSwitch(), HuaHuaChance(80), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("lsp别想泡我"))
|
||||
})
|
||||
}
|
||||
|
||||
func randText(text ...string) message.MessageSegment {
|
||||
length := len(text)
|
||||
return message.Text(text[rand.Intn(length)])
|
||||
}
|
||||
|
||||
func randImage(file ...string) message.MessageSegment {
|
||||
length := len(file)
|
||||
return message.Image(RES + file[rand.Intn(length)])
|
||||
}
|
||||
|
||||
// HuaHuaSwitch 控制 HuaHua 的开关
|
||||
func HuaHuaSwitch() zero.Rule {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
return ENABLE
|
||||
}
|
||||
}
|
||||
|
||||
// HuaHuaChance 概率响应,输入回应 1-100
|
||||
func HuaHuaChance(percent int) zero.Rule {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
if r := rand.Intn(100); r <= percent-1 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
49
main.go
49
main.go
@ -2,33 +2,31 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
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/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
// 注:以下插件均可通过前面加 // 注释,注释后停用并不加载插件
|
||||
// 下列插件可与 wdvxdr1123/ZeroBot v1.1.2 以上配合单独使用
|
||||
// 词库类
|
||||
_ "github.com/Yiwen-Chan/ZeroBot-Plugin/atri" // ATRI词库
|
||||
_ "github.com/Yiwen-Chan/ZeroBot-Plugin/chat" // 基础词库
|
||||
_ "github.com/Yiwen-Chan/ZeroBot-Plugin/huahua" // 椛椛词库
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/atri" // ATRI词库
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/chat" // 基础词库
|
||||
|
||||
// 实用类
|
||||
_ "github.com/Yiwen-Chan/ZeroBot-Plugin/github" // 搜索GitHub仓库
|
||||
_ "github.com/Yiwen-Chan/ZeroBot-Plugin/manager" // 群管
|
||||
_ "github.com/Yiwen-Chan/ZeroBot-Plugin/runcode" // 在线运行代码
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/github" // 搜索GitHub仓库
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/manager" // 群管
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/runcode" // 在线运行代码
|
||||
|
||||
// 娱乐类
|
||||
_ "github.com/Yiwen-Chan/ZeroBot-Plugin/music" // 点歌
|
||||
_ "github.com/Yiwen-Chan/ZeroBot-Plugin/picsearcher" // 搜图
|
||||
_ "github.com/Yiwen-Chan/ZeroBot-Plugin/randimg" //简易随机图片
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/music" // 点歌
|
||||
//_ "github.com/Yiwen-Chan/ZeroBot-Plugin/randimg" //简易随机图片
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/setutime" // 涩图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/shindan" // 测定
|
||||
|
||||
_ "github.com/Yiwen-Chan/ZeroBot-Plugin/setutime" // 涩图
|
||||
_ "github.com/Yiwen-Chan/ZeroBot-Plugin/shindan" // 测定
|
||||
// 以下为内置依赖,勿动
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/driver"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
easy "github.com/t-tomalak/logrus-easy-formatter"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -44,16 +42,19 @@ func main() {
|
||||
====================[ZeroBot-Plugin]====================
|
||||
* OneBot + ZeroBot + Golang
|
||||
* Version 1.0.3 - 2021-05-02 18:50:40.5489203 +0800 CST
|
||||
* Copyright © 2021 Kanri, DawnNights, All Rights Reserved
|
||||
* Project: https://github.com/Yiwen-Chan/ZeroBot-Plugin
|
||||
* Copyright © 2021 Kanri, DawnNights, Fumiama
|
||||
* Project: https://github.com/FloatTech/ZeroBot-Plugin
|
||||
========================================================
|
||||
`) // 启动打印
|
||||
zero.Run(zero.Config{
|
||||
NickName: []string{"椛椛", "ATRI", "atri", "亚托莉", "アトリ"},
|
||||
CommandPrefix: "/",
|
||||
SuperUsers: os.Args[1:], // 必须修改,否则无权限
|
||||
SuperUsers: []string{"213864964"}, // 必须修改,否则无权限
|
||||
Driver: []zero.Driver{
|
||||
driver.NewWebSocketClient("ws://127.0.0.1:6700/", ""),
|
||||
&driver.WSClient{
|
||||
Url: "ws://127.0.0.1:6700",
|
||||
AccessToken: "",
|
||||
},
|
||||
},
|
||||
})
|
||||
// 帮助
|
||||
@ -62,8 +63,8 @@ func main() {
|
||||
ctx.SendChain(message.Text(
|
||||
"* OneBot + ZeroBot + Golang ", "\n",
|
||||
"* Version 1.0.3 - 2021-05-02 18:50:40.5489203 +0800 CST", "\n",
|
||||
"* Copyright © 2021 Kanri, DawnNights, All Rights Reserved ", "\n",
|
||||
"* Project: https://github.com/Yiwen-Chan/ZeroBot-Plugin",
|
||||
"* Copyright © 2021 Kanri, DawnNights, Fumiama ", "\n",
|
||||
"* Project: https://github.com/FloatTech/ZeroBot-Plugin",
|
||||
))
|
||||
})
|
||||
select {}
|
||||
|
||||
@ -7,7 +7,6 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
timer "github.com/fumiama/ZeroBot-Plugin-Timer"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
@ -234,37 +233,39 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("📧 --> " + ctx.State["regex_matched"].([]string)[1]))
|
||||
return
|
||||
})
|
||||
// 定时提醒
|
||||
zero.OnRegex(`^在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分时(用.+)?提醒大家(.*)`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
dateStrs := ctx.State["regex_matched"].([]string)
|
||||
ts := timer.GetFilledTimeStamp(dateStrs, false)
|
||||
ts.Grpid = uint64(ctx.Event.GroupID)
|
||||
if ts.Enable {
|
||||
go timer.RegisterTimer(ts, true)
|
||||
ctx.Send("记住了~")
|
||||
} else {
|
||||
ctx.Send("参数非法!")
|
||||
}
|
||||
return
|
||||
})
|
||||
// 取消定时
|
||||
zero.OnRegex(`^取消在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分的提醒`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
dateStrs := ctx.State["regex_matched"].([]string)
|
||||
ts := timer.GetFilledTimeStamp(dateStrs, true)
|
||||
ti := timer.GetTimerInfo(ts)
|
||||
t, ok := (*timer.Timers)[ti]
|
||||
if ok {
|
||||
t.Enable = false
|
||||
delete(*timer.Timers, ti) //避免重复取消
|
||||
timer.SaveTimers()
|
||||
ctx.Send("取消成功~")
|
||||
} else {
|
||||
ctx.Send("没有这个定时器哦~")
|
||||
}
|
||||
return
|
||||
})
|
||||
/*
|
||||
// 定时提醒
|
||||
zero.OnRegex(`^在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分时(用.+)?提醒大家(.*)`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
dateStrs := ctx.State["regex_matched"].([]string)
|
||||
ts := timer.GetFilledTimeStamp(dateStrs, false)
|
||||
ts.Grpid = uint64(ctx.Event.GroupID)
|
||||
if ts.Enable {
|
||||
go timer.RegisterTimer(ts, true)
|
||||
ctx.Send("记住了~")
|
||||
} else {
|
||||
ctx.Send("参数非法!")
|
||||
}
|
||||
return
|
||||
})
|
||||
// 取消定时
|
||||
zero.OnRegex(`^取消在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分的提醒`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
dateStrs := ctx.State["regex_matched"].([]string)
|
||||
ts := timer.GetFilledTimeStamp(dateStrs, true)
|
||||
ti := timer.GetTimerInfo(ts)
|
||||
t, ok := (*timer.Timers)[ti]
|
||||
if ok {
|
||||
t.Enable = false
|
||||
delete(*timer.Timers, ti) //避免重复取消
|
||||
timer.SaveTimers()
|
||||
ctx.Send("取消成功~")
|
||||
} else {
|
||||
ctx.Send("没有这个定时器哦~")
|
||||
}
|
||||
return
|
||||
})
|
||||
*/
|
||||
// 随机点名
|
||||
zero.OnFullMatchGroup([]string{"翻牌"}).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
/*
|
||||
QQ音乐、网易云、酷狗、酷我 点歌
|
||||
*/
|
||||
package music
|
||||
|
||||
import (
|
||||
|
||||
@ -1,91 +0,0 @@
|
||||
package picsearcher
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/Yiwen-Chan/ZeroBot-Plugin/api/context"
|
||||
"github.com/Yiwen-Chan/ZeroBot-Plugin/api/pixiv"
|
||||
apiutils "github.com/Yiwen-Chan/ZeroBot-Plugin/api/utils"
|
||||
utils "github.com/Yiwen-Chan/ZeroBot-Plugin/picsearcher/utils"
|
||||
)
|
||||
|
||||
var (
|
||||
CACHEPATH = os.TempDir() // 缓冲图片路径
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
if strings.Contains(CACHEPATH, "\\") {
|
||||
CACHEPATH += "\\picsch\\"
|
||||
} else {
|
||||
CACHEPATH += "/picsch/"
|
||||
}
|
||||
apiutils.CreatePath(CACHEPATH)
|
||||
// 根据PID搜图
|
||||
zero.OnRegex(`^搜图(\d+)$`).SetBlock(true).SetPriority(30).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
id := apiutils.Str2Int(ctx.State["regex_matched"].([]string)[1])
|
||||
ctx.Send("少女祈祷中......")
|
||||
// 获取P站插图信息
|
||||
illust := &pixiv.Illust{}
|
||||
if err := illust.IllustInfo(id); err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
return
|
||||
}
|
||||
// 下载P站插图
|
||||
savePath, err := illust.PixivPicDown(CACHEPATH)
|
||||
if err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
return
|
||||
}
|
||||
// 发送搜索结果
|
||||
ctx.Send(illust.DetailPic(savePath))
|
||||
illust.RmPic(CACHEPATH)
|
||||
})
|
||||
// 以图搜图
|
||||
zero.OnMessage(FullMatchText("以图搜图", "搜索图片", "以图识图"), context.MustHasPicture()).SetBlock(true).SetPriority(999).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 开始搜索图片
|
||||
ctx.Send("少女祈祷中......")
|
||||
for _, pic := range ctx.State["image_url"].([]string) {
|
||||
fmt.Println(pic)
|
||||
if m, err := utils.SauceNaoSearch(pic); err == nil {
|
||||
ctx.SendChain(m...) // 返回SauceNAO的结果
|
||||
continue
|
||||
} else {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
}
|
||||
if m, err := utils.Ascii2dSearch(pic); err == nil {
|
||||
ctx.SendChain(m...) // 返回Ascii2d的结果
|
||||
continue
|
||||
} else {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// FullMatchText 如果信息中文本完全匹配则返回 true
|
||||
func FullMatchText(src ...string) zero.Rule {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
msg := ctx.Event.Message
|
||||
for _, elem := range msg {
|
||||
if elem.Type == "text" {
|
||||
text := elem.Data["text"]
|
||||
text = strings.ReplaceAll(text, " ", "")
|
||||
text = strings.ReplaceAll(text, "\r", "")
|
||||
text = strings.ReplaceAll(text, "\n", "")
|
||||
for _, s := range src {
|
||||
if text == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -1,99 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/Yiwen-Chan/ZeroBot-Plugin/api/pixiv"
|
||||
"github.com/Yiwen-Chan/ZeroBot-Plugin/api/utils"
|
||||
xpath "github.com/antchfx/htmlquery"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
// Ascii2dSearch Ascii2d 以图搜图
|
||||
// 第一个参数 返回错误
|
||||
// 第二个参数 返回的信息
|
||||
func Ascii2dSearch(pic string) (message.Message, 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 nil, 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 nil, err
|
||||
}
|
||||
defer bovwResp.Body.Close()
|
||||
// 解析XPATH
|
||||
doc, err := xpath.Parse(resp.Body)
|
||||
if err != nil {
|
||||
return nil, 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 nil, fmt.Errorf("Ascii2d not found")
|
||||
}
|
||||
var id = utils.Str2Int(link[index+1:])
|
||||
if id == 0 {
|
||||
return nil, fmt.Errorf("convert to pid error")
|
||||
}
|
||||
// 根据PID查询插图信息
|
||||
var illust = &pixiv.Illust{}
|
||||
if err := illust.IllustInfo(id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if illust.AgeLimit != "all-age" {
|
||||
return nil, fmt.Errorf("Ascii2d not found")
|
||||
}
|
||||
// 返回插图信息文本
|
||||
return message.Message{
|
||||
message.Text(
|
||||
"[SetuTime] emmm大概是这个?", "\n",
|
||||
"标题:", illust.Title, "\n",
|
||||
"插画ID:", illust.Pid, "\n",
|
||||
"画师:", illust.UserName, "\n",
|
||||
"画师ID:", illust.UserId, "\n",
|
||||
"直链:", "https://pixivel.moe/detail?id=", illust.Pid,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
@ -1,77 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
// SauceNaoSearch SauceNao 以图搜图 需要链接 返回错误和信息
|
||||
func SauceNaoSearch(pic string) (message.Message, error) {
|
||||
var (
|
||||
api = "https://saucenao.com/search.php"
|
||||
apiKey = "2cc2772ca550dbacb4c35731a79d341d1a143cb5"
|
||||
|
||||
minSimilarity = 70.0 // 返回图片结果的最小相似度
|
||||
)
|
||||
|
||||
// 包装请求参数
|
||||
link, _ := url.Parse(api)
|
||||
link.RawQuery = url.Values{
|
||||
"url": []string{pic},
|
||||
"api_key": []string{apiKey},
|
||||
"db": []string{"5"},
|
||||
"numres": []string{"1"},
|
||||
"output_type": []string{"2"},
|
||||
}.Encode()
|
||||
|
||||
// 网络请求
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequest("GET", link.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
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 nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
// 如果返回不是200则立刻抛出错误
|
||||
return nil, fmt.Errorf("SauceNAO not found, code %d", resp.StatusCode)
|
||||
}
|
||||
content := gjson.ParseBytes(body)
|
||||
if status := content.Get("header.status").Int(); status != 0 {
|
||||
// 如果json信息返回status不为0则立刻抛出错误
|
||||
return nil, fmt.Errorf("SauceNAO not found, status %d", status)
|
||||
}
|
||||
if content.Get("results.0.header.similarity").Float() < minSimilarity {
|
||||
return nil, fmt.Errorf("SauceNAO not found")
|
||||
}
|
||||
result := content.Get("results.0")
|
||||
// 正常发送
|
||||
return message.Message{
|
||||
message.Text("[SetuTime] 我有把握是这个!"),
|
||||
message.Image(result.Get("header.thumbnail").Str),
|
||||
message.Text(
|
||||
"\n",
|
||||
"相似度:", result.Get("header.similarity").Str, "\n",
|
||||
"标题:", result.Get("data.title").Str, "\n",
|
||||
"插画ID:", result.Get("data.pixiv_id").Int(), "\n",
|
||||
"画师:", result.Get("data.member_name").Str, "\n",
|
||||
"画师ID:", result.Get("data.member_id").Int(), "\n",
|
||||
"直链:", "https://pixivel.moe/detail?id=", result.Get("data.pixiv_id").Int(),
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
2
run.bat
2
run.bat
@ -1,7 +1,7 @@
|
||||
go version
|
||||
gcc -v
|
||||
go env -w GOPROXY=https://goproxy.cn,direct
|
||||
go env -w GO111MODULE=auto
|
||||
go mod tidy
|
||||
::go build -ldflags="-s -w" -o ZeroBot-Plugin.exe
|
||||
go run main.go
|
||||
pause
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
go version
|
||||
gcc -v
|
||||
go env -w GOPROXY=https://goproxy.cn,direct
|
||||
go env -w GO111MODULE=auto
|
||||
go mod tidy
|
||||
go build -ldflags="-s -w" -o ZeroBot-Plugin-windows.exe
|
||||
pause
|
||||
#go build -ldflags="-s -w" -o ZeroBot-Plugin
|
||||
go run main.go
|
||||
@ -1,3 +1,6 @@
|
||||
/*
|
||||
基于 https://tool.runoob.com 的在线运行代码
|
||||
*/
|
||||
package runcode
|
||||
|
||||
import (
|
||||
@ -8,10 +11,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/extension/rate"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
var limit = rate.NewManager(time.Minute*3, 5)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package classify
|
||||
package setutime
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -8,10 +8,10 @@ import (
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/Yiwen-Chan/ZeroBot-Plugin/api/msgext"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -88,7 +88,7 @@ func replyClass(ctx *zero.Ctx, dhash string, class int, noimg bool) {
|
||||
} else {
|
||||
var last_message_id int64
|
||||
if !noimg {
|
||||
last_message_id = ctx.Send(msgext.ImageNoCache(CACHE_URI))
|
||||
last_message_id = ctx.SendChain(message.Image(CACHE_URI).Add("no_cache", "0"))
|
||||
last_group_id := ctx.Event.GroupID
|
||||
MsgofGrp[last_group_id] = last_message_id
|
||||
dhashofmsg[last_message_id] = dhash
|
||||
167
setutime/pic_searcher.go
Normal file
167
setutime/pic_searcher.go
Normal file
@ -0,0 +1,167 @@
|
||||
package setutime
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/ascii2d"
|
||||
"github.com/FloatTech/AnimeAPI/pixiv"
|
||||
"github.com/FloatTech/AnimeAPI/saucenao"
|
||||
)
|
||||
|
||||
var (
|
||||
CACHEPATH = os.TempDir() // 缓冲图片路径
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
// 根据PID搜图
|
||||
zero.OnRegex(`^搜图(\d+)$`).SetBlock(true).SetPriority(30).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
id, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
|
||||
ctx.Send("少女祈祷中......")
|
||||
// 获取P站插图信息
|
||||
illust, err := pixiv.Works(id)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
// 下载P站插图
|
||||
if _, err := download(illust, "data/SetuTime/search/"); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
// 发送搜索结果
|
||||
ctx.SendChain(
|
||||
message.Image(file(illust)),
|
||||
message.Text(
|
||||
"\n",
|
||||
"标题:", illust.Title, "\n",
|
||||
"插画ID:", illust.Pid, "\n",
|
||||
"画师:", illust.UserName, "\n",
|
||||
"画师ID:", illust.UserId, "\n",
|
||||
"直链:", "https://pixivel.moe/detail?id=", illust.Pid,
|
||||
),
|
||||
)
|
||||
})
|
||||
// 以图搜图
|
||||
zero.OnMessage(FullMatchText("以图搜图", "搜索图片", "以图识图"), MustHasPicture()).SetBlock(true).SetPriority(999).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 开始搜索图片
|
||||
ctx.Send("少女祈祷中......")
|
||||
for _, pic := range ctx.State["image_url"].([]string) {
|
||||
fmt.Println(pic)
|
||||
if result, err := saucenao.SauceNAO(pic); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
} else {
|
||||
// 返回SauceNAO的结果
|
||||
ctx.SendChain(
|
||||
message.Text("我有把握是这个!"),
|
||||
message.Image(result.Thumbnail),
|
||||
message.Text(
|
||||
"\n",
|
||||
"相似度:", result.Similarity, "\n",
|
||||
"标题:", result.Title, "\n",
|
||||
"插画ID:", result.PixivID, "\n",
|
||||
"画师:", result.MemberName, "\n",
|
||||
"画师ID:", result.MemberID, "\n",
|
||||
"直链:", "https://pixivel.moe/detail?id=", result.PixivID,
|
||||
),
|
||||
)
|
||||
continue
|
||||
}
|
||||
if result, err := ascii2d.Ascii2d(pic); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
} else {
|
||||
// 返回Ascii2d的结果
|
||||
ctx.SendChain(
|
||||
message.Text(
|
||||
"大概是这个?", "\n",
|
||||
"标题:", result.Title, "\n",
|
||||
"插画ID:", result.Pid, "\n",
|
||||
"画师:", result.UserName, "\n",
|
||||
"画师ID:", result.UserId, "\n",
|
||||
"直链:", "https://pixivel.moe/detail?id=", result.Pid,
|
||||
),
|
||||
)
|
||||
continue
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// FullMatchText 如果信息中文本完全匹配则返回 true
|
||||
func FullMatchText(src ...string) zero.Rule {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
msg := ctx.Event.Message
|
||||
for _, elem := range msg {
|
||||
if elem.Type == "text" {
|
||||
text := elem.Data["text"]
|
||||
text = strings.ReplaceAll(text, " ", "")
|
||||
text = strings.ReplaceAll(text, "\r", "")
|
||||
text = strings.ReplaceAll(text, "\n", "")
|
||||
for _, s := range src {
|
||||
if text == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// HasPicture 消息含有图片返回 true
|
||||
func HasPicture() zero.Rule {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
msg := ctx.Event.Message
|
||||
url := []string{}
|
||||
// 如果是回复信息则将信息替换成被回复的那条
|
||||
if msg[0].Type == "reply" {
|
||||
id, _ := strconv.Atoi(msg[0].Data["id"])
|
||||
msg = ctx.GetMessage(int64(id)).Elements
|
||||
}
|
||||
// 遍历信息中所有图片
|
||||
for _, elem := range msg {
|
||||
if elem.Type == "image" {
|
||||
url = append(url, elem.Data["url"])
|
||||
}
|
||||
}
|
||||
// 如果有图片就返回true
|
||||
if len(url) > 0 {
|
||||
ctx.State["image_url"] = url
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// MustHasPicture 消息不存在图片阻塞60秒至有图片,超时返回 false
|
||||
func MustHasPicture() zero.Rule {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
if HasPicture()(ctx) {
|
||||
return true
|
||||
}
|
||||
// 没有图片就索取
|
||||
ctx.Send("请发送一张图片")
|
||||
next := zero.NewFutureEvent("message", 999, false, zero.CheckUser(ctx.Event.UserID), HasPicture())
|
||||
recv, cancel := next.Repeat()
|
||||
select {
|
||||
case e := <-recv:
|
||||
cancel()
|
||||
newCtx := &zero.Ctx{Event: e, State: zero.State{}}
|
||||
if HasPicture()(newCtx) {
|
||||
ctx.State["image_url"] = newCtx.State["image_url"]
|
||||
return true
|
||||
}
|
||||
return false
|
||||
case <-time.After(time.Second * 60):
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,11 @@
|
||||
package randimg
|
||||
package setutime
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/Yiwen-Chan/ZeroBot-Plugin/api/classify"
|
||||
"github.com/Yiwen-Chan/ZeroBot-Plugin/api/context"
|
||||
"github.com/Yiwen-Chan/ZeroBot-Plugin/api/msgext"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -30,7 +28,7 @@ func init() { // 插件主体
|
||||
zero.OnFullMatch("随机图片").SetBlock(true).SetPriority(24).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if ctx.Event.GroupID > 0 {
|
||||
classify.Classify(ctx, RANDOM_API_URL, false)
|
||||
Classify(ctx, RANDOM_API_URL, false)
|
||||
}
|
||||
return
|
||||
})
|
||||
@ -42,9 +40,9 @@ func init() { // 插件主体
|
||||
ctx.Send("请稍后再试哦")
|
||||
} else {
|
||||
BLOCK_REQUEST = true
|
||||
last_message_id := ctx.Send(msgext.ImageNoCache(RANDOM_API_URL))
|
||||
last_message_id := ctx.SendChain(message.Image(RANDOM_API_URL).Add("no_cache", "0"))
|
||||
last_group_id := ctx.Event.GroupID
|
||||
classify.MsgofGrp[last_group_id] = last_message_id
|
||||
MsgofGrp[last_group_id] = last_message_id
|
||||
BLOCK_REQUEST = false
|
||||
}
|
||||
}
|
||||
@ -53,21 +51,21 @@ func init() { // 插件主体
|
||||
// 撤回最后的随机图片
|
||||
zero.OnFullMatch("不许好").SetBlock(true).SetPriority(24).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
classify.Vote(ctx, 5)
|
||||
Vote(ctx, 5)
|
||||
})
|
||||
// 撤回最后的随机图片
|
||||
zero.OnFullMatch("太涩了").SetBlock(true).SetPriority(24).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
classify.Vote(ctx, 6)
|
||||
Vote(ctx, 6)
|
||||
})
|
||||
// 上传一张图进行评价
|
||||
zero.OnFullMatch("评价图片", context.MustHasPicture()).SetBlock(true).SetPriority(24).
|
||||
zero.OnFullMatch("评价图片", MustHasPicture()).SetBlock(true).SetPriority(24).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if ctx.Event.GroupID > 0 {
|
||||
ctx.Send("少女祈祷中......")
|
||||
for _, pic := range ctx.State["image_url"].([]string) {
|
||||
fmt.Println(pic)
|
||||
classify.Classify(ctx, pic, true)
|
||||
Classify(ctx, pic, true)
|
||||
}
|
||||
}
|
||||
return
|
||||
@ -1,140 +1,147 @@
|
||||
package setutime
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/extension/rate"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/Yiwen-Chan/ZeroBot-Plugin/api/pixiv"
|
||||
apiutils "github.com/Yiwen-Chan/ZeroBot-Plugin/api/utils"
|
||||
"github.com/Yiwen-Chan/ZeroBot-Plugin/setutime/utils"
|
||||
"github.com/FloatTech/AnimeAPI/pixiv"
|
||||
)
|
||||
|
||||
var limit = rate.NewManager(time.Minute*1, 5)
|
||||
// Pools 图片缓冲池
|
||||
type Pool struct {
|
||||
Lock sync.Mutex
|
||||
DB *Sqlite
|
||||
Path string
|
||||
Group int64
|
||||
List []string
|
||||
Max int
|
||||
Pool map[string][]*pixiv.Illust
|
||||
Form int64
|
||||
}
|
||||
|
||||
var (
|
||||
BOTPATH = apiutils.PathExecute() // 当前bot运行目录
|
||||
DATAPATH = BOTPATH + "data/SetuTime/" // 数据目录
|
||||
DBPATH = DATAPATH + "SetuTime.db" // 数据库路径
|
||||
|
||||
CACHEPATH = DATAPATH + "cache/" // 缓冲图片路径
|
||||
CACHEGROUP int64 = 0 // 缓冲图片群,为0即可
|
||||
PoolList = []string{"涩图", "二次元", "风景", "车万"} // 可自定义
|
||||
|
||||
DB = utils.Sqlite{DBPath: DBPATH} // 新建涩图数据库对象
|
||||
PoolsCache = utils.NewPoolsCache() // 新建一个缓冲池对象
|
||||
|
||||
FORM = "PIC" // 默认 PIC 格式
|
||||
)
|
||||
|
||||
func init() {
|
||||
PoolsCache.Group = CACHEGROUP // 图片缓冲群
|
||||
PoolsCache.Path = CACHEPATH // 缓冲图片路径
|
||||
|
||||
apiutils.CreatePath(DBPATH)
|
||||
apiutils.CreatePath(CACHEPATH)
|
||||
|
||||
for i := range PoolList {
|
||||
if err := DB.Create(PoolList[i], &pixiv.Illust{}); err != nil {
|
||||
// NewPoolsCache 返回一个缓冲池对象
|
||||
func NewPools() *Pool {
|
||||
cache := &Pool{
|
||||
DB: &Sqlite{DBPath: "data/SetuTime/SetuTime.db"},
|
||||
Path: "data/SetuTime/cache/",
|
||||
Group: 0,
|
||||
List: []string{"涩图", "二次元", "风景", "车万"}, // 可以自己加类别,得自己加图片进数据库
|
||||
Max: 10,
|
||||
Pool: map[string][]*pixiv.Illust{},
|
||||
Form: 0,
|
||||
}
|
||||
err := os.MkdirAll(cache.Path, 0644)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for i := range cache.List {
|
||||
if err := cache.DB.Create(cache.List[i], &pixiv.Illust{}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
return cache
|
||||
}
|
||||
|
||||
var (
|
||||
POOL = NewPools()
|
||||
limit = rate.NewManager(time.Minute*1, 5)
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
zero.OnRegex(`^来份(.*)$`, FirstValueInList(PoolList)).SetBlock(true).SetPriority(20).
|
||||
zero.OnRegex(`^来份(.*)$`, FirstValueInList(POOL.List)).SetBlock(true).SetPriority(20).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if !limit.Load(ctx.Event.UserID).Acquire() {
|
||||
ctx.Send("请稍后重试0x0...")
|
||||
ctx.SendChain(message.Text("少女祈祷中......"))
|
||||
return
|
||||
}
|
||||
var type_ = ctx.State["regex_matched"].([]string)[1]
|
||||
// 补充池子
|
||||
go func() {
|
||||
times := apiutils.Min(PoolsCache.Max-PoolsCache.Size(type_), 2)
|
||||
times := Min(POOL.Max-POOL.Size(type_), 2)
|
||||
for i := 0; i < times; i++ {
|
||||
illust := &pixiv.Illust{}
|
||||
// 查询出一张图片
|
||||
if err := DB.Select(type_, illust, "ORDER BY RANDOM() limit 1"); err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
if err := POOL.DB.Select(type_, illust, "ORDER BY RANDOM() limit 1"); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
continue
|
||||
}
|
||||
ctx.SendGroupMessage(PoolsCache.Group, "正在下载"+illust.ImageUrls)
|
||||
file, err := illust.PixivPicDown(PoolsCache.Path)
|
||||
// 下载图片
|
||||
file, err := download(illust, POOL.Path)
|
||||
if err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
continue
|
||||
}
|
||||
ctx.SendGroupMessage(PoolsCache.Group, illust.NormalPic(file))
|
||||
ctx.SendGroupMessage(POOL.Group, []message.MessageSegment{message.Image(file)})
|
||||
// 向缓冲池添加一张图片
|
||||
if err := PoolsCache.Push(type_, illust); err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
continue
|
||||
}
|
||||
POOL.Push(type_, illust)
|
||||
|
||||
time.Sleep(time.Second * 1)
|
||||
}
|
||||
}()
|
||||
// 如果没有缓存,阻塞5秒
|
||||
if PoolsCache.Size(type_) == 0 {
|
||||
ctx.Send("[SetuTime] 正在填充弹药......")
|
||||
if POOL.Size(type_) == 0 {
|
||||
ctx.SendChain(message.Text("INFO: 正在填充弹药......"))
|
||||
<-time.After(time.Second * 5)
|
||||
if PoolsCache.Size(type_) == 0 {
|
||||
ctx.Send("[SetuTime] 等待填充,请稍后再试......")
|
||||
if POOL.Size(type_) == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 等待填充,请稍后再试......"))
|
||||
return
|
||||
}
|
||||
}
|
||||
// 从缓冲池里抽一张
|
||||
if id := ctx.Send(PoolsCache.GetOnePic(type_, FORM)); id == 0 {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", errors.New("可能被风控了")))
|
||||
if id := ctx.SendChain(message.Image(file(POOL.Pop(type_)))); id == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
return
|
||||
})
|
||||
|
||||
zero.OnRegex(`^添加(.*?)(\d+)$`, FirstValueInList(PoolList), zero.SuperUserPermission).SetBlock(true).SetPriority(21).
|
||||
zero.OnRegex(`^添加(.*?)(\d+)$`, FirstValueInList(POOL.List), zero.SuperUserPermission).SetBlock(true).SetPriority(21).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var (
|
||||
type_ = ctx.State["regex_matched"].([]string)[1]
|
||||
id = apiutils.Str2Int(ctx.State["regex_matched"].([]string)[2])
|
||||
illust = &pixiv.Illust{}
|
||||
type_ = ctx.State["regex_matched"].([]string)[1]
|
||||
id, _ = strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
|
||||
)
|
||||
ctx.Send("少女祈祷中......")
|
||||
ctx.SendChain(message.Text("少女祈祷中......"))
|
||||
// 查询P站插图信息
|
||||
|
||||
if err := illust.IllustInfo(id); err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
illust, err := pixiv.Works(id)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
// 下载插画
|
||||
if _, err := illust.PixivPicDown(PoolsCache.Path); err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
if _, err := download(illust, POOL.Path); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", 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", "可能被风控,发送失败"))
|
||||
// 发送到发送者
|
||||
if id := ctx.SendChain(message.Image(file(illust))); id == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控,发送失败"))
|
||||
return
|
||||
}
|
||||
// 添加插画到对应的数据库table
|
||||
if err := DB.Insert(type_, illust); err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
if err := POOL.DB.Insert(type_, illust); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.Send("添加成功")
|
||||
return
|
||||
})
|
||||
|
||||
zero.OnRegex(`^删除(.*?)(\d+)$`, FirstValueInList(PoolList), zero.SuperUserPermission).SetBlock(true).SetPriority(22).
|
||||
zero.OnRegex(`^删除(.*?)(\d+)$`, FirstValueInList(POOL.List), zero.SuperUserPermission).SetBlock(true).SetPriority(22).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var (
|
||||
type_ = ctx.State["regex_matched"].([]string)[1]
|
||||
id = apiutils.Str2Int(ctx.State["regex_matched"].([]string)[2])
|
||||
id, _ = strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
|
||||
)
|
||||
// 查询数据库
|
||||
if err := DB.Delete(type_, fmt.Sprintf("WHERE pid=%d", id)); err != nil {
|
||||
if err := POOL.DB.Delete(type_, fmt.Sprintf("WHERE pid=%d", id)); err != nil {
|
||||
ctx.Send(fmt.Sprintf("ERROR: %v", err))
|
||||
return
|
||||
}
|
||||
@ -143,36 +150,22 @@ func init() { // 插件主体
|
||||
})
|
||||
|
||||
// 查询数据库涩图数量
|
||||
zero.OnFullMatchGroup([]string{"setu -s", "setu --status", ">setu status"}).SetBlock(true).SetPriority(23).
|
||||
zero.OnFullMatchGroup([]string{">setu status"}).SetBlock(true).SetPriority(23).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
state := []string{"[SetuTime]"}
|
||||
for i := range PoolList {
|
||||
num, err := DB.Num(PoolList[i])
|
||||
for i := range POOL.List {
|
||||
num, err := POOL.DB.Num(POOL.List[i])
|
||||
if err != nil {
|
||||
num = 0
|
||||
}
|
||||
state = append(state, "\n")
|
||||
state = append(state, PoolList[i])
|
||||
state = append(state, POOL.List[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", ">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", ">setu pic"}).SetBlock(true).SetPriority(24).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
FORM = "PIC"
|
||||
ctx.Send("[SetuTime] XML->OFF")
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
// FirstValueInList 判断正则匹配的第一个参数是否在列表中
|
||||
@ -187,3 +180,80 @@ func FirstValueInList(list []string) zero.Rule {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Min 返回两数最小值
|
||||
func Min(a, b int) int {
|
||||
switch {
|
||||
default:
|
||||
return a
|
||||
case a > b:
|
||||
return b
|
||||
case a < b:
|
||||
return a
|
||||
}
|
||||
}
|
||||
|
||||
// Size 返回缓冲池指定类型的现有大小
|
||||
func (p *Pool) Size(type_ string) int {
|
||||
return len(p.Pool[type_])
|
||||
}
|
||||
|
||||
// IsFull 返回缓冲池指定类型是否已满
|
||||
func (p *Pool) IsFull(type_ string) bool {
|
||||
return len(p.Pool[type_]) >= p.Max
|
||||
}
|
||||
|
||||
// Push 向缓冲池插入一张图片
|
||||
func (p *Pool) Push(type_ string, illust *pixiv.Illust) {
|
||||
p.Lock.Lock()
|
||||
defer p.Lock.Unlock()
|
||||
p.Pool[type_] = append(p.Pool[type_], illust)
|
||||
}
|
||||
|
||||
// Push 在缓冲池拿出一张图片
|
||||
func (p *Pool) Pop(type_ string) (illust *pixiv.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
|
||||
}
|
||||
|
||||
func file(i *pixiv.Illust) string {
|
||||
filename := fmt.Sprint(i.Pid)
|
||||
pwd, _ := os.Getwd()
|
||||
filepath := pwd + `\` + POOL.Path + filename
|
||||
if _, err := os.Stat(filepath + ".jpg"); err == nil || os.IsExist(err) {
|
||||
return `file:///` + filepath + ".jpg"
|
||||
}
|
||||
if _, err := os.Stat(filepath + ".png"); err == nil || os.IsExist(err) {
|
||||
return `file:///` + filepath + ".png"
|
||||
}
|
||||
if _, err := os.Stat(filepath + ".gif"); err == nil || os.IsExist(err) {
|
||||
return `file:///` + filepath + ".gif"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func download(i *pixiv.Illust, filedir string) (string, error) {
|
||||
filename := fmt.Sprint(i.Pid)
|
||||
filepath := filedir + filename
|
||||
if _, err := os.Stat(filepath + ".jpg"); err == nil || os.IsExist(err) {
|
||||
return filepath + ".jpg", nil
|
||||
}
|
||||
if _, err := os.Stat(filepath + ".png"); err == nil || os.IsExist(err) {
|
||||
return filepath + ".png", nil
|
||||
}
|
||||
if _, err := os.Stat(filepath + ".gif"); err == nil || os.IsExist(err) {
|
||||
return filepath + ".gif", nil
|
||||
}
|
||||
// 下载最大分辨率为 1200 的图片
|
||||
link := i.ImageUrls
|
||||
link = strings.ReplaceAll(link, "img-original", "img-master")
|
||||
link = strings.ReplaceAll(link, "_p0", "_p0_master1200")
|
||||
// 下载
|
||||
return pixiv.Download(link, filedir, filename)
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package utils
|
||||
package setutime
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
@ -6,7 +6,7 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
// Sqlite 数据库对象
|
||||
@ -20,7 +20,7 @@ type Sqlite struct {
|
||||
// 返回错误
|
||||
func (db *Sqlite) Create(table string, objptr interface{}) (err error) {
|
||||
if db.DB == nil {
|
||||
database, err := sql.Open("sqlite3", db.DBPath)
|
||||
database, err := sql.Open("sqlite", db.DBPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1,73 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/Yiwen-Chan/ZeroBot-Plugin/api/pixiv"
|
||||
)
|
||||
|
||||
// PoolsCache 图片缓冲池
|
||||
type PoolsCache struct {
|
||||
Lock sync.Mutex
|
||||
Max int
|
||||
Path string
|
||||
Group int64
|
||||
Pool map[string][]*pixiv.Illust
|
||||
}
|
||||
|
||||
// NewPoolsCache 返回一个缓冲池对象
|
||||
func NewPoolsCache() *PoolsCache {
|
||||
return &PoolsCache{
|
||||
Max: 10,
|
||||
Path: "./data/SetuTime/cache/",
|
||||
Group: 1048452984,
|
||||
Pool: map[string][]*pixiv.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 *pixiv.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 *pixiv.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)
|
||||
}
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
package utils
|
||||
|
||||
var (
|
||||
XML = true // 图片XML开关,默认开启
|
||||
)
|
||||
@ -4,144 +4,53 @@
|
||||
package shindan
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
xpath "github.com/antchfx/htmlquery"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/extension/rate"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/shindanmaker"
|
||||
)
|
||||
|
||||
var limit = rate.NewManager(time.Minute*5, 5)
|
||||
var (
|
||||
// 限制调用频率
|
||||
limit = rate.NewManager(time.Minute*5, 5)
|
||||
)
|
||||
|
||||
func init() {
|
||||
table := map[string]string{
|
||||
// 可自行添加,前面为指令名,后面为网页ID
|
||||
"异世界转生": "587874",
|
||||
"卖萌": "360578",
|
||||
"今天是什么少女": "162207",
|
||||
}
|
||||
zero.OnMessage(HasTableKey(table), GetName()).SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if !limit.Load(ctx.Event.UserID).Acquire() {
|
||||
ctx.Send("请稍后重试0x0...")
|
||||
return
|
||||
}
|
||||
|
||||
type_ := ctx.State["key"].(string)
|
||||
name := ctx.State["name"].(string)
|
||||
|
||||
text, err := shindanmaker(table[type_], name)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
}
|
||||
ctx.SendChain(message.Text(text))
|
||||
})
|
||||
zero.OnPrefix("异世界转生", number(587874)).SetBlock(true).FirstPriority().Handle(handle)
|
||||
zero.OnPrefix("今天是什么少女", number(162207)).SetBlock(true).FirstPriority().Handle(handle)
|
||||
zero.OnPrefix("卖萌", number(360578)).SetBlock(true).FirstPriority().Handle(handle)
|
||||
}
|
||||
|
||||
// HasTableKey 如果 ctx.Event.RawMessage 是以 table 的 key 开头,返回真
|
||||
func HasTableKey(table map[string]string) func(ctx *zero.Ctx) bool {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
msg := ctx.Event.RawMessage
|
||||
for key := range table {
|
||||
if strings.HasPrefix(msg, key) {
|
||||
temp := strings.TrimPrefix(msg, key)
|
||||
ctx.State["key"] = key
|
||||
ctx.State["trim_key"] = temp
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
// shindanmaker 处理函数
|
||||
var handle = func(ctx *zero.Ctx) {
|
||||
if !limit.Load(ctx.Event.UserID).Acquire() {
|
||||
ctx.Send("请稍后重试0x0...")
|
||||
return
|
||||
}
|
||||
// 获取名字
|
||||
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
|
||||
}
|
||||
// 调用接口
|
||||
text, err := shindanmaker.Shindanmaker(ctx.State["id"].(int64), name)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
}
|
||||
ctx.SendChain(message.Text(text))
|
||||
}
|
||||
|
||||
// GetName 获取名字
|
||||
// 如果 ctx.State["trim_key"] 为空
|
||||
// 则 ctx.State["name"] 为发送者的 名片 昵称 群头衔
|
||||
// 如果 rule:HasTableKey 中 ctx.State["trim_key"] 是艾特
|
||||
// 则 ctx.State["name"] 为 被艾特的人的 名片 昵称 群头衔
|
||||
// 否则 ctx.State["name"] 为 ctx.State["trim_key"]
|
||||
func GetName() func(ctx *zero.Ctx) bool {
|
||||
// 传入 shindanmaker id
|
||||
var number = func(id int64) func(ctx *zero.Ctx) bool {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
name := ctx.State["trim_key"].(string)
|
||||
arr := message.ParseMessageFromString(name)
|
||||
var qq int64 = 0
|
||||
switch {
|
||||
case name == "":
|
||||
qq = ctx.Event.UserID
|
||||
case arr[0].Type == "at":
|
||||
qq, _ = strconv.ParseInt(arr[0].Data["qq"], 10, 64)
|
||||
}
|
||||
// 获取名字
|
||||
info := ctx.GetGroupMemberInfo(ctx.Event.GroupID, qq, false)
|
||||
switch {
|
||||
case info.Get("nickname").Str != "":
|
||||
name = info.Get("nickname").Str
|
||||
case info.Get("card").Str != "":
|
||||
name = info.Get("card").Str
|
||||
case info.Get("title").Str != "":
|
||||
name = info.Get("title").Str
|
||||
}
|
||||
temp := []rune(name)
|
||||
if len(temp) > 20 {
|
||||
// 防止超长名字
|
||||
temp = temp[:20]
|
||||
}
|
||||
name = string(temp)
|
||||
ctx.State["name"] = name
|
||||
ctx.State["id"] = id
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// shindanmaker 返回网页 shindanmaker.com 测定结果
|
||||
func shindanmaker(id, name string) (string, error) {
|
||||
url := "https://shindanmaker.com/" + id
|
||||
// seed 使每一天的结果都不同
|
||||
now := time.Now()
|
||||
seed := fmt.Sprintf("%d%d%d", now.Year(), now.Month(), now.Day())
|
||||
name = name + seed
|
||||
|
||||
// 组装参数
|
||||
client := &http.Client{}
|
||||
payload := &bytes.Buffer{}
|
||||
writer := multipart.NewWriter(payload)
|
||||
_ = writer.WriteField("_token", "D6Rn2BTOTMht2FBKNhpwOWqymZuoifLNt31RqlLj")
|
||||
_ = writer.WriteField("name", name)
|
||||
_ = writer.WriteField("hiddenName", "名無しのV")
|
||||
_ = writer.Close()
|
||||
// 发送请求
|
||||
req, _ := http.NewRequest("POST", url, payload)
|
||||
req.Header.Add("Cookie", "_ga=GA1.2.531883706.1618563450; trc_cookie_storage=taboola%20global%3Auser-id=09ef6d7e-ddb2-4a3f-ac71-b75801d11fef-tuct7602eee; dui=eyJpdiI6ImJ0MThXNTFoZ1hVOXNWZXZFeTRDdlE9PSIsInZhbHVlIjoibUF3em14ZzhXbVJsL1k5b284Tzh5QUhHa0VSYWtYZjF3KzZNRkxtRmVIMHBUbnJ1M0JwNTEzaWhWTzZTT1NGcGVxdFhGaG11Y052a3hyUUZVZDRtNFc0ZndiRnVTSHJFL1hzak43QzNhYVd6cEFEZVJxZVNNNytpNHhQbnF0TGpmbXNNdFlUNjFwNVNubnVJbkN5NHNRPT0iLCJtYWMiOiIzOTNmNmU2NmM3ZmNlMWU5OTA1ZDFlZTJlYTRiZThlZDViMzEwN2VmN2Y0NDEyZjNkYmM5ZGJhNTllMGU1ZjE3In0=; _session=XAj6V877yp1DE8Cb405837ySa0t6fYHM21R2HZ8Z; _gid=GA1.2.2089711003.1622961890; _gat_UA-19089743-2=1; _gat_UA-19089743-3=1; __gads=ID=b597940057bf81ba:T=1622961888:S=ALNI_MY9F-63AstFh3E3tS-DTVh08KgjJg; dsr=eyJpdiI6IlhBWTRYdk14SysyNms5VVpoMFUzMFE9PSIsInZhbHVlIjoiZUl2S2ZSL3M5a2RwT253MlpoQnJPb1NJQjZ1RUJLOWtTWnFXeWpvOG9XUnAwSGw4MGMyVDVIZjJiN0VSSUd6Vkt0V0wreEpEb3d6M2ZDZE51UzJDTGc9PSIsIm1hYyI6IjRkZjU5MjJhMTVhZjQwOGY4MjRhYzhiMjJkMzg0YTFhNzQ1YWVkODZmYjEyMjA5ODliNDdkZGQzMzVkOTdjNGIifQ==; name=eyJpdiI6Ilp0TWxIeG1scW80VWlyTFJQUG4yZWc9PSIsInZhbHVlIjoiL1NqMnJyKzhtdW1hUnFBYjhvUVhVeW9EVWdMSjdjSklvdUsrRk5Id0lrOHdtcjVDU010QkovQjAxYkZZT2Q3TSIsIm1hYyI6IjU4ZDc4NGQzNTMyMzJlZjk0YjZmNjBiMjkzNTAyYTQ0ZDg4NGNkZjhmMDY2ODk2YjdkOTdkZTY3MDlmYzdhYjkifQ==; XSRF-TOKEN=eyJpdiI6IjJrRzRiZTVYcldiL09XSURJTDJQYVE9PSIsInZhbHVlIjoicC8yVzV0cnFQQ2RXOG0xeDdUNTc1V2RmYlJIWnNiTjJ5UVFHMGlTOUhPT3VOOWtZbFFLS0d4QUxDTjdYTEdrYWdvbUJ5Y24wOVpmZjNVdTdtUUNkNmMrVDk0U3RoT0NsZmxZVWIveTh3QU9PT25aLzd1UndpUWVvTlZ2Tjd2c3IiLCJtYWMiOiIyYjdlNjFhYTAzYTIyZTdjMDIwNTZkNjIwMDJlMTI3MTZkNzhjYzdkMzIyNjdmNzFmYzI1ZmE5NzczZTVmZWVjIn0=")
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
// 解析XPATH
|
||||
doc, err := xpath.Parse(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// 取出每个返回的结果
|
||||
list := xpath.Find(doc, `//*[@id="shindanResult"]`)
|
||||
if len(list) == 0 {
|
||||
return "", errors.New("无法查找到结果,可能 token 失效,请提交 issue")
|
||||
}
|
||||
var output = []string{}
|
||||
for child := list[0].FirstChild; child != nil; child = child.NextSibling {
|
||||
if text := xpath.InnerText(child); text != "" {
|
||||
output = append(output, text)
|
||||
} else {
|
||||
output = append(output, "\n")
|
||||
}
|
||||
}
|
||||
return strings.ReplaceAll(strings.Join(output, ""), seed, ""), nil
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user