Skip to content

Commit b1df852

Browse files
ltou14fumiama
andauthored
修复赛博猫猫无法出图的问题,增加了后备选项 (#252)
* Change module path from FloatTech to ltou14 修改赛博猫猫 * 修改赛博猫猫 * 修复赛博猫猫 * 修复赛博猫猫不能显示图片的bug * Change module path from ltou14 to FloatTech把module修改回来 * 标注连续使用了三个空白标识符(_)忽略 suineko() 函数的多个返回值 * 将suineko参数修改为结构体 --------- Co-authored-by: fumiama <41315874+fumiama@users.noreply.github.com>
1 parent b755e23 commit b1df852

File tree

1 file changed

+142
-77
lines changed

1 file changed

+142
-77
lines changed

plugin/cybercat/catdata.go

Lines changed: 142 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
// Package cybercat 云养猫
22
package cybercat
3-
3+
import "errors"
44
import (
55
"fmt"
66
"os"
77
"path"
88
"path/filepath"
99
"sync"
1010
"time"
11+
"strconv"
1112

1213
fcext "github.com/FloatTech/floatbox/ctxext"
1314
"github.com/FloatTech/floatbox/file"
@@ -50,6 +51,14 @@ type catdb struct {
5051
sql.Sqlite
5152
}
5253

54+
type breedInfo struct {
55+
TypeName string
56+
Temperament string
57+
Description string
58+
ImageURL string
59+
Err error
60+
}
61+
5362
type catInfo struct {
5463
User int64 // 主人
5564
Name string // 喵喵名称
@@ -65,44 +74,85 @@ type catInfo struct {
6574
}
6675

6776
func (inf *catInfo) avatar(gid int64) string {
68-
cache := path.Join(engine.DataFolder(), "cache")
69-
imgname := fmt.Sprintf("%d_%d", inf.User, gid)
70-
imgfile := filepath.Join(cache, inf.Type+imgname+".png")
71-
aimgfile := filepath.Join(file.BOTPATH, imgfile)
77+
// 构建缓存文件路径
78+
cache := path.Join(engine.DataFolder(), "cache")
79+
imgname := fmt.Sprintf("%d_%d", inf.User, gid)
80+
imgfile := filepath.Join(cache, inf.Type+imgname+".png")
81+
aimgfile := filepath.Join(file.BOTPATH, imgfile)
7282

73-
if _, err := os.Stat(cache); os.IsNotExist(err) {
74-
err := os.MkdirAll(cache, 0755)
75-
if err != nil {
76-
fmt.Println("Error creating cache directory:", err)
77-
return err.Error()
78-
}
79-
}
80-
if file.IsNotExist(aimgfile) {
81-
breed := inf.Type
82-
data, err := web.GetData(apiURL + "search?has_breeds=" + breed)
83-
if err != nil {
84-
fmt.Println("Error fetching avatar URL:", err)
85-
return err.Error() // 返回错误信息
86-
}
87-
imgurl := gjson.ParseBytes(data).Get("0.url").String()
88-
imgdata, err := web.GetData(imgurl)
89-
if err != nil {
90-
return "错误:未能解析图片URL"
91-
}
92-
var f *os.File
93-
f, err = os.Create(aimgfile) // 使用 aimgfile 作为文件路径
94-
if err != nil {
95-
fmt.Println("Error creating file:", err)
96-
return err.Error() // 返回错误信息
97-
}
98-
defer f.Close()
99-
_, err = f.Write(imgdata) // 写入图片数据
100-
if err != nil {
101-
fmt.Println("Error writing file:", err)
102-
return err.Error() // 返回错误信息
83+
// 确保缓存目录存在
84+
_ = os.MkdirAll(cache, 0755)
85+
86+
// 1. 如果本地已有缓存文件,直接返回
87+
if file.IsExist(aimgfile) {
88+
return "file:///" + aimgfile
89+
}
90+
91+
// 2. 优先使用已有的 Picurl(例如用户上传的猫娘图片)
92+
if inf.Picurl != "" {
93+
if err := downloadAndSave(inf.Picurl, aimgfile); err == nil {
94+
return "file:///" + aimgfile
95+
}
96+
// 下载失败,继续尝试通过品种获取
97+
}
98+
99+
// 3. 通过品种ID获取图片
100+
breedID, ok := typeZH2Breeds[inf.Type]
101+
if ok {
102+
// 构建请求URL(使用 breed_ids 参数)
103+
url := apiURL + "search?breed_ids=" + breedID + "&limit=1"
104+
// 添加 API 密钥
105+
if apiKey := getCatAPIKey(); apiKey != "" {
106+
url += "&api_key=" + apiKey
107+
}
108+
109+
data, err := web.GetData(url)
110+
if err == nil {
111+
imgURL := gjson.ParseBytes(data).Get("0.url").String()
112+
if imgURL != "" {
113+
if err := downloadAndSave(imgURL, aimgfile); err == nil {
114+
// 保存 URL 到数据库供下次使用
115+
inf.Picurl = imgURL
116+
go func() {
117+
gidStr := "group" + strconv.FormatInt(gid, 10)
118+
_ = catdata.insert(gidStr, inf) // 异步更新,忽略错误
119+
}()
120+
return "file:///" + aimgfile
121+
}
122+
}
123+
}
124+
}
125+
126+
// 4. 后备方案:随机猫图
127+
result := suineko()
128+
if result.Err == nil && result.ImageURL != "" {
129+
if err := downloadAndSave(result.ImageURL, aimgfile); err == nil {
130+
return "file:///" + aimgfile
103131
}
104132
}
105-
return "file:///" + aimgfile // 返回文件协议的完整路径
133+
134+
// 5. 最终后备:透明PNG(避免报错)
135+
return "base64://iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="
136+
}
137+
138+
// downloadAndSave 下载图片并保存到本地
139+
func downloadAndSave(url, filepath string) error {
140+
data, err := web.GetData(url)
141+
if err != nil {
142+
return err
143+
}
144+
f, err := os.Create(filepath)
145+
if err != nil {
146+
return err
147+
}
148+
defer f.Close()
149+
_, err = f.Write(data)
150+
return err
151+
}
152+
153+
// getCatAPIKey API密钥
154+
func getCatAPIKey() string {
155+
return "live_jjmlzq8FSiuFko40Utf43EfniNWYY1MtBaCej1Fy2YRDW9nMEmtgJwOMiZzs6fXc" // 替换为真实免费密钥
106156
}
107157

108158
var (
@@ -135,52 +185,67 @@ var (
135185
)
136186

137187
func init() {
138-
engine.OnRegex(`^吸(.*猫)$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
139-
typeOfcat := ctx.State["regex_matched"].([]string)[1]
140-
if typeOfcat == "猫" {
141-
typeName, temperament, description, url, err := suineko()
142-
if err != nil {
143-
ctx.SendChain(message.Text("[ERROR]: ", err))
144-
return
145-
}
146-
ctx.SendChain(message.Image(url), message.Text("品种: ", typeName,
147-
"\n气质:\n", temperament, "\n描述:\n", description))
148-
return
149-
}
150-
breeds, ok := typeZH2Breeds[typeOfcat]
151-
if !ok {
152-
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("没有相关该品种的猫图"))
153-
return
154-
}
155-
picurl, err := getPicByBreed(breeds)
156-
if err != nil {
157-
ctx.SendChain(message.Text("[ERROR]: ", err))
158-
return
159-
}
160-
ctx.SendChain(message.Text("品种: ", typeOfcat), message.Image(picurl))
161-
})
188+
engine.OnRegex(`^吸(.*猫)$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
189+
typeOfcat := ctx.State["regex_matched"].([]string)[1]
190+
if typeOfcat == "猫" {
191+
result := suineko()
192+
if result.Err != nil {
193+
ctx.SendChain(message.Text("[ERROR]: ", result.Err))
194+
return
195+
}
196+
ctx.SendChain(
197+
message.Image(result.ImageURL),
198+
message.Text("品种: ", result.TypeName,
199+
"\n气质:\n", result.Temperament,
200+
"\n描述:\n", result.Description),
201+
)
202+
return
203+
}
204+
breeds, ok := typeZH2Breeds[typeOfcat]
205+
if !ok {
206+
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("没有相关该品种的猫图"))
207+
return
208+
}
209+
picurl, err := getPicByBreed(breeds)
210+
if err != nil {
211+
ctx.SendChain(message.Text("[ERROR]: ", err))
212+
return
213+
}
214+
ctx.SendChain(message.Text("品种: ", typeOfcat), message.Image(picurl))
215+
})
162216
}
163217

164-
func suineko() (typeName, temperament, description, url string, err error) {
165-
data, err := web.GetData(apiURL + "search?has_breeds=1")
166-
if err != nil {
167-
return
168-
}
169-
picID := gjson.ParseBytes(data).Get("0.id").String()
170-
picdata, err := web.GetData(apiURL + picID)
171-
if err != nil {
172-
return
173-
}
174-
name := gjson.ParseBytes(picdata).Get("breeds.0.name").String()
175-
return typeEN2ZH[name], gjson.ParseBytes(picdata).Get("breeds.0.temperament").String(), gjson.ParseBytes(picdata).Get("breeds.0.description").String(), gjson.ParseBytes(picdata).Get("url").String(), nil
218+
219+
func suineko() breedInfo {
220+
data, err := web.GetData(apiURL + "search?has_breeds=1")
221+
if err != nil {
222+
return breedInfo{Err: err}
223+
}
224+
picID := gjson.ParseBytes(data).Get("0.id").String()
225+
picdata, err := web.GetData(apiURL + picID)
226+
if err != nil {
227+
return breedInfo{Err: err}
228+
}
229+
name := gjson.ParseBytes(picdata).Get("breeds.0.name").String()
230+
return breedInfo{
231+
TypeName: typeEN2ZH[name],
232+
Temperament: gjson.ParseBytes(picdata).Get("breeds.0.temperament").String(),
233+
Description: gjson.ParseBytes(picdata).Get("breeds.0.description").String(),
234+
ImageURL: gjson.ParseBytes(picdata).Get("url").String(),
235+
Err: nil,
236+
}
176237
}
177238

178239
func getPicByBreed(catBreed string) (url string, err error) {
179-
data, err := web.GetData(apiURL + "search?breed_ids=" + catBreed)
180-
if err != nil {
181-
return
182-
}
183-
return gjson.ParseBytes(data).Get("0.url").String(), nil
240+
data, err := web.GetData(apiURL + "search?breed_ids=" + catBreed)
241+
if err != nil {
242+
return
243+
}
244+
url = gjson.ParseBytes(data).Get("0.url").String()
245+
if url == "" {
246+
err = errors.New("no image found")
247+
}
248+
return
184249
}
185250

186251
func (sql *catdb) insert(gid string, dbInfo *catInfo) error {

0 commit comments

Comments
 (0)