Files
yenai-plugin/model/PicSearch/ascii2d.js
2024-04-06 19:02:02 +08:00

125 lines
3.9 KiB
JavaScript
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.
/* eslint-disable no-unused-vars */
import _ from "lodash"
import { puppeteer } from "../index.js"
import request from "../../lib/request/request.js"
import { Config } from "../../components/index.js"
let cheerio = ""
let domain = "https://ascii2d.net/"
/**
*
*/
async function importCheerio() {
if (cheerio) return cheerio
try {
cheerio = await import("cheerio")
} catch (e) {
throw new ReplyError("未检测到依赖cheerio请安装后再使用Ascii2D搜图安装命令pnpm add cheerio -w 或 pnpm install -P")
}
}
/**
*
* @param url
*/
export default async function doSearch(url) {
await importCheerio()
const { ascii2dUsePuppeteer, ascii2dResultMaxQuantity } = Config.picSearch
const callApi = ascii2dUsePuppeteer ? callAscii2dUrlApiWithPuppeteer : callAscii2dUrlApi
let ret = await callApi(url)
if (!ret) throw new ReplyError("Ascii2D搜图请求失败")
const colorURL = ret.url
if (!colorURL.includes("/color/")) {
const $ = cheerio.load(ret.data, { decodeEntities: false })
logger.error("[error] ascii2d url:", colorURL)
logger.debug(ret.data)
let isCloudflare = ret.data.includes("cloudflare") ? "绕过Cloudflare盾失败" : false
throw new ReplyError(`Ascii2D搜索失败错误原因${isCloudflare || $(".container > .row > div:first-child > p").text().trim()}`)
}
const bovwURL = colorURL.replace("/color/", "/bovw/")
let bovwDetail = await (ascii2dUsePuppeteer ? getAscii2dWithPuppeteer(bovwURL) : request.cfGet(bovwURL))
if (!ascii2dUsePuppeteer) {
bovwDetail = {
url: bovwDetail.url,
data: await bovwDetail.text()
}
}
let colorData = (await parse(ret.data)).slice(0, ascii2dResultMaxQuantity)
let bovwData = (await parse(bovwDetail.data)).slice(0, ascii2dResultMaxQuantity)
if (_.isEmpty(colorData)) throw new ReplyError("Ascii2D数据获取失败")
let mapfun = item => [
Config.picSearch.hideImg ? "" : segment.image(item.image),
`${item.info}\n`,
`标题:${item.source?.text}\n`,
`作者:${item.author?.text}(${item.author?.link})\n`,
`来源:${item.source?.link}`
]
let color = colorData.map(mapfun)
let bovw = bovwData.map(mapfun)
color.unshift("ascii2d 色合検索")
bovw.unshift("ascii2d 特徴検索")
return {
color,
bovw
}
}
const callAscii2dUrlApiWithPuppeteer = (imgUrl) => {
return getAscii2dWithPuppeteer(`${domain}/search/url/${imgUrl}`)
}
const callAscii2dUrlApi = async(imgUrl) => {
let res = await request.cfGet(`${domain}/search/url/${imgUrl}`).catch(
err => {
if (err.stack?.includes("legacy sigalg disallowed or unsupported")) {
throw new ReplyError(`Error Tls版本过低 请尝试将配置文件的cfTLSVersion字段改为TLS1.2\n详情请参考https://www.yenai.ren/faq.html#openssl-%E9%94%99%E8%AF%AF\n错误信息:${err.stack}`)
} else {
throw err
}
}
)
return {
url: res.url,
data: await res.text()
}
}
/**
*
* @param url
*/
async function getAscii2dWithPuppeteer(url) {
return await puppeteer.get(url, "body > .container")
}
/**
*
* @param body
*/
async function parse(body) {
const $ = cheerio.load(body, { decodeEntities: true })
return _.map($(".item-box"), (item) => {
const detail = $(".detail-box", item)
const hash = $(".hash", item)
const info = $(".info-box > .text-muted", item)
const [ image ] = $(".image-box > img", item)
const [ source, author ] = $("a[rel=noopener]", detail)
if (!source && !author) return
return {
hash: hash.text(),
info: info.text(),
image: new URL(
image.attribs.src ?? image.attribs["data-cfsrc"],
domain
).toString(),
source: source
? { link: source.attribs.href, text: $(source).text() }
: undefined,
author: author
? { link: author.attribs.href, text: $(author).text() }
: undefined
}
}).filter(v => v !== undefined)
}