mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2025-12-19 13:59:39 +08:00
Some checks failed
自动更新 nix 依赖 / gomod2nix update (push) Has been cancelled
打包最新版为 Docker Image / build docker (push) Has been cancelled
最新版 / Build binary CI (386, linux) (push) Has been cancelled
最新版 / Build binary CI (386, windows) (push) Has been cancelled
最新版 / Build binary CI (amd64, linux) (push) Has been cancelled
最新版 / Build binary CI (amd64, windows) (push) Has been cancelled
最新版 / Build binary CI (arm, linux) (push) Has been cancelled
最新版 / Build binary CI (arm64, linux) (push) Has been cancelled
PushLint / lint (push) Has been cancelled
172 lines
4.9 KiB
Go
172 lines
4.9 KiB
Go
// Package aiimage AI画图
|
|
package aiimage
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
fcext "github.com/FloatTech/floatbox/ctxext"
|
|
"github.com/FloatTech/floatbox/web"
|
|
sql "github.com/FloatTech/sqlite"
|
|
"github.com/tidwall/gjson"
|
|
zero "github.com/wdvxdr1123/ZeroBot"
|
|
"github.com/wdvxdr1123/ZeroBot/message"
|
|
|
|
ctrl "github.com/FloatTech/zbpctrl"
|
|
"github.com/FloatTech/zbputils/control"
|
|
"github.com/FloatTech/zbputils/ctxext"
|
|
)
|
|
|
|
func init() {
|
|
var sdb = &storage{}
|
|
|
|
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
|
DisableOnDefault: false,
|
|
Extra: control.ExtraFromString("aiimage"),
|
|
Brief: "AI画图",
|
|
Help: "- 设置AI画图密钥xxx\n" +
|
|
"- 设置AI画图接口地址https://api.siliconflow.cn/v1/images/generations\n" +
|
|
"- 设置AI画图模型名Kwai-Kolors/Kolors\n" +
|
|
"- 查看AI画图配置\n" +
|
|
"- AI画图 [描述]",
|
|
PrivateDataFolder: "aiimage",
|
|
})
|
|
|
|
getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
|
sdb.db = sql.New(en.DataFolder() + "aiimage.db")
|
|
err := sdb.db.Open(time.Hour)
|
|
if err == nil {
|
|
// 创建配置表
|
|
err = sdb.db.Create("config", &imageConfig{})
|
|
if err != nil {
|
|
ctx.SendChain(message.Text("[ERROR]:", err))
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
ctx.SendChain(message.Text("[ERROR]:", err))
|
|
return false
|
|
})
|
|
|
|
en.OnPrefix("设置AI画图密钥", getdb, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
|
Handle(func(ctx *zero.Ctx) {
|
|
apiKey := strings.TrimSpace(ctx.State["args"].(string))
|
|
cfg := sdb.getConfig()
|
|
err := sdb.setConfig(apiKey, cfg.APIURL, cfg.ModelName)
|
|
if err != nil {
|
|
ctx.SendChain(message.Text("ERROR: 设置API密钥失败: ", err))
|
|
return
|
|
}
|
|
ctx.SendChain(message.Text("成功设置API密钥"))
|
|
})
|
|
|
|
en.OnPrefix("设置AI画图接口地址", getdb, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
|
Handle(func(ctx *zero.Ctx) {
|
|
apiURL := strings.TrimSpace(ctx.State["args"].(string))
|
|
cfg := sdb.getConfig()
|
|
err := sdb.setConfig(cfg.APIKey, apiURL, cfg.ModelName)
|
|
if err != nil {
|
|
ctx.SendChain(message.Text("ERROR: 设置API地址失败: ", err))
|
|
return
|
|
}
|
|
ctx.SendChain(message.Text("成功设置API地址"))
|
|
})
|
|
|
|
en.OnPrefix("设置AI画图模型名", getdb, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
|
Handle(func(ctx *zero.Ctx) {
|
|
modelName := strings.TrimSpace(ctx.State["args"].(string))
|
|
cfg := sdb.getConfig()
|
|
err := sdb.setConfig(cfg.APIKey, cfg.APIURL, modelName)
|
|
if err != nil {
|
|
ctx.SendChain(message.Text("ERROR: 设置模型失败: ", err))
|
|
return
|
|
}
|
|
ctx.SendChain(message.Text("成功设置模型: ", modelName))
|
|
})
|
|
|
|
en.OnFullMatch("查看AI画图配置", getdb, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
|
|
Handle(func(ctx *zero.Ctx) {
|
|
ctx.SendChain(message.Text(sdb.PrintConfig()))
|
|
})
|
|
|
|
en.OnPrefix("AI画图", getdb).SetBlock(true).
|
|
Handle(func(ctx *zero.Ctx) {
|
|
ctx.SendChain(message.Text("少女思考中..."))
|
|
prompt := strings.TrimSpace(ctx.State["args"].(string))
|
|
if prompt == "" {
|
|
ctx.SendChain(message.Text("请输入图片描述"))
|
|
return
|
|
}
|
|
|
|
cfg := sdb.getConfig()
|
|
if cfg.APIKey == "" || cfg.APIURL == "" || cfg.ModelName == "" {
|
|
ctx.SendChain(message.Text("请先配置API密钥、地址和模型"))
|
|
return
|
|
}
|
|
|
|
// 准备请求数据
|
|
reqBytes, _ := json.Marshal(map[string]interface{}{
|
|
"model": cfg.ModelName,
|
|
"prompt": prompt,
|
|
"image_size": "1024x1024",
|
|
"batch_size": 4,
|
|
"num_inference_steps": 20,
|
|
"guidance_scale": 7.5,
|
|
})
|
|
|
|
// 发送API请求
|
|
data, err := web.RequestDataWithHeaders(
|
|
web.NewDefaultClient(),
|
|
cfg.APIURL,
|
|
"POST",
|
|
func(req *http.Request) error {
|
|
req.Header.Set("Authorization", "Bearer "+cfg.APIKey)
|
|
req.Header.Set("Content-Type", "application/json")
|
|
return nil
|
|
},
|
|
bytes.NewReader(reqBytes),
|
|
)
|
|
if err != nil {
|
|
ctx.SendChain(message.Text("API请求失败: ", err))
|
|
return
|
|
}
|
|
|
|
// 解析API响应
|
|
jsonData := gjson.ParseBytes(data)
|
|
images := jsonData.Get("images")
|
|
if !images.Exists() {
|
|
images = jsonData.Get("data")
|
|
if !images.Exists() {
|
|
ctx.SendChain(message.Text("未获取到图片URL"))
|
|
return
|
|
}
|
|
}
|
|
|
|
// 发送生成的图片和相关信息
|
|
inferenceTime := jsonData.Get("timings.inference").Float()
|
|
seed := jsonData.Get("seed").Int()
|
|
msg := make(message.Message, 0, 1)
|
|
msg = append(msg, ctxext.FakeSenderForwardNode(ctx, message.Text("图片生成成功!\n",
|
|
"提示词: ", prompt, "\n",
|
|
"模型: ", cfg.ModelName, "\n",
|
|
"推理时间: ", inferenceTime, "秒\n",
|
|
"种子: ", seed)))
|
|
|
|
// 添加所有图片
|
|
images.ForEach(func(_, value gjson.Result) bool {
|
|
url := value.Get("url").String()
|
|
if url != "" {
|
|
msg = append(msg, ctxext.FakeSenderForwardNode(ctx, message.Image(url)))
|
|
}
|
|
return true
|
|
})
|
|
|
|
if len(msg) > 0 {
|
|
ctx.Send(msg)
|
|
}
|
|
})
|
|
}
|