Feature huggingface (#478)

This commit is contained in:
himawari 2022-11-05 17:32:31 +08:00 committed by GitHub
parent 8d1c18cb4a
commit deb655de36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 463 additions and 55 deletions

View File

@ -368,6 +368,10 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 设置ai绘图配置 [server] [token]
- [x] 设置ai绘图撤回时间90s
- [x] 查看ai绘图配置
例: 设置ai绘图配置 http://91.216.169.75:5010 abc
参考服务器 http://91.217.139.190:5010, http://91.216.169.75:5010, http://185.80.202.180:5010
@ -860,6 +864,14 @@ print("run[CQ:image,file="+j["img"]+"]")
来份萝莉
```
</details>
<details>
<summary>MagicPrompt-Stable-Diffusion吟唱提示</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/magicprompt"`
- [x] 吟唱提示[xxxx]
</details>
<details>
<summary>简易midi音乐制作</summary>
@ -1045,6 +1057,14 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 重置花名册
</details>
<details>
<summary>Real-CUGAN清晰术</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/realcugan"`
- [x] 清晰术(双重吟唱|三重吟唱|四重吟唱)(强力术式|中等术式|弱术式|不变式|原式)[图片]
</details>
<details>
<summary>投胎</summary>
@ -1142,6 +1162,14 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 解塔罗牌[牌名]
- [x] [塔罗|大阿卡纳|小阿卡纳|混合]牌阵[圣三角|时间之流|四要素|五牌阵|吉普赛十字|马蹄|六芒星]
</details>
<details>
<summary>舔狗日记</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/tiangou"`
- [x] 舔狗日记
</details>
<details>
<summary>搜番</summary>
@ -1150,20 +1178,6 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 搜番 | 搜索番剧[图片]
</details>
<details>
<summary>猜单词</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordle"`
- [x] 个人猜单词
- [x] 团队猜单词
- [x] 团队六阶猜单词
- [x] 团队七阶猜单词
</details>
<details>
<summary>翻译</summary>
@ -1172,6 +1186,14 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] >TL 你好
</details>
<details>
<summary>vits猫雷</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/vitsnyaru"`
- [x] 让猫雷说[xxxx]
</details>
<details>
<summary>vtb语录</summary>
@ -1252,14 +1274,6 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 更新gal
</details>
<details>
<summary>舔狗日记</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/tiangou"`
- [x] 舔狗日记
</details>
<details>
<summary>聊天热词</summary>
@ -1268,6 +1282,20 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 热词 [群号] [消息数目]|热词 123456 1000
</details>
<details>
<summary>猜单词</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordle"`
- [x] 个人猜单词
- [x] 团队猜单词
- [x] 团队六阶猜单词
- [x] 团队七阶猜单词
</details>
<details>
<summary>鬼东西</summary>

4
go.mod
View File

