koishi-plugin-pixiv-parse
Version:
提供 Pixiv 链接解析与更新订阅功能的 Koishi 插件
520 lines (518 loc) • 27.3 kB
JavaScript
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
});
module.exports = __toCommonJS(src_exports);
var import_koishi = require("koishi");
var import_fs = require("fs");
var import_path = __toESM(require("path"));
var import_muhammara = require("muhammara");
var import_sharp = __toESM(require("sharp"));
var name = "pixiv-parse";
var inject = {
required: ["http", "database"],
optional: ["puppeteer"]
};
var logger = new import_koishi.Logger(name);
var Config = import_koishi.Schema.intersect([
import_koishi.Schema.object({
refreshToken: import_koishi.Schema.string().role("secret").description("Pixiv API Refresh Token。用于 API 请求。"),
phpsessid: import_koishi.Schema.string().role("secret").description("Pixiv 网页版 Cookie (PHPSESSID)。用于 Puppeteer 截图。")
}).description("账户设置"),
import_koishi.Schema.object({
sendTags: import_koishi.Schema.boolean().description("发送作品时,是否附带标签。").default(true),
sendAuthor: import_koishi.Schema.boolean().description("发送作品时,是否附带作者信息。").default(true),
sendLinkWithCommand: import_koishi.Schema.boolean().description("当使用指令时,是否在消息中一并发送作品的源链接。").default(false),
r18Action: import_koishi.Schema.union([
import_koishi.Schema.const("block").description("屏蔽 R-18 作品"),
import_koishi.Schema.const("warn").description("发送警告并附带作品信息 (不发图)"),
import_koishi.Schema.const("send").description("直接发送 (后果自负)")
]).description("【最高优先级】如何处理 R-18/R-18G 作品。").default("warn")
}).description("发送设置"),
import_koishi.Schema.object({
forwardThreshold: import_koishi.Schema.number().min(0).step(1).description("【插画】图片数量超过此值时,将启用合并转发。设为 0 则彻底禁用此功能。").default(3),
pdfThreshold: import_koishi.Schema.number().min(0).step(1).description("【插画】图片数量超过此值时,将自动转为 PDF 发送。优先级高于合并转发。设为 0 则永不转为 PDF。").default(10),
autoPdfForR18: import_koishi.Schema.boolean().description("【插画】当 R-18 作品被允许发送时,是否自动转为 PDF 发送(无视图片数量)。").default(true),
pdfPassword: import_koishi.Schema.string().role("secret").description("(可选)为生成的 PDF 文件设置一个打开密码。"),
pdfSendMode: import_koishi.Schema.union([
import_koishi.Schema.const("buffer").description("buffer (内存模式)"),
import_koishi.Schema.const("file").description("file (硬盘模式)")
]).description("【PDF模式】发送方式。Docker 环境请选择 buffer 。").default("buffer"),
enableCompression: import_koishi.Schema.boolean().description("【PDF模式】是否启用图片压缩以减小 PDF 文件体积。").default(true),
compressionQuality: import_koishi.Schema.number().min(1).max(100).step(1).role("slider").default(80).description("【PDF模式】JPEG 图片质量 (1-100)。注意:JPEG为有损压缩,100为最高质量而非无损。")
}).description("插画输出模式设置"),
import_koishi.Schema.object({
enableUidCommand: import_koishi.Schema.boolean().description("是否启用 `uid` 指令来获取作者主页截图。<b>注意:必须安装并启用 `puppeteer` 服务插件才能使用此功能。</b>").default(true),
sendUserInfoText: import_koishi.Schema.boolean().description("发送作者主页截图时,是否同时发送作者的文本信息(昵称、简介等)。").default(true)
}).description("作者主页 (UID) 设置"),
import_koishi.Schema.object({
enableSubscription: import_koishi.Schema.boolean().description("**【总开关】是否启用订阅功能。** 开启后会显示详细设置。").default(false)
}).description("订阅设置"),
import_koishi.Schema.union([
import_koishi.Schema.object({
enableSubscription: import_koishi.Schema.const(false)
}),
import_koishi.Schema.object({
enableSubscription: import_koishi.Schema.const(true),
updateInterval: import_koishi.Schema.number().min(1).description("每隔多少分钟检查一次更新。").default(30),
pushBotPlatform: import_koishi.Schema.string().description("用于执行推送的机器人平台 (例如: onebot)。").required(),
pushBotId: import_koishi.Schema.string().description("用于执行推送的机器人账号/ID (例如: 12345678)。").required(),
subscriptions: import_koishi.Schema.array(import_koishi.Schema.object({
uid: import_koishi.Schema.string().description("作者的 UID (纯数字)"),
name: import_koishi.Schema.string().description("作者名字 (仅用于备注)"),
channelIds: import_koishi.Schema.array(String).role("table").description("要推送到的频道/群组ID列表 (纯数字)。")
})).role("table").description("订阅列表")
})
]),
import_koishi.Schema.object({
downloadConcurrency: import_koishi.Schema.number().min(1).max(10).step(1).description("下载多张图片时的并行下载数量。").default(4)
}).description("网络与下载设置"),
import_koishi.Schema.object({
debug: import_koishi.Schema.boolean().description("是否在控制台输出详细的调试日志。").default(false)
}).description("调试设置"),
import_koishi.Schema.object({
clientId: import_koishi.Schema.string().role("secret").description("Pixiv API Client ID.").default("MOBrBDS8blbauoSck0ZfDbtuzpyT"),
clientSecret: import_koishi.Schema.string().role("secret").description("Pixiv API Client Secret.").default("lsACyCD94FhDUtGTXi3QzcFE2uU1hqtDaKeqrdwj")
}).description("高级设置 (警告:除非你知道你在做什么,否则不要修改这些值!)")
]);
var PixivService = class {
constructor(ctx, config) {
this.ctx = ctx;
this.config = config;
this.headers = {
"app-os": "ios",
"app-os-version": "14.6",
"user-agent": "PixivIOSApp/7.13.3 (iOS 14.6; iPhone13,2)",
"Referer": "https://www.pixiv.net/"
};
}
static {
__name(this, "PixivService");
}
accessToken = null;
headers;
async _refreshAccessToken() {
if (!this.config.refreshToken) {
logger.warn("未配置 Refresh Token,无法进行认证。");
return false;
}
const data = new URLSearchParams({
"grant_type": "refresh_token",
"client_id": this.config.clientId,
"client_secret": this.config.clientSecret,
"refresh_token": this.config.refreshToken,
"get_secure_url": "true"
}).toString();
try {
const response = await this.ctx.http.post("https://oauth.secure.pixiv.net/auth/token", data, {
headers: {
...this.headers,
"Content-Type": "application/x-www-form-urlencoded",
"host": "oauth.secure.pixiv.net"
}
});
if (response.access_token) {
this.accessToken = response.access_token;
if (this.config.debug) logger.info("AccessToken 刷新成功!");
return true;
}
return false;
} catch (error) {
this.accessToken = null;
logger.error("刷新 AccessToken 失败:", error.response?.data || error.message);
return false;
}
}
async _request(url, params) {
if (!this.accessToken) {
if (!await this._refreshAccessToken()) {
throw new Error("无法获取或刷新 Access Token。");
}
}
const makeRequest = /* @__PURE__ */ __name(() => {
const requestHeaders = { ...this.headers, "Authorization": `Bearer ${this.accessToken}` };
return this.ctx.http.get(url, { params, headers: requestHeaders });
}, "makeRequest");
try {
return await makeRequest();
} catch (error) {
const errorMsg = error.response?.data?.error?.message || "";
if (error.response?.status === 400 && /invalid_grant|invalid_token/i.test(errorMsg)) {
if (this.config.debug) logger.info("AccessToken 已失效,尝试强制刷新...");
if (await this._refreshAccessToken()) {
if (this.config.debug) logger.info("刷新成功,正在重试请求...");
return await makeRequest();
}
}
throw error;
}
}
async getArtworkDetail(pid) {
try {
const response = await this._request(`https://app-api.pixiv.net/v1/illust/detail`, { illust_id: pid, filter: "for_ios" });
return response.illust;
} catch (error) {
if (this.config.debug) logger.warn(`获取插画详情失败 (PID: ${pid}):`, error.response?.data || error.message);
return null;
}
}
async downloadImage(url) {
try {
const arrayBuffer = await this.ctx.http.get(url, {
headers: { "Referer": "https://www.pixiv.net/" },
responseType: "arraybuffer",
timeout: 6e4
});
return Buffer.from(arrayBuffer);
} catch (error) {
logger.warn(`图片下载失败 (URL: ${url}):`, error.message);
return null;
}
}
async getUserDetail(uid) {
try {
const response = await this._request("https://app-api.pixiv.net/v1/user/detail", { user_id: uid });
return response;
} catch (error) {
if (this.config.debug) logger.warn(`获取用户详情失败 (UID: ${uid}):`, error.response?.data || error.message);
return null;
}
}
async getUserIllusts(uid) {
try {
const response = await this._request(`https://app-api.pixiv.net/v1/user/illusts`, { user_id: uid, filter: "for_ios" });
return response.illusts;
} catch (error) {
if (this.config.debug) logger.warn(`获取用户作品失败 (UID: ${uid}):`, error.response?.data || error.message);
return null;
}
}
};
function apply(ctx, config) {
ctx.model.extend("pixiv_last_artworks", {
author_id: "string",
last_artwork_id: "string"
}, {
primary: "author_id"
});
const pixiv = new PixivService(ctx, config);
async function createPdfFile(illust, buffers) {
const safeTitle = (illust.title || illust.id).replace(/[\\/:\*\?"<>\|]/g, "_");
const tempDir = import_path.default.resolve(ctx.app.baseDir, "data", "temp", "pixiv-parse");
const tempPdfPath = import_path.default.resolve(tempDir, `${safeTitle}_${Date.now()}.pdf`);
const tempImageDir = import_path.default.resolve(tempDir, `pid_${illust.id}_${Date.now()}`);
await import_fs.promises.mkdir(tempImageDir, { recursive: true });
const recipe = new import_muhammara.Recipe("new", tempPdfPath, { version: 1.6 });
try {
for (const [index, buffer] of buffers.entries()) {
const tempImagePath = import_path.default.resolve(tempImageDir, `${index + 1}.jpg`);
let imageToProcess = (0, import_sharp.default)(buffer);
if (config.enableCompression) {
imageToProcess = imageToProcess.jpeg({ quality: config.compressionQuality });
}
await imageToProcess.toFile(tempImagePath);
const metadata = await (0, import_sharp.default)(tempImagePath).metadata();
recipe.createPage(metadata.width, metadata.height).image(tempImagePath, 0, 0, {
keepAspectRatio: true,
width: metadata.width,
height: metadata.height
}).endPage();
}
if (config.pdfPassword) recipe.encrypt({ userPassword: config.pdfPassword, ownerPassword: config.pdfPassword });
recipe.endPDF();
return tempPdfPath;
} finally {
try {
await import_fs.promises.rm(tempImageDir, { recursive: true, force: true });
} catch {
}
}
}
__name(createPdfFile, "createPdfFile");
async function takeUserPageScreenshot(uid) {
const page = await ctx.puppeteer.page();
try {
if (config.phpsessid) {
await page.setCookie({ name: "PHPSESSID", value: config.phpsessid, domain: ".pixiv.net", path: "/" });
if (config.debug) logger.info(`[Puppeteer] 已设置 PHPSESSID Cookie。`);
} else {
logger.warn(`[Puppeteer] 未配置 PHPSESSID,截图可能会因登录墙而失败。`);
}
const url = `https://www.pixiv.net/users/${uid}`;
await page.goto(url, { waitUntil: "networkidle0", timeout: 3e4 });
await (0, import_koishi.sleep)(2e3);
if (config.debug) logger.info(`[Puppeteer] 页面加载完成,准备截取完整页面...`);
return await page.screenshot({ type: "png", fullPage: true });
} catch (error) {
logger.error(`[Puppeteer] 截图失败 (UID: ${uid}):`, error);
return null;
} finally {
if (page) await page.close();
}
}
__name(takeUserPageScreenshot, "takeUserPageScreenshot");
async function handlePixivRequest(session, id, source, isSubscription = false) {
const statusMessage = !isSubscription ? await session.send((0, import_koishi.h)("quote", { id: session.messageId }) + `正在解析 Pixiv 作品 (ID: ${id})...`) : null;
try {
const illust = await pixiv.getArtworkDetail(id);
if (!illust) return isSubscription ? null : (0, import_koishi.h)("quote", { id: session.messageId }) + "找不到该 ID 对应的插画作品。";
const isR18 = illust.x_restrict > 0;
if (isR18) {
if (config.r18Action === "block") return isSubscription ? null : (0, import_koishi.h)("quote", { id: session.messageId }) + "根据配置,已屏蔽 R-18 作品。";
if (config.r18Action === "warn" && !isSubscription) return (0, import_koishi.h)("quote", { id: session.messageId }) + `[警告] 该作品为 R-18/R-18G 内容!
标题: ${illust.title}
作者: ${illust.user.name}`;
}
const imageUrls = [];
if (illust.meta_pages && illust.meta_pages.length > 0) {
imageUrls.push(...illust.meta_pages.map((p) => p.image_urls.original));
} else {
imageUrls.push(illust.meta_single_page.original_image_url);
}
const imageBuffers = (await Promise.all(imageUrls.map((url) => pixiv.downloadImage(url)))).filter(Boolean);
if (imageBuffers.length === 0) return isSubscription ? null : (0, import_koishi.h)("quote", { id: session.messageId }) + "所有图片都下载失败了,无法发送。";
const imageCount = imageBuffers.length;
let textInfo = (isSubscription ? `[${illust.user.name} 的作品更新]
` : "") + `[标题] ${illust.title}` + (config.sendAuthor ? `
[作者] ${illust.user.name}` : "") + (config.sendTags && illust.tags.length > 0 ? `
[标签] ${illust.tags.map((t) => t.name).join(", ")}` : "") + (isR18 ? `
[警告] 本作品为 R-18/R-18G 内容` : "");
if (source === "command" && config.sendLinkWithCommand) {
textInfo += `
[源链接] https://www.pixiv.net/artworks/${id}`;
}
const safeTitle = (illust.title || illust.id).replace(/[\\/:\*\?"<>\|]/g, "_");
const shouldCreatePdf = config.autoPdfForR18 && isR18 || config.pdfThreshold > 0 && imageCount >= config.pdfThreshold;
if (shouldCreatePdf) {
const pdfPath = await createPdfFile(illust, imageBuffers);
let messageElements;
try {
if (config.pdfSendMode === "file") {
if (config.debug) logger.info(`[PDF] 使用 "file" 模式发送: ${pdfPath}`);
messageElements = [(0, import_koishi.h)("p", textInfo), import_koishi.h.file(`file://${pdfPath}`, { title: `${safeTitle}.pdf` })];
} else {
if (config.debug) logger.info(`[PDF] 使用 "buffer" 模式发送`);
const pdfBuffer = await import_fs.promises.readFile(pdfPath);
messageElements = [(0, import_koishi.h)("p", textInfo), import_koishi.h.file(pdfBuffer, "application/pdf", { title: `${safeTitle}.pdf` })];
}
return messageElements;
} finally {
const delay = config.pdfSendMode === "file" ? 5e3 : 0;
setTimeout(() => {
import_fs.promises.unlink(pdfPath).catch((e) => logger.warn(`[PDF] 清理临时文件失败 ${pdfPath}:`, e));
}, delay);
}
}
const allContentNodes = [(0, import_koishi.h)("p", textInfo), ...imageBuffers.map((buffer) => import_koishi.h.image(buffer, "image/png"))];
const platform = isSubscription ? config.pushBotPlatform : session?.platform;
if (config.forwardThreshold > 0 && imageCount >= config.forwardThreshold && ["qq", "onebot"].includes(platform)) {
return (0, import_koishi.h)("figure", {}, allContentNodes);
}
return allContentNodes;
} catch (error) {
logger.error(`处理 Pixiv 请求时发生未知错误 (ID: ${id}):`, error);
return isSubscription ? null : (0, import_koishi.h)("quote", { id: session.messageId }) + `处理时发生未知错误:${error.message}`;
} finally {
if (statusMessage) try {
await session.bot.deleteMessage(session.channelId, statusMessage[0]);
} catch (e) {
}
}
}
__name(handlePixivRequest, "handlePixivRequest");
async function checkAndPushUpdates(isManualTrigger = false) {
if (!config.enableSubscription) return;
if (config.debug) logger.info("[订阅] 开始检查更新...");
const bot = ctx.bots.find((b) => b.platform === config.pushBotPlatform && b.selfId === config.pushBotId && b.status === 1);
if (!bot) {
const botIdentifier = `${config.pushBotPlatform}:${config.pushBotId}`;
logger.warn(`[订阅] 配置中指定的机器人 [${botIdentifier}] 不存在或不在线,跳过本轮检查。`);
return isManualTrigger ? `配置中指定的机器人 [${botIdentifier}] 不存在或不在线。` : void 0;
}
let updatesFound = 0;
for (const sub of config.subscriptions) {
if (!sub.uid || !sub.channelIds || sub.channelIds.length === 0) continue;
if (config.debug) logger.info(`[订阅] 正在检查作者: ${sub.name} (UID: ${sub.uid})`);
try {
const illusts = await pixiv.getUserIllusts(sub.uid);
if (!illusts || illusts.length === 0) {
if (config.debug) logger.info(`[订阅] 未能获取到作者 ${sub.name} 的任何作品,跳过。`);
continue;
}
const latestIllust = illusts[0];
const latestId = latestIllust.id.toString();
if (config.debug) logger.info(`[订阅] API 返回的最新作品ID: ${latestId}`);
const record = await ctx.database.get("pixiv_last_artworks", { author_id: sub.uid });
const lastIdInDb = record[0]?.last_artwork_id;
if (config.debug) logger.info(`[订阅] 数据库中记录的ID: ${lastIdInDb || "无"}`);
const isNew = !lastIdInDb || latestId !== lastIdInDb;
const shouldPush = isNew || isManualTrigger && !!latestId;
if (config.debug) logger.info(`[订阅] 检查结果: isNew=${isNew}, isManualTrigger=${isManualTrigger}, shouldPush=${shouldPush}`);
if (shouldPush) {
logger.info(`[订阅] ★ 发现 [${sub.name}] 的新作品或被手动触发: ${latestId}`);
updatesFound++;
const messageContent = await handlePixivRequest(null, latestId, "middleware", true);
if (!messageContent) {
logger.warn(`[订阅] 新作品 ${latestId} 内容生成失败,跳过推送。`);
continue;
}
for (const channelId of sub.channelIds) {
try {
await bot.sendMessage(channelId, Array.isArray(messageContent) ? messageContent.join("\n") : messageContent);
} catch (e) {
logger.warn(`[订阅] 向频道 ${channelId} 推送失败 (使用机器人 ${bot.sid}):`, e.message);
}
}
}
if (isNew) {
await ctx.database.upsert("pixiv_last_artworks", [{ author_id: sub.uid, last_artwork_id: latestId }]);
if (config.debug) logger.info(`[订阅] 数据库ID已更新为: ${latestId}`);
}
} catch (error) {
logger.error(`[订阅] 检查作者 ${sub.name} (UID: ${sub.uid}) 时出错:`, error);
}
}
if (config.debug) logger.info(`[订阅] 本轮检查结束,共推送 ${updatesFound} 个更新。`);
if (isManualTrigger) return `手动检查完成,共为 ${updatesFound} 个订阅执行了推送任务。`;
}
__name(checkAndPushUpdates, "checkAndPushUpdates");
ctx.command("pid <id:string>", "通过 ID 获取 Pixiv 插画").action(async ({ session }, id) => {
if (!id || !/^\d+$/.test(id)) return "请输入有效的 Pixiv 作品 ID。";
const result = await handlePixivRequest(session, id, "command");
if (result) await session.send(Array.isArray(result) ? result.join("\n") : result);
});
ctx.command("uid <uid:string>", "获取 Pixiv 作者主页信息与截图").action(async ({ session }, uid) => {
if (!config.enableUidCommand) return "uid 指令未启用。";
if (!ctx.puppeteer) {
logger.warn("uid 指令需要 puppeteer 服务,但该服务未启用或未注入。");
return "错误:此功能依赖的 puppeteer 服务未启用。";
}
if (!uid || !/^\d+$/.test(uid)) return "请输入有效的 Pixiv 用户 ID。";
const statusMessage = await session.send((0, import_koishi.h)("quote", { id: session.messageId }) + `正在获取作者信息 (UID: ${uid})...`);
try {
const [detailResponse, screenshotBuffer] = await Promise.all([
config.sendUserInfoText ? pixiv.getUserDetail(uid) : Promise.resolve(null),
takeUserPageScreenshot(uid)
]);
const messageElements = [];
if (detailResponse?.user) {
const { user, profile } = detailResponse;
let textInfo = `[作者] ${user.name} (@${user.account})
[主页] https://www.pixiv.net/users/${user.id}`;
if (profile.total_follow_users) textInfo += `
[关注] ${profile.total_follow_users} 人`;
const totalWorks = profile.total_illusts + profile.total_manga;
if (totalWorks > 0) textInfo += `
[插画/漫画] ${totalWorks} 个`;
const cleanBio = (profile.comment || "").replace(/<br \/>/g, "\n").replace(/<[^>]*>/g, "");
if (cleanBio) textInfo += `
[简介] ${cleanBio}`;
messageElements.push((0, import_koishi.h)("p", textInfo));
} else if (config.sendUserInfoText) {
messageElements.push((0, import_koishi.h)("p", `获取作者文本信息失败。`));
}
if (screenshotBuffer) {
messageElements.push(import_koishi.h.image(screenshotBuffer, "image/png"));
} else {
messageElements.push((0, import_koishi.h)("p", `获取主页截图失败。`));
}
await session.send(messageElements);
} catch (error) {
logger.error(`处理 UID 请求时发生未知错误 (UID: ${uid}):`, error);
return (0, import_koishi.h)("quote", { id: session.messageId }) + `处理时发生未知错误:${error.message}`;
} finally {
try {
await session.bot.deleteMessage(session.channelId, statusMessage[0]);
} catch (e) {
}
}
});
ctx.command("pixivtest <uid:string>", "测试获取作者最新作品并推送到当前频道").action(async ({ session }, uid) => {
if (!config.enableSubscription) return "订阅功能未启用。";
if (!uid || !/^\d+$/.test(uid)) return "请输入有效的作者 UID。";
await session.send(`正在为 [${uid}] 获取最新作品并模拟推送到当前会话...`);
const illusts = await pixiv.getUserIllusts(uid);
if (!illusts || illusts.length === 0) return "无法找到该作者的任何作品。";
const latestId = illusts[0].id.toString();
await session.send(`成功获取到最新作品ID: ${latestId}
正在生成内容...`);
const messageContent = await handlePixivRequest(session, latestId, "middleware", true);
if (messageContent) await session.send(Array.isArray(messageContent) ? messageContent.join("\n") : messageContent);
else await session.send("内容生成失败。");
});
ctx.command("pixivcheck", "立即检查所有订阅并推送更新").action(async ({ session }) => {
if (!config.enableSubscription) return "订阅功能未启用。";
session.send("正在手动触发所有订阅的更新任务...");
return await checkAndPushUpdates(true);
});
ctx.middleware(async (session, next) => {
const match = session.content.match(/pixiv\.net\/(?:artworks|i)\/(\d+)/);
if (!match) return next();
if (session.content.startsWith(ctx.root.config.prefix[0] + "pid")) return next();
const id = match[1];
const result = await handlePixivRequest(session, id, "middleware");
if (result) await session.send(Array.isArray(result) ? result.join("\n") : result);
});
if (config.enableSubscription) {
logger.info("Pixiv 订阅功能已启动。");
ctx.on("ready", async () => {
if (config.debug) logger.info("[订阅] 正在初始化最新作品ID...");
if (!config.subscriptions || config.subscriptions.length === 0) return;
for (const sub of config.subscriptions) {
const record = await ctx.database.get("pixiv_last_artworks", { author_id: sub.uid });
if (record.length === 0) {
const illusts = await pixiv.getUserIllusts(sub.uid);
if (illusts && illusts.length > 0) {
await ctx.database.create("pixiv_last_artworks", { author_id: sub.uid, last_artwork_id: illusts[0].id.toString() });
}
}
}
if (config.debug) logger.info("[订阅] 初始化完成。");
});
const interval = setInterval(() => checkAndPushUpdates(false), config.updateInterval * import_koishi.Time.minute);
ctx.on("dispose", () => {
clearInterval(interval);
logger.info("Pixiv 订阅功能已关闭。");
});
}
}
__name(apply, "apply");
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Config,
apply,
inject,
name
});