diff --git a/cmd/main.go b/cmd/main.go index a502051..76fafff 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -34,6 +34,7 @@ import ( _ "github.com/RicheyJang/PaimengBot/plugins/music" _ "github.com/RicheyJang/PaimengBot/plugins/note" _ "github.com/RicheyJang/PaimengBot/plugins/pixiv" + _ "github.com/RicheyJang/PaimengBot/plugins/pixiv_query" _ "github.com/RicheyJang/PaimengBot/plugins/pixiv_rank" _ "github.com/RicheyJang/PaimengBot/plugins/random" _ "github.com/RicheyJang/PaimengBot/plugins/short_url" diff --git a/plugins/pixiv/download.go b/plugins/pixiv/download.go index 4ee5a80..f26ab34 100644 --- a/plugins/pixiv/download.go +++ b/plugins/pixiv/download.go @@ -155,6 +155,7 @@ func (pic *PictureInfo) GetPicture() (path string, err error) { return "", fmt.Errorf("GetURLByPID failed: %v", err) } } + pic.ReplaceURLToProxy() // 反代 // 下载图片 path, err = images.GetNewTempSavePath("pixiv") if err != nil { @@ -198,7 +199,7 @@ func (pic *PictureInfo) GetDescribe() string { // GetURLByPID 通过PID获取图片下载URL func (pic *PictureInfo) GetURLByPID() (err error) { - if pic.PID == 0 { + if pic == nil || pic.PID == 0 { return fmt.Errorf("pid is 0") } // 整理API URL diff --git a/plugins/pixiv_query/hibi.go b/plugins/pixiv_query/hibi.go new file mode 100644 index 0000000..6fa2c3f --- /dev/null +++ b/plugins/pixiv_query/hibi.go @@ -0,0 +1,94 @@ +package pixiv_query + +import ( + "fmt" + "strconv" + "strings" + + "github.com/RicheyJang/PaimengBot/plugins/pixiv" + "github.com/RicheyJang/PaimengBot/utils" + "github.com/RicheyJang/PaimengBot/utils/client" + "github.com/RicheyJang/PaimengBot/utils/consts" + + "github.com/tidwall/gjson" +) + +func getPixivPIDsByHIBI(pid int64) ([]pixiv.PictureInfo, error) { + // URL + api, err := getHibiAPI() + if err != nil { + return nil, err + } + api = fmt.Sprintf("%sapi/pixiv/illust?id=%v", api, pid) + // 调用 + c := client.NewHttpClient(nil) + rsp, err := c.GetGJson(api) + if err != nil { + return nil, err + } + illust := rsp.Get("illust") + if !illust.Exists() { + return []pixiv.PictureInfo{{Title: rsp.Get("error.user_message").String()}}, fmt.Errorf("illust is not found") + } + // 解析 + pics := make([]pixiv.PictureInfo, int(illust.Get("page_count").Int())) + if len(pics) == 0 { + return nil, fmt.Errorf("page_count is zero") + } + pics[0] = analysisHIBIIllust(illust, 0) + if len(pics) > 1 { // 获取所有分P的URL + urls := illust.Get("meta_pages.#.image_urls.original").Array() + for i, url := range urls { + if i >= len(pics) { + break + } + pics[i].PID = pid + pics[i].P = i + pics[i].URL = url.String() + } + } + return pics, nil +} + +// 工具函数 + +// 整理API URL +func getHibiAPI() (string, error) { + api := proxy.GetAPIConfig(consts.APIOfHibiAPIKey) + if len(api) == 0 { + return "", fmt.Errorf("API of HibiAPI is empty") + } + if !strings.HasPrefix(api, "http://") && !strings.HasPrefix(api, "https://") { + api = "https://" + api + } + if !strings.HasSuffix(api, "/") { + api += "/" + } + return api, nil +} + +// 分析单张插图信息 +func analysisHIBIIllust(illust gjson.Result, p int) pixiv.PictureInfo { + pic := pixiv.PictureInfo{ + Title: illust.Get("title").String(), + PID: illust.Get("id").Int(), + P: p, + Author: illust.Get("user.name").String(), + UID: illust.Get("user.id").Int(), + } + for _, tag := range illust.Get("tags").Array() { + if tag.Get("name").Type != gjson.Null { + pic.Tags = append(pic.Tags, tag.Get("name").String()) + } + if tag.Get("translated_name").Type != gjson.Null { + pic.Tags = append(pic.Tags, tag.Get("translated_name").String()) + } + } + pic.Tags = utils.MergeStringSlices(pic.Tags) // 去重 + if illust.Get("page_count").Int() == 1 { + pic.URL = illust.Get("meta_single_page.original_image_url").String() + } else if illust.Get("page_count").Int() > int64(pic.P) { + pic.URL = illust.Get("meta_pages." + strconv.Itoa(pic.P) + ".image_urls.original").String() + } + return pic +} diff --git a/plugins/pixiv_query/init.go b/plugins/pixiv_query/init.go new file mode 100644 index 0000000..c1a9af3 --- /dev/null +++ b/plugins/pixiv_query/init.go @@ -0,0 +1,108 @@ +package pixiv_query + +import ( + "fmt" + "strconv" + "strings" + + "github.com/RicheyJang/PaimengBot/manager" + "github.com/RicheyJang/PaimengBot/utils" + "github.com/RicheyJang/PaimengBot/utils/consts" + + log "github.com/sirupsen/logrus" + zero "github.com/wdvxdr1123/ZeroBot" + "github.com/wdvxdr1123/ZeroBot/message" +) + +var info = manager.PluginInfo{ + Name: "pixiv搜索", + Usage: `用法:(以下功能仅限私聊) + pixiv搜索 p[PID]:发送指定PID的所有分P插画`, + Classify: "好康的", +} +var proxy *manager.PluginProxy + +func init() { + proxy = manager.RegisterPlugin(info) + if proxy == nil { + return + } + proxy.OnCommands([]string{"pixiv搜索", "pixiv查询", "p站搜索", "P站查询"}, zero.OnlyPrivate).SetBlock(true).SetPriority(3).Handle(queryHandler) + proxy.AddAPIConfig(consts.APIOfHibiAPIKey, "api.obfs.dev") +} + +func queryHandler(ctx *zero.Ctx) { + if proxy.LockUser(ctx.Event.UserID) { + ctx.Send("有正在进行中的搜索,稍等哦") + return + } + defer proxy.UnlockUser(ctx.Event.UserID) + // 解析参数 + arg := strings.TrimSpace(utils.GetArgs(ctx)) + if strings.HasPrefix(arg, "p") { // 搜索PID + id, err := strconv.ParseInt(arg[len("p"):], 10, 64) + if err != nil { + ctx.Send("PID格式不对") + return + } + queryPID(ctx, id) + return + } else { // 搜索其它内容 + ctx.Send(`暂不支持搜索此类内容,可以看看"帮助 pixiv搜索"或"帮助 好康的"`) + return + } +} + +func queryPID(ctx *zero.Ctx, pid int64) { + pics, err := getPixivPIDsByHIBI(pid) + if err != nil || len(pics) == 0 { + if len(pics) > 0 && len(pics[0].Title) > 0 { + ctx.Send(pics[0].Title) + } else { + ctx.Send("失败了...") + } + log.Warnf("getPixivPIDsByHIBI err: %v", err) + return + } + // 首图信息及模式检查 + mainPic := pics[0] + str := mainPic.Title + "\n" + mainPic.GetDescribe() + if !mainPic.CheckNoSESE() { + ctx.Send(str) + return + } + str += fmt.Sprintf("\n是否确定发送?") + ctx.Send(str) + // 发送确认 + if !isConfirm(ctx) { + ctx.Send("那算啦") + return + } + ctx.Send(fmt.Sprintf("即将发送共%d张图片", len(pics))) + // 发送图片 + for i, pic := range pics { + path, err := pic.GetPicture() + if err != nil { // 下载失败 + log.Infof("下载第%d张插画失败,err: %v", i, err) + ctx.Send(fmt.Sprintf("下载第%d张插画失败,跳过", i+1)) + continue + } + // 构成消息 + picMsg, err := utils.GetImageFileMsg(path) + if err != nil { + log.Infof("发送第%d张插画失败 GetImageFileMsg err: %v", i, err) + ctx.Send(fmt.Sprintf("发送第%d张插画失败,跳过", i+1)) + continue + } + ctx.Send(message.Message{picMsg}) + } +} + +func isConfirm(ctx *zero.Ctx) bool { + e := utils.WaitNextMessage(ctx) + if e == nil { + return false + } + confirm := e.Message.ExtractPlainText() + return confirm == "是" || confirm == "确定" || confirm == "确认" +}