ZeroBot-Plugin/plugin/setutime/setu_geter.go
莫思潋 0698d8e3b1
fix:修复了枝网查重无法使用的问题 (#175)
* 优化在两个命令中使用空格分隔的体验
- fortune的设置底图功能
- b14的加密功能

* 优化四个插件中使用空格分隔的体验
- 加密
- 哔哩哔哩推送
- 藏头诗
- 运势

* 优化并修正了上一个commit
- 加上了因为复制粘贴疏忽又没有注意测试遗漏的`?`
- 调整藏头诗和加密的正则触发,使其不必多此一举
- 删去了未被发现的测试代码

* - 删去了遗漏的Trim

* 优化了更多插件中使用空格的体验
- 优化了music bilibili image_finder 中使用空格的体验
- 补上了plugin_bilibili中未实现的vup开头触发
- 为plugin_bilibili_parse输出的消息加上一个换行符,优化排版

* 小调整

- 考虑到屌字既难打又有碍观瞻,改为正则匹配`[屌|弔|吊]图`
- 增加了退群提醒的定制

* - 修复退群提醒本身忘记修改了的问题

* fix:修复了枝网查重无法使用的问题

* readme适配上次的欢迎语修改

* 删去调试语句

* Update setu_geter.go

* Update zhiwang.go

Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2022-03-31 19:36:29 +08:00

239 lines
6.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package setutime 来份涩图
package setutime
import (
"fmt"
"strconv"
"strings"
"sync"
"time"
"github.com/FloatTech/AnimeAPI/pixiv"
sql "github.com/FloatTech/sqlite"
control "github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
fileutil "github.com/FloatTech/zbputils/file"
imagepool "github.com/FloatTech/zbputils/img/pool"
"github.com/FloatTech/zbputils/math"
"github.com/FloatTech/zbputils/process"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/zbputils/control/order"
)
// Pools 图片缓冲池
type imgpool struct {
db *sql.Sqlite
dbmu sync.RWMutex
path string
max int
pool map[string][]*message.MessageSegment
poolmu sync.Mutex
}
func (p *imgpool) List() (l []string) {
var err error
p.dbmu.RLock()
defer p.dbmu.RUnlock()
l, err = p.db.ListTables()
if err != nil {
l = []string{"涩图", "二次元", "风景", "车万"}
}
return l
}
var pool = &imgpool{
db: &sql.Sqlite{},
path: pixiv.CacheDir,
max: 10,
pool: make(map[string][]*message.MessageSegment),
}
func init() { // 插件主体
engine := control.Register("setutime", order.AcquirePrio(), &control.Options{
DisableOnDefault: false,
Help: "涩图\n" +
"- 来份[涩图/二次元/风景/车万]\n" +
"- 添加[涩图/二次元/风景/车万][P站图片ID]\n" +
"- 删除[涩图/二次元/风景/车万][P站图片ID]\n" +
"- >setu status",
PublicDataFolder: "SetuTime",
})
go func() {
// 如果数据库不存在则下载
pool.db.DBPath = engine.DataFolder() + "SetuTime.db"
_, _ = fileutil.GetLazyData(pool.db.DBPath, false, false)
err := pool.db.Open()
if err != nil {
panic(err)
}
for _, imgtype := range pool.List() {
if err := pool.db.Create(imgtype, &pixiv.Illust{}); err != nil {
panic(err)
}
}
}()
engine.OnRegex(`^来份(.+)$`, ctxext.FirstValueInList(pool)).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
var imgtype = ctx.State["regex_matched"].([]string)[1]
// 补充池子
go pool.fill(ctx, imgtype)
// 如果没有缓存阻塞10秒
if pool.size(imgtype) == 0 {
ctx.SendChain(message.Text("INFO: 正在填充弹药......"))
time.Sleep(time.Second * 10)
if pool.size(imgtype) == 0 {
ctx.SendChain(message.Text("ERROR:等待填充,请稍后再试......"))
return
}
}
// 从缓冲池里抽一张
if id := ctx.SendChain(*pool.pop(imgtype)); id.ID() == 0 {
ctx.SendChain(message.Text("ERROR:可能被风控了"))
}
})
engine.OnRegex(`^添加(.+)\s?(\d+)$`, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
var (
imgtype = ctx.State["regex_matched"].([]string)[1]
id, _ = strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
)
err := pool.add(ctx, imgtype, id)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text("成功向分类", imgtype, "添加图片", id))
})
engine.OnRegex(`^删除(.+)\s?(\d+)$`, ctxext.FirstValueInList(pool), zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
var (
imgtype = ctx.State["regex_matched"].([]string)[1]
id, _ = strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
)
// 查询数据库
if err := pool.remove(imgtype, id); err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text("删除成功"))
})
// 查询数据库涩图数量
engine.OnFullMatchGroup([]string{">setu status"}).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
state := []string{"[SetuTime]"}
pool.dbmu.RLock()
defer pool.dbmu.RUnlock()
for _, imgtype := range pool.List() {
num, err := pool.db.Count(imgtype)
if err != nil {
num = 0
}
state = append(state, "\n")
state = append(state, imgtype)
state = append(state, ": ")
state = append(state, fmt.Sprintf("%d", num))
}
ctx.SendChain(message.Text(state))
})
}
// size 返回缓冲池指定类型的现有大小
func (p *imgpool) size(imgtype string) int {
return len(p.pool[imgtype])
}
func (p *imgpool) push(ctx *zero.Ctx, imgtype string, illust *pixiv.Illust) {
u := illust.ImageUrls[0]
n := u[strings.LastIndex(u, "/")+1 : len(u)-4]
m, err := imagepool.GetImage(n)
var msg message.MessageSegment
f := fileutil.BOTPATH + "/" + illust.Path(0)
if err != nil {
if fileutil.IsNotExist(f) {
// 下载图片
if err := illust.DownloadToCache(0); err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
}
m.SetFile(f)
_, _ = m.Push(ctxext.SendToSelf(ctx), ctxext.GetMessage(ctx))
msg = message.Image("file:///" + f)
} else {
msg = message.Image(m.String())
if ctxext.SendToSelf(ctx)(msg) == 0 {
msg = msg.Add("cache", "0")
}
}
p.poolmu.Lock()
p.pool[imgtype] = append(p.pool[imgtype], &msg)
p.poolmu.Unlock()
}
func (p *imgpool) pop(imgtype string) (msg *message.MessageSegment) {
p.poolmu.Lock()
defer p.poolmu.Unlock()
if p.size(imgtype) == 0 {
return
}
msg = p.pool[imgtype][0]
p.pool[imgtype] = p.pool[imgtype][1:]
return
}
// fill 补充池子
func (p *imgpool) fill(ctx *zero.Ctx, imgtype string) {
times := math.Min(p.max-p.size(imgtype), 2)
p.dbmu.RLock()
defer p.dbmu.RUnlock()
for i := 0; i < times; i++ {
illust := &pixiv.Illust{}
// 查询出一张图片
if err := p.db.Pick(imgtype, illust); err != nil {
ctx.SendChain(message.Text("ERROR:", err))
continue
}
// 向缓冲池添加一张图片
p.push(ctx, imgtype, illust)
process.SleepAbout1sTo2s()
}
}
func (p *imgpool) add(ctx *zero.Ctx, imgtype string, id int64) error {
p.dbmu.Lock()
defer p.dbmu.Unlock()
if err := p.db.Create(imgtype, &pixiv.Illust{}); err != nil {
return err
}
ctx.SendChain(message.Text("少女祈祷中......"))
// 查询P站插图信息
illust, err := pixiv.Works(id)
if err != nil {
return err
}
err = imagepool.SendImageFromPool(strconv.FormatInt(illust.Pid, 10)+"_p0", illust.Path(0), func() error {
return illust.DownloadToCache(0)
}, ctxext.Send(ctx), ctxext.GetMessage(ctx))
if err != nil {
return err
}
// 添加插画到对应的数据库table
if err := p.db.Insert(imgtype, illust); err != nil {
return err
}
return nil
}
func (p *imgpool) remove(imgtype string, id int64) error {
p.dbmu.Lock()
defer p.dbmu.Unlock()
return p.db.Del(imgtype, fmt.Sprintf("WHERE pid=%d", id))
}