@ -5,13 +5,14 @@ go 1.19
require (
github.com/Baidu-AIP/golang-sdk v1.1.1
github.com/Coloured-glaze/gg v1.3.4
github.com/FloatTech/AnimeAPI v1.5.2-0.20221101144606-ec2f4e59d0ef
github.com/FloatTech/AnimeAPI v1.5.2-0.20221105044443-0c9004b2f051
github.com/FloatTech/floatbox v0.0.0-20221029160423-446812ec82d9
github.com/FloatTech/sqlite v0.5.0
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b
github.com/FloatTech/zbpctrl v1.5.2
github.com/FloatTech/zbputils v1.5.1-0.20221101032142-05b2a4825567
github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc
github.com/antchfx/htmlquery v1.2.5
github.com/corona10/goimagehash v1.1.0
github.com/fumiama/ahsai v0.1.0
@ -38,7 +39,6 @@ require (
)
require (
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc // indirect
github.com/antchfx/xpath v1.2.1 // indirect
github.com/disintegration/imaging v1.6.2 // indirect
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 // indirect

4
go.sum
View File

@ -4,8 +4,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
github.com/Coloured-glaze/gg v1.3.4 h1:l31zIF/HaVwkzjrj+A56RGQoSKyKuR1IWtIrqXGFStI=
github.com/Coloured-glaze/gg v1.3.4/go.mod h1:Ih5NLNNDHOy3RJbB0EPqGTreIzq/H02TGThIagh8HJg=
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/FloatTech/AnimeAPI v1.5.2-0.20221101144606-ec2f4e59d0ef h1:IO4ZSaTrRTidAXqUH86dHgzk8vRlw2+YX0Oz+4n/oeg=
github.com/FloatTech/AnimeAPI v1.5.2-0.20221101144606-ec2f4e59d0ef/go.mod h1:7ZXHFEgAOFvfbgIwgyFl8G/ISnUl1KvWBzngoCpQVLg=
github.com/FloatTech/AnimeAPI v1.5.2-0.20221105044443-0c9004b2f051 h1:NEW8HzBNybMXAV0NrDpMF31n/e9BFGvNiGkDPGSkouc=
github.com/FloatTech/AnimeAPI v1.5.2-0.20221105044443-0c9004b2f051/go.mod h1:Z+Q4kIPNo/OX4RWw6WGQOQcaNsbkv/wPmPDw8p4aQIY=
github.com/FloatTech/floatbox v0.0.0-20221029160423-446812ec82d9 h1:HYJ7lwaqaOKmbYooPUMWxMhXRTp+JItoyeqa320ARD4=
github.com/FloatTech/floatbox v0.0.0-20221029160423-446812ec82d9/go.mod h1:w+ND28mRaJvxUJ6pRXS6i4cLzutpXsWyroutCzBdL78=
github.com/FloatTech/sqlite v0.5.0 h1:U7J5Omc534PqmH6csfu+ypCo3DS8L91l5lTsxUu3b/U=

View File

@ -99,6 +99,7 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/jptingroom" // 日语听力学习材料
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/juejuezi" // 绝绝子生成器
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/lolicon" // lolicon 随机图片
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/magicprompt" // magicprompt吟唱提示
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/midicreate" // 简易midi音乐制作
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/moegoe" // 日韩 VITS 模型拟声
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/moyu" // 摸鱼
@ -112,6 +113,7 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nsfw" // nsfw图片识别
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/omikuji" // 浅草寺求签
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/qqwife" // 一群一天一夫一妻制群老婆
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/realcugan" // realcugan清晰术
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/reborn" // 投胎
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/runcode" // 在线运行代码
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/saucenao" // 以图搜图
@ -124,6 +126,7 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/tiangou" // 舔狗日记
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/tracemoe" // 搜番
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/translation" // 翻译
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/vitsnyaru" // vits猫雷
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/vtb_quotation" // vtb语录
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wangyiyun" // 网易云音乐热评
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wenxinAI" // 百度文心AI画图

View File

@ -56,6 +56,8 @@ func init() { // 插件主体
"- [ ai高级绘图 | 高级生成色图 | 高级生成涩图 | ai高级画图 ] [prompt]\n" +
"- [ 以图绘图 | 以图生图 | 以图画图 ] xxx [图片]|@xxx|[qq号]\n" +
"- 设置ai绘图配置 [server] [token]\n" +
"- 设置ai绘图撤回时间90s\n" +
"- 查看ai绘图配置\n" +
"例: 设置ai绘图配置 http://91.217.139.190:5010 abc\n" +
"参考服务器 http://91.217.139.190:5010, http://91.216.169.75:5010, http://185.80.202.180:5010\n" +
"通过 http://91.217.139.190:5010/token 获取token\n" +
@ -67,23 +69,23 @@ func init() { // 插件主体
datapath = file.BOTPATH + "/" + engine.DataFolder()
engine.OnPrefixGroup([]string{`ai绘图`, `生成色图`, `生成涩图`, `ai画图`}).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
server, token, err := cfg.load()
err := cfg.load()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("少女祈祷中..."))
args := ctx.State["args"].(string)
data, err := web.GetData(server + fmt.Sprintf(aipaintTxt2ImgURL, token, url.QueryEscape(strings.TrimSpace(strings.ReplaceAll(args, " ", "%20")))))
data, err := web.GetData(cfg.BaseURL + fmt.Sprintf(aipaintTxt2ImgURL, cfg.Token, url.QueryEscape(strings.TrimSpace(strings.ReplaceAll(args, " ", "%20")))))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
sendAiImg(ctx, data)
sendAiImg(ctx, data, cfg.Interval)
})
engine.OnRegex(`^(以图绘图|以图生图|以图画图)[\s\S]*?(\[CQ:(image\,file=([0-9a-zA-Z]{32}).*|at.+?(\d{5,11}))\].*|(\d+))$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
server, token, err := cfg.load()
err := cfg.load()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
@ -101,7 +103,7 @@ func init() { // 插件主体
return
}
ctx.SendChain(message.Text("少女祈祷中..."))
postURL := server + fmt.Sprintf(aipaintImg2ImgURL, token, url.QueryEscape(strings.TrimSpace(strings.ReplaceAll(args, " ", "%20"))))
postURL := cfg.BaseURL + fmt.Sprintf(aipaintImg2ImgURL, cfg.Token, url.QueryEscape(strings.TrimSpace(strings.ReplaceAll(args, " ", "%20"))))
f, err := os.Open(c.headimgsdir[0])
if err != nil {
@ -136,11 +138,11 @@ func init() { // 插件主体
ctx.SendChain(message.Text("ERROR: ", err))
return
}
sendAiImg(ctx, data)
sendAiImg(ctx, data, cfg.Interval)
})
engine.OnPrefixGroup([]string{`ai高级绘图`, `高级生成色图`, `高级生成涩图`, `ai高级画图`}).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
server, token, err := cfg.load()
err := cfg.load()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
@ -156,13 +158,13 @@ func init() { // 插件主体
if len(value) > 1 {
if value[0] == "R18" && value[1] == "1" {
value[1] = "0"
ctx.SendChain(message.Text("不准涩涩!已将R18设置为0。"))
ctx.SendChain(message.Text("不准涩涩! 已将R18设置为0. "))
}
tags[value[0]] = strings.Join(value[1:], ":")
}
}
ctx.SendChain(message.Text("少女祈祷中..."))
apiurl := "/got_image?token=" + token
apiurl := "/got_image?token=" + cfg.Token
if _, ok := tags["tags"]; ok {
apiurl += "&tags=" + url.QueryEscape(strings.ReplaceAll(strings.TrimSpace(tags["tags"]), " ", "%20"))
}
@ -181,26 +183,63 @@ func init() { // 插件主体
if _, ok := tags["seed"]; ok {
apiurl += "&seed=" + url.QueryEscape(strings.TrimSpace(tags["seed"]))
}
data, err := web.GetData(server + apiurl)
data, err := web.GetData(cfg.BaseURL + apiurl)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
sendAiImg(ctx, data)
sendAiImg(ctx, data, cfg.Interval)
})
engine.OnRegex(`^设置ai绘图配置\s(.*[^\s$])\s(.+)$`, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
regexMatched := ctx.State["regex_matched"].([]string)
err := cfg.save(regexMatched[1], regexMatched[2])
err := cfg.load()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("成功设置server为", regexMatched[1], ", token为", regexMatched[2]))
err = cfg.update(regexMatched[1], regexMatched[2], cfg.Interval)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
text := fmt.Sprintf("成功设置\nbase_url: %v\ntoken: %v\ninterval: %v\n", cfg.BaseURL, cfg.Token, cfg.Interval)
ctx.SendChain(message.Text(text))
})
engine.OnRegex(`^设置ai绘图撤回时间(\d{1,3})s$`, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
regexMatched := ctx.State["regex_matched"].([]string)
interval, err := strconv.Atoi(regexMatched[1])
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
err = cfg.load()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
err = cfg.update(cfg.BaseURL, cfg.Token, interval)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
text := fmt.Sprintf("成功设置\nbase_url: %v\ntoken: %v\ninterval: %v\n", cfg.BaseURL, cfg.Token, cfg.Interval)
ctx.SendChain(message.Text(text))
})
engine.OnFullMatch(`查看ai绘图配置`, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
err := cfg.load()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
text := fmt.Sprintf("base_url: %v\ntoken: %v\ninterval: %v\n", cfg.BaseURL, cfg.Token, cfg.Interval)
ctx.SendChain(message.Text(text))
})
}
func sendAiImg(ctx *zero.Ctx, data []byte) {
func sendAiImg(ctx *zero.Ctx, data []byte, interval int) {
var loadData string
if predictRe.MatchString(binary.BytesToString(data)) {
loadData = predictRe.FindStringSubmatch(binary.BytesToString(data))[0]
@ -223,11 +262,10 @@ func sendAiImg(ctx *zero.Ctx, data []byte) {
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text(r.String())))
if mid := ctx.Send(m); mid.ID() == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
} else {
} else if interval > 0 {
go func(i message.MessageID) {
time.Sleep(90 * time.Second)
time.Sleep(time.Duration(interval) * time.Second)
ctx.DeleteMessage(i)
}(mid)
}
}

View File

@ -10,9 +10,10 @@ import (
// 配置结构体
type serverConfig struct {
BaseURL string `json:"base_url"`
Token string `json:"token"`
file string
BaseURL string `json:"base_url"`
Token string `json:"token"`
Interval int `json:"interval"`
file string
}
func newServerConfig(file string) *serverConfig {
@ -21,9 +22,14 @@ func newServerConfig(file string) *serverConfig {
}
}
func (cfg *serverConfig) save(baseURL, token string) (err error) {
cfg.BaseURL = baseURL
cfg.Token = token
func (cfg *serverConfig) update(baseURL, token string, interval int) (err error) {
if baseURL != "" {
cfg.BaseURL = baseURL
}
if token != "" {
cfg.Token = token
}
cfg.Interval = interval
reader, err := os.Create(cfg.file)
if err != nil {
return err
@ -32,10 +38,8 @@ func (cfg *serverConfig) save(baseURL, token string) (err error) {
return json.NewEncoder(reader).Encode(cfg)
}
func (cfg *serverConfig) load() (aipaintServer, token string, err error) {
if cfg.BaseURL != "" && cfg.Token != "" {
aipaintServer = cfg.BaseURL
token = cfg.Token
func (cfg *serverConfig) load() (err error) {
if cfg.BaseURL != "" && cfg.Token != "" && cfg.Interval != 0 {
return
}
if file.IsNotExist(cfg.file) {
@ -48,7 +52,5 @@ func (cfg *serverConfig) load() (aipaintServer, token string, err error) {
}
defer reader.Close()
err = json.NewDecoder(reader).Decode(cfg)
aipaintServer = cfg.BaseURL
token = cfg.Token
return
}

View File

@ -0,0 +1,91 @@
// Package magicprompt MagicPrompt-Stable-Diffusion吟唱提示
package magicprompt
import (
"context"
"encoding/json"
"fmt"
"strings"
"time"
hf "github.com/FloatTech/AnimeAPI/huggingface"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/RomiChan/websocket"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
const (
magicpromptRepo = "Gustavosta/MagicPrompt-Stable-Diffusion"
)
func init() { // 插件主体
engine := control.Register("magicprompt", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "MagicPrompt-Stable-Diffusion吟唱提示",
Help: "- 吟唱提示 xxx",
PrivateDataFolder: "magicprompt",
})
// 开启
engine.OnPrefixGroup([]string{`吟唱提示`, "吟唱补全"}).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
_ctx, _cancel := context.WithTimeout(context.Background(), hf.TimeoutMax*time.Second)
defer _cancel()
ctx.SendChain(message.Text("少女祈祷中..."))
magicpromptURL := fmt.Sprintf(hf.WssJoinPath, magicpromptRepo)
args := ctx.State["args"].(string)
c, _, err := websocket.DefaultDialer.Dial(magicpromptURL, nil)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
defer c.Close()
r := hf.PushRequest{
FnIndex: 0,
Data: []interface{}{args},
}
b, err := json.Marshal(r)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
err = c.WriteMessage(websocket.TextMessage, b)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
t := time.NewTicker(time.Second * 1)
defer t.Stop()
for {
select {
case <-t.C:
_, data, err := c.ReadMessage()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
j := gjson.ParseBytes(data)
if j.Get("msg").String() == hf.WssCompleteStatus {
m := message.Message{}
for _, v := range strings.Split(j.Get("output.data.0").String(), "\n\n") {
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text(v)))
}
if id := ctx.Send(m).ID(); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
}
return
}
case <-_ctx.Done():
ctx.SendChain(message.Text("ERROR: 吟唱提示指令超时"))
return
}
}
})
}

View File

@ -0,0 +1,105 @@
// Package realcugan Real-CUGAN清晰术
package realcugan
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"image"
"strings"
hf "github.com/FloatTech/AnimeAPI/huggingface"
"github.com/FloatTech/floatbox/web"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
const (
realcuganRepo = "shichen1231/Real-CUGAN"
)
func init() { // 插件主体
engine := control.Register("realcugan", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "Real-CUGAN清晰术",
Help: "- 清晰术(双重吟唱|三重吟唱|四重吟唱)(强力术式|中等术式|弱术式|不变式|原式)[图片]",
PrivateDataFolder: "realcugan",
})
engine.OnPrefix("清晰术", zero.MustProvidePicture).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text("少女祈祷中..."))
realcuganURL := fmt.Sprintf(hf.HTTPSPredictPath, realcuganRepo)
for _, url := range ctx.State["image_url"].([]string) {
imgdata, err := web.GetData(url)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
img, _, err := image.Decode(bytes.NewReader(imgdata))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
// 初始化参数
var (
fashu = ctx.Event.Message.ExtractPlainText()
scale = 2
con = "conservative"
)
switch {
case strings.Contains(fashu, "双重吟唱"):
scale = 2
case strings.Contains(fashu, "三重吟唱") && img.Bounds().Dx()*img.Bounds().Dy() < 400000:
scale = 3
case strings.Contains(fashu, "四重吟唱") && img.Bounds().Dx()*img.Bounds().Dy() < 400000:
scale = 4
}
switch {
case strings.Contains(fashu, "强力术式"):
con = "denoise3x"
case strings.Contains(fashu, "中等术式"):
con = "no-denoise"
if scale == 2 {
con = "denoise2x"
}
case strings.Contains(fashu, "弱术式"):
con = "no-denoise"
if scale == 2 {
con = "denoise1x"
}
case strings.Contains(fashu, "不变式"):
con = "no-denoise"
case strings.Contains(fashu, "原式"):
con = "conservative"
}
modelname := fmt.Sprintf("up%vx-latest-%v.pth", scale, con)
encodeStr := base64.StdEncoding.EncodeToString(imgdata)
encodeStr = "data:image/jpeg;base64," + encodeStr
pr := hf.PushRequest{
Data: []interface{}{encodeStr, modelname, 2},
}
buf := bytes.NewBuffer([]byte{})
err = json.NewEncoder(buf).Encode(pr)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
data, err := web.PostData(realcuganURL, "application/json", buf)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
imgStr := gjson.ParseBytes(data).Get("data.0").String()
m := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Text(scale, "重唱", con, "分支大清晰术!")),
ctxext.FakeSenderForwardNode(ctx, message.Image("base64://"+strings.TrimPrefix(imgStr, "data:image/png;base64,")))}
if id := ctx.Send(m).ID(); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
}
}
})
}

View File

@ -0,0 +1,141 @@
// Package vitsnyaru vits猫雷
package vitsnyaru
import (
"context"
"encoding/json"
"fmt"
"strings"
"time"
hf "github.com/FloatTech/AnimeAPI/huggingface"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
const (
vitsnyaruRepo = "innnky/vits-nyaru"
)
func init() { // 插件主体
engine := control.Register("vitsnyaru", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "vits猫雷",
Help: "- 让猫雷说 xxx",
PrivateDataFolder: "vitsnyaru",
})
// 开启
engine.OnPrefix(`让猫雷说`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
_ctx, _cancel := context.WithTimeout(context.Background(), hf.TimeoutMax*time.Second)
defer _cancel()
ch := make(chan []byte, 1)
args := ctx.State["args"].(string)
pushURL := fmt.Sprintf(hf.HTTPSPushPath, vitsnyaruRepo)
statusURL := fmt.Sprintf(hf.HTTPSStatusPath, vitsnyaruRepo)
ctx.SendChain(message.Text("少女祈祷中..."))
var (
pushReq hf.PushRequest
pushRes hf.PushResponse
statusReq hf.StatusRequest
statusRes hf.StatusResponse
data []byte
)
// 获取clean后的文本
pushReq = hf.PushRequest{
Action: hf.DefaultAction,
Data: []interface{}{args},
FnIndex: 1,
}
pushRes, err := hf.Push(pushURL, pushReq)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
statusReq = hf.StatusRequest{
Hash: pushRes.Hash,
}
t := time.NewTicker(time.Second * 1)
defer t.Stop()
LOOP:
for {
select {
case <-t.C:
data, err = hf.Status(statusURL, statusReq)
if err != nil {
ch <- data
break LOOP
}
if gjson.ParseBytes(data).Get("status").String() == hf.CompleteStatus {
ch <- data
break LOOP
}
case <-_ctx.Done():
ch <- data
break LOOP
}
}
data = <-ch
err = json.Unmarshal(data, &statusRes)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
// 用clean的文本预测语音
pushReq = hf.PushRequest{
Action: hf.DefaultAction,
Data: statusRes.Data.Data,
FnIndex: 2,
}
pushRes, err = hf.Push(pushURL, pushReq)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
statusReq = hf.StatusRequest{
Hash: pushRes.Hash,
}
LOOP2:
for {
select {
case <-t.C:
data, err = hf.Status(statusURL, statusReq)
if err != nil {
ch <- data
break LOOP2
}
if gjson.ParseBytes(data).Get("status").String() == hf.CompleteStatus {
ch <- data
break LOOP2
}
case <-_ctx.Done():
ch <- data
break LOOP2
}
}
data = <-ch
err = json.Unmarshal(data, &statusRes)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
// 发送语音
if len(statusRes.Data.Data) < 2 {
ctx.SendChain(message.Text("ERROR: 未能获取语音"))
return
}
ctx.SendChain(message.Record("base64://" + strings.TrimPrefix(statusRes.Data.Data[1].(string), "data:audio/wav;base64,")))
})
}