UNPKG

@quanhuzeyu/koishi-plugin-pixiv

Version:

指令:随机涩图,无需获取cookies等复杂操作,获取账号下的每日推荐

530 lines (514 loc) 19.6 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __export = (target, all) => { for (var name2 in all) __defProp(target, name2, { get: all[name2], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { Config: () => Config, apply: () => apply, inject: () => inject, name: () => name, usage: () => usage }); module.exports = __toCommonJS(src_exports); var import_koishi2 = require("koishi"); // src/Data/baseData.ts var import_path = __toESM(require("path")); var ctx; var logger; var koishiBaseDir; var myPluginDataDir; var myBrowserUserDataDir; var puppeteer; var browserExecutePath; var controledPage; var pixivNetHeader; var iPximgNetHeader; function inintAllBaseData(ctx2) { setCTX(ctx2); setLogger(ctx2.logger); logger.info("正在初始化资源..."); initKoishiBaseDir(ctx2.baseDir); logger.info(`获取Koishi插件的Data目录: ${koishiBaseDir}`); initMyPluginDataDir(); logger.info(`获取插件的Data目录: ${myPluginDataDir}`); initPuppeteer(ctx2); logger.info("资源初始化完毕"); initBrowserExecutePath(ctx2.config); } __name(inintAllBaseData, "inintAllBaseData"); function setLogger(_) { logger = _; } __name(setLogger, "setLogger"); function getLogger() { return logger; } __name(getLogger, "getLogger"); function getKoishiBaseDir() { return koishiBaseDir; } __name(getKoishiBaseDir, "getKoishiBaseDir"); function initKoishiBaseDir(dir) { koishiBaseDir = dir; } __name(initKoishiBaseDir, "initKoishiBaseDir"); function getMyPluginDataDir() { return myPluginDataDir; } __name(getMyPluginDataDir, "getMyPluginDataDir"); function initMyPluginDataDir() { const baseDir = getKoishiBaseDir(); myPluginDataDir = import_path.default.resolve(baseDir, "data/@QuanhuZeYu/pixiv"); } __name(initMyPluginDataDir, "initMyPluginDataDir"); function initMyBrowserUserDataDir() { const userDataDir = import_path.default.resolve(myPluginDataDir, "chromeData"); myBrowserUserDataDir = userDataDir; } __name(initMyBrowserUserDataDir, "initMyBrowserUserDataDir"); function getMyUserDataDir() { return myBrowserUserDataDir; } __name(getMyUserDataDir, "getMyUserDataDir"); function getPuppeteer() { return puppeteer; } __name(getPuppeteer, "getPuppeteer"); function initPuppeteer(ctx2) { puppeteer = ctx2.puppeteer; } __name(initPuppeteer, "initPuppeteer"); function initBrowserExecutePath(path2) { browserExecutePath = path2; } __name(initBrowserExecutePath, "initBrowserExecutePath"); function setCTX(ctx_) { ctx = ctx_; } __name(setCTX, "setCTX"); function getCTX() { return ctx; } __name(getCTX, "getCTX"); function setCurPage(p) { controledPage = p; } __name(setCurPage, "setCurPage"); function getCurPage() { return controledPage; } __name(getCurPage, "getCurPage"); function setPixivNetHeader(h) { pixivNetHeader = h; } __name(setPixivNetHeader, "setPixivNetHeader"); function getPixivNetHeader() { return pixivNetHeader; } __name(getPixivNetHeader, "getPixivNetHeader"); function setIpximgNetHeader(h) { iPximgNetHeader = h; } __name(setIpximgNetHeader, "setIpximgNetHeader"); function getIpximgNetHeader() { return iPximgNetHeader; } __name(getIpximgNetHeader, "getIpximgNetHeader"); var baseData = { inintAllBaseData, setLogger, initKoishiBaseDir, initMyPluginDataDir, initMyBrowserUserDataDir, initPuppeteer, setCTX, setCurPage, setPixivNetHeader, setIpximgNetHeader, getLogger, getKoishiBaseDir, getMyPluginDataDir, getMyUserDataDir, getPuppeteer, getCTX, getCurPage, getPixivNetHeader, getIpximgNetHeader }; var baseData_default = baseData; // src/Data/_index.ts var Data = { baseData: baseData_default }; var index_default = Data; // src/Event/preInit.ts var started = false; async function preInit(ctx2) { if (started) return; index_default.baseData.inintAllBaseData(ctx2); started = true; } __name(preInit, "preInit"); var preInit_default = preInit; // src/chrome/mainPage.ts var import_axios = __toESM(require("axios")); var import_koishi = require("koishi"); async function pupterBrowserInit(ctx2) { const logger2 = ctx2.logger; if (ctx2.config.ensureLogin === false) { logger2.warn("当前状态为未登录,将不会进行页面初始化"); return; } const puppeteer2 = index_default.baseData.getPuppeteer(); const pages = await puppeteer2.browser.pages(); let myPage; for (const page of pages) { if (page.url() === "about:blank" || page.url().includes("pixiv.net")) { myPage = page; break; } } if (!myPage) { myPage = await puppeteer2.browser.newPage(); await myPage.goto("https://www.pixiv.net/"); } await myPage.bringToFront(); await myPage.goto("https://www.pixiv.net/"); await myPage.setRequestInterception(true); myPage.on("request", (request) => { const domain = new URL(request.url()).hostname; if (domain === "www.pixiv.net") { let header = index_default.baseData.getPixivNetHeader() || {}; header = { ...header, ...request.headers() }; index_default.baseData.setPixivNetHeader(header); } else if (domain === "i.pximg.net") { let header = index_default.baseData.getIpximgNetHeader() || {}; header = { ...header, ...request.headers() }; index_default.baseData.setIpximgNetHeader(header); } request.continue(); }); baseData_default.setCurPage(myPage); } __name(pupterBrowserInit, "pupterBrowserInit"); async function getRandomTJPic() { const logger2 = index_default.baseData.getLogger(); const page = baseData_default.getCurPage(); try { logger2.info("正在查找推荐作品"); await page.bringToFront(); const imgSelector = await page.evaluate(index_default.baseData.getCTX().config.HTMLSelector.推荐作品URLs选择器); if (!imgSelector || imgSelector.length === 0) { logger2.warn('未找到 "推荐作品" 块或其中的图片!'); return [[], "未找到推荐作品"]; } const randomIndex = getRandomInt(0, imgSelector.length - 1); const imgURL = imgSelector[randomIndex]; logger2.info(`随机选择的第${randomIndex}张图片: ${imgURL}`); const imgElement = await page.$(`img[src="${imgURL}"]`); if (!imgElement) { logger2.warn("未找到对应的图片元素"); return [[], "未找到对应的图片元素"]; } try { await imgElement.click(); } catch (e) { logger2.warn("打开作品时发生错误:", e); } logger2.info("等待网页跳转完成,并且等待选择器找到"); try { await index_default2.waitFunc.waitNav(page); logger2.info(`等待网页跳转完成: ${index_default.baseData.getCTX().config.等待NAV超时时间}ms`); await page.waitForSelector("main section figure img"); logger2.info("选择器找到,开始解析图片URL"); } catch (error) { logger2.warn(`等待超时,尝试跳过等待继续执行逻辑: ${error}`); } logger2.info("等待图片加载已结束"); const artInfo = await index_default2.pageController.getArtWorkInfo(page); try { await page.evaluate(index_default.baseData.getCTX().config.HTMLSelector.主图像查看全部按钮选择点击); } catch (error) { logger2.warn(`没有找到查看全部按钮,继续执行逻辑: ${error}`); } const bigPicURLs = await page.evaluate(index_default.baseData.getCTX().config.HTMLSelector.主图像URLs选择器); logger2.info(`从浏览器中获取到的图片链接: ${bigPicURLs}`); const pics = []; for (const url of bigPicURLs) { try { const pic = await downloadPixivImg(url); pics.push(pic); } catch (error) { logger2.warn(`下载图片失败: ${url}, 错误: ${error}`); } } return [pics, artInfo]; } catch (error) { logger2.error(`发生错误: ${error}`); return [[], error]; } finally { logger2.info("正在返回主页"); await page.goto("https://www.pixiv.net/"); index_default.baseData.setCurPage(page); } } __name(getRandomTJPic, "getRandomTJPic"); var browser = { pupterBrowserInit, getRandomTJPic }; var mainPage_default = browser; function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } __name(getRandomInt, "getRandomInt"); async function downloadPixivImg(picUrl) { const logger2 = index_default.baseData.getLogger(); try { const bigPicBuffer = await import_axios.default.get(picUrl, { responseType: "arraybuffer", headers: { ...index_default.baseData.getIpximgNetHeader(), accept: "*/*", referer: "https://www.pixiv.net/", origin: "https://www.pixiv.net" } }); logger2.info("图片下载成功"); return Buffer.from(bigPicBuffer.data); } catch (axiosError) { logger2.error(`下载图片时发生错误: `); logger2.error(axiosError); throw axiosError; } } __name(downloadPixivImg, "downloadPixivImg"); // src/chrome/waitFunc.ts async function waitNav(page) { await page.waitForNavigation({ timeout: index_default.baseData.getCTX().config.等待NAV超时时间 }); } __name(waitNav, "waitNav"); var waitFunc = { waitNav }; var waitFunc_default = waitFunc; // src/chrome/pageController/getPixivArtworkInfo.ts async function getArtWorkInfo(p) { const logger2 = index_default.baseData.getLogger(); const artWorkInfo = await p.evaluate(() => { try { const authorSection = document.querySelector("main")?.nextElementSibling?.querySelector("section"); const authorName = authorSection?.querySelectorAll("a")[1]?.textContent?.trim() || "未知"; const authorNumber = authorSection?.querySelectorAll("a")[1]?.getAttribute("href"); const infoSection = document.querySelector("section figcaption"); if (!infoSection) throw new Error("无法找到作品信息区域"); const footerSection = infoSection.querySelector("footer"); if (!footerSection) throw new Error("无法找到页脚信息区域"); const tags = footerSection.querySelectorAll("li"); const hotInfo = footerSection.nextElementSibling?.querySelectorAll("li"); const timeSection = footerSection.nextElementSibling?.nextElementSibling; const tagString = []; tags.forEach((li) => { const tagInfo = li.querySelectorAll("span"); if (tagInfo.length >= 3) { const tagText = tagInfo[1]?.textContent?.trim() || ""; const tagLinkText = tagInfo[2]?.querySelector("a")?.textContent?.trim() || ""; tagString.push(`#${tagText} ${tagLinkText}`); } else if (tagInfo.length === 2) { tagString.push(`#${tagInfo[0]?.textContent?.trim()}`); } }); const likeCount = hotInfo?.[0]?.textContent?.trim() || "0"; const collectionCount = hotInfo?.[1]?.textContent?.trim() || "0"; const viewCount = hotInfo?.[2]?.textContent?.trim() || "0"; const time = timeSection?.querySelector("time")?.textContent?.trim() || "未知"; const title0Section = infoSection.querySelector("h1"); if (title0Section) { const title1Section = title0Section.nextElementSibling; const title0 = title0Section.textContent?.trim() || "无"; const title1 = title1Section?.textContent?.trim() || "无"; return `作品名称: ${title0} 作者: ${authorName} 作者ID:${authorNumber} 副标题: ${title1} tags: ${tagString.join(" ")} 喜欢数: ${likeCount} 收藏数: ${collectionCount} 浏览数: ${viewCount} 时间: ${time}`; } else { return `作品名称: 无 作者: ${authorName} 作者ID: ${authorNumber} 副标题: 无 tags: ${tagString.join(" ")} 喜欢数: ${likeCount} 收藏数: ${collectionCount} 浏览数: ${viewCount} 时间: ${time}`; } } catch (error) { console.error("Error fetching artwork info:", error); return "无法获取作品信息"; } }); return artWorkInfo; } __name(getArtWorkInfo, "getArtWorkInfo"); var getPixivArtworkInfo_default = getArtWorkInfo; // src/chrome/pageController/_index.ts var pageController = { getArtWorkInfo: getPixivArtworkInfo_default }; var index_default3 = pageController; // src/chrome/_index.ts var chrome = { browser: mainPage_default, waitFunc: waitFunc_default, pageController: index_default3 }; var index_default2 = chrome; // src/Event/init.ts function init(ctx2) { index_default2.browser.pupterBrowserInit(ctx2); } __name(init, "init"); var init_default = init; // src/Event/cir.ts async function cycle(ctx2) { if (!started) { return; } index_default.baseData.setCTX(ctx2); const logger2 = ctx2.logger; logger2.info("正在尝试获取新的puppeteer"); index_default.baseData.initPuppeteer(ctx2); logger2.info(`正在寻找合适的页面`); await selectSuitablePage(); logger2.info("重新获取logger"); index_default.baseData.setLogger(logger2); } __name(cycle, "cycle"); var cir_default = cycle; async function selectSuitablePage() { const logger2 = index_default.baseData.getLogger(); const pages = await index_default.baseData.getPuppeteer().browser.pages(); let myPage; for (const page of pages) { if (page.url() === "about:blank" || page.url().includes("pixiv.net")) { myPage = page; myPage.goto("https://www.pixiv.net/"); } } if (myPage === void 0) { myPage = await index_default.baseData.getPuppeteer().browser.newPage(); } logger2.info(`page设置完毕: ${myPage.url()}`); index_default.baseData.setCurPage(myPage); } __name(selectSuitablePage, "selectSuitablePage"); // src/Event/_index.ts var Event = { preInit: preInit_default, init: init_default, cycle: cir_default }; var index_default4 = Event; // src/command/randomPic.tsx var import_jsx_runtime = require("@satorijs/element/jsx-runtime"); async function randomTJPic(av, ms) { let message; const logger2 = index_default.baseData.getLogger(); const ss = av.session; logger2.info("正在随机获取图片"); message = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("message", { children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("quote", { id: ss.messageId }), "你在此地不要走动" ] }); await ss.send(message); message = []; try { const [picBuffers, artInfo] = await index_default2.browser.getRandomTJPic(); logger2.info(`图片获取成功: 数量${picBuffers?.length}`); for (const pic of picBuffers) { /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: "data:image/png;base64," + pic.toString("base64") }) }); } message.push(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: artInfo })); message.join(""); message = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("message", { children: message }); await ss.send(message); } catch (e) { logger2.warn(`获取失败,失败信息: ${e}`); ss.send("获取失败,请联系管理员查看控制台"); } } __name(randomTJPic, "randomTJPic"); var randomPic_default = randomTJPic; // src/command/_index.ts var commands = { randomTJPic: randomPic_default }; var index_default5 = commands; // src/index.ts var name = "pixiv"; var usage = "第一次使用本插件时请在puppeteer服务中设置args: `--user-data-dir=/path/to/custom-profile-dir` 否则无法记录登录信息\n\n本插件没有使用反代站点,直接操作pixiv网站,所以需要能访问国外网络,在puppeteer服务中添加args `--proxy-server=127.0.0.1:<端口>`\n\n且强烈推荐关闭无头模式,因为插件可能会打开很多页面,如果你开了无头模式可能会不知不觉吃掉很多内存和性能,关掉无头随时查看浏览器\n\n使用 `随机涩图` 即可随机获取一张p站推荐作品中的图片~~~"; var inject = { required: ["puppeteer"] }; var Config = import_koishi2.Schema.object({ // excutePath: Schema.string().description("puppeteer的chrome路径或者chromium路径").required(), ensureLogin: import_koishi2.Schema.boolean().description("请在确认登录过pixiv后再打开此开关!").default(false), 等待NAV超时时间: import_koishi2.Schema.number().description("等待NAV超时时间,单位ms").default(15e3), HTMLSelector: import_koishi2.Schema.object({ 推荐作品URLs选择器: import_koishi2.Schema.string().description("如果你不知道这是什么请不要动它!!!推荐页面的图片选择器,编辑一段可以在浏览器运行的代码段,最后返回目标图片urls数组").default("const sections = Array.from(document.querySelectorAll('section'));const tuijianSections = sections.filter((section) =>section.textContent.includes('推荐作品'));const listItems = Array.from(tuijianSections[0].querySelectorAll('li'));const imgEs = [];for(const li of listItems) {const img = li.querySelector('img');if (img && img?.src) {if (img.src.includes('i.pximg.net')) {imgEs.push(img.src);}}} imgEs;"), 主图像查看全部按钮选择点击: import_koishi2.Schema.string().description("如果你不知道这是什么请不要动它!!!这个选择器是尝试找查看全部按钮然后展开全部作品,方便获取所有图片").default("const buttonsDivs = Array.from(document.querySelectorAll(`main button div`));const lookAllDiv = buttonsDivs.find(div => div.textContent.includes(`查看全部`));lookAllDiv.click()"), 主图像URLs选择器: import_koishi2.Schema.string().description("如果你不知道这是什么请不要动它!!!这个选择器是选择点击进入作品后寻找大图的,最后返回原图像的URLs数组").default("const urls = []; Array.from(document.querySelector('main section figure').querySelectorAll('img')).forEach(img => urls.push(img.src)); urls;") }) }); function apply(ctx2) { index_default4.preInit(ctx2); index_default4.init(ctx2); index_default4.cycle(ctx2); ctx2.command("随机涩图 [message:text]").usage("从p站的推荐作品中随机获取一张图片").action(async (av, ms) => { await index_default5.randomTJPic(av, ms); }); } __name(apply, "apply"); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Config, apply, inject, name, usage });