UNPKG

karin-plugin-kkk

Version:

Karin 的「抖音」「B 站」视频解析/动态推送插件

1,508 lines 1.85 MB
import { i as __toESM } from "./rolldown-runtime.js"; import { $ as SiOppo, $n as zod_default, $t as MessageCircle, A as n, An as CircleAlert, At as Sparkles, B as RiPieChart2Fill, Bn as Chip, Bt as RotateCcw, C as BiImage, Cn as Clock, Ct as TriangleAlert, D as AiOutlineVideoCamera, Dn as CircleEllipsis, Dt as Star, E as AiFillStar, En as CircleFadingArrowUp, Et as Sun, F as RiHeart3Fill, Fn as Box, Ft as Share2, G as RiTiktokFill, Gn as require_react, Gt as Puzzle, H as RiStarFill, Hn as clsx, Ht as Radio, I as RiHeart3Line, In as Bot, It as Settings2, J as RiVerifiedBadgeFill, Jn as require_jpeg_js, Jt as Pencil, K as RiTrophyFill, Kn as require_png, Kt as Plus, L as RiHeartLine, Ln as Bookmark, Lt as Search, M as RiArrowRightFill, Mn as ChartColumn, Mt as ShoppingBag, N as RiGroupLine, Nn as Camera, Nt as Shield, O as m, On as CircleCheck, Ot as Square, P as RiHashtag, Pn as Calendar, Pt as ShieldCheck, Q as SiSamsung, Qn as Xhshow, Qt as Monitor, R as RiLiveLine, Rn as BellRing, Rt as ScanLine, S as FaUserGroup, Sn as Code, St as Upload, T as AiFillPushpin, Tn as CircleQuestionMark, Tt as Terminal, U as RiStarLine, Un as require_jsx_runtime, Ut as Quote, V as RiShareForwardFill, Vn as Button, Vt as RefreshCw, W as RiThumbUpFill, Wn as require_server_node, Wt as QrCode, X as SiXiaomi, Xn as require_protobufjs, Xt as Music, Y as RiVideoLine, Yn as require_heic_decode, Yt as Palette, Z as SiVivo, Zn as Chalk, Zt as Moon, _ as MdLocationOn, _n as Download, _t as Video, a as purify, an as Info, at as SiBilibili, b as FaMusic, bn as CornerDownLeft, bt as User, c as VictoryLine, cn as Hash, ct as zhCN, d as VictoryLabel, dn as Gamepad2, dt as formatDistanceToNow, en as Menu, et as SiOneplus, f as VictoryTheme, fn as FileText, ft as format, g as MdLightbulbOutline, gn as ExternalLink, gt as WandSparkles, h as MdInfoOutline, hn as EyeOff, ht as X, i as Window, in as LayoutTemplate, it as SiGithub, j as Markdown, jn as Check, jt as Smartphone, k as a, kn as CircleCheckBig, kt as SquarePen, l as VictoryChart, ln as GitBranch, lt as parse, m as MdFitScreen, mn as Eye, mt as Zap, n as require_lib, nn as MapPin, nt as SiHonor, o as VictoryScatter, on as Image$1, ot as SiApple, p as rehypeHighlight, pn as FilePlay, pt as differenceInSeconds, q as RiUserFollowLine, qn as require_jsQR, qt as Play, r as require_qr_code_styling, rn as LoaderCircle, rt as SiGooglephotos, s as VictoryPie, sn as Heart, st as SiAnthropic, t as createProxyMiddleware, tn as Maximize, tt as SiHuawei, u as VictoryAxis, un as Gift, ut as fromUnixTime, v as MdSchedule, vn as Crown, vt as Users, w as AiFillHeart, wn as Clapperboard, wt as Trash2, x as FaTiktok, xn as Copy, xt as UserPlus, y as FaCommentDots, yn as Cpu, yt as UsersRound, z as RiMessage3Fill, zn as ArrowDownToLine, zt as Save } from "./vendor.js"; import "node:module"; import fs from "node:fs"; import path, { resolve } from "node:path"; import URL$2, { fileURLToPath } from "node:url"; import os, { platform } from "node:os"; import karin$1, { BOT_CONNECT, app, authMiddleware, checkPkgUpdate, checkPort, common, components, config, copyConfigSync, createBadRequestResponse, createNotFoundResponse, createServerErrorResponse, createSuccessResponse, db, defineConfig, ffmpeg, ffprobe, filesByExt, getBot, hooks, karin, karinPathHtml, karinPathTemp, logger, logger as logger$1, logs, mkdirSync, parseChangelog, range, render, requireFileSync, restart, segment, updatePkg, watch } from "node-karin"; import _ from "node-karin/lodash"; import { EventEmitter } from "node:events"; import crypto from "node:crypto"; import axios, { AxiosError } from "node-karin/axios"; import express from "node-karin/express"; import { karinPathBase, karinPathTemp as karinPathTemp$1 } from "node-karin/root"; import sqlite3 from "node-karin/sqlite3"; import YAML from "node-karin/yaml"; import util from "node:util"; import { Transform } from "node:stream"; import { pipeline } from "node:stream/promises"; import { embedWatermarkToPngBytes } from "@ikenxuan/watermark"; import { snapka } from "@karinjs/plugin-puppeteer"; import { newInjectedPage } from "fingerprint-injector"; //#region src/index.ts globalThis.__kkkLoadStart ??= process.hrtime.bigint(); import("./setup.js"); //#endregion //#region src/root.ts var resolvePluginRoot = (startUrl) => { let dir = path.dirname(startUrl); for (let i = 0; i < 8; i++) { const pkgPath = path.join(dir, "package.json"); if (fs.existsSync(pkgPath)) return dir; const parent = path.dirname(dir); if (parent === dir) break; dir = parent; } return path.resolve(startUrl, "../.."); }; var pluginPath = resolvePluginRoot(fileURLToPath(import.meta.url)); var pkg = JSON.parse(fs.readFileSync(path.join(pluginPath, "package.json"), "utf-8")); var Root = { pluginName: pkg.name, pluginVersion: pkg.version, pluginPath, karinVersion: process.env.KARIN_VERSION, pkg }; //#endregion //#region ../amagi/packages/core/src/utils/deprecation.ts /** * 废弃 API 注册表 * 存储所有已注册的废弃 API 配置 */ var deprecatedApis = /* @__PURE__ */ new Map(); /** * 注册一个废弃的 API * * 将 API 添加到废弃注册表中,后续可通过 checkDeprecation 检查 * * @param config - 废弃配置对象 * * @example * ```typescript * registerDeprecatedApi({ * name: 'getDouyinData', * deprecatedIn: '6.0.0', * removedIn: '7.0.0', * replacement: 'douyinFetcher', * throwError: true * }) * ``` */ function registerDeprecatedApi(config) { deprecatedApis.set(config.name, config); } /** * 检查 API 是否已废弃并进行相应处理 * * 如果 API 已注册为废弃,根据配置决定是打印警告还是抛出错误 * * @param apiName - 要检查的 API 名称 * @throws {DeprecatedApiError} 如果 API 已废弃且配置为抛出错误 * * @example * ```typescript * // 在函数开头调用检查 * function getDouyinData(options) { * checkDeprecation('getDouyinData') * // ... * } * ``` */ function checkDeprecation(apiName) { const config = deprecatedApis.get(apiName); if (!config) return; const message = buildDeprecationMessage(config); if (config.throwError) throw new DeprecatedApiError(message, config); else console.warn(message); } /** * 根据配置构建废弃提示消息 * * @param config - 废弃配置 * @returns 格式化的废弃提示消息字符串 */ function buildDeprecationMessage(config) { const lines = [`[DEPRECATED] "${config.name}" 已在 v${config.deprecatedIn} 版本废弃。`]; if (config.replacement) lines.push(`请使用 "${config.replacement}" 替代。`); else lines.push("此接口已被上游删除,无法继续使用,无可用替代方案。"); if (config.removedIn) lines.push(`此 API 将在 v${config.removedIn} 版本移除。`); if (config.migrationGuide) lines.push(`迁移指南: ${config.migrationGuide}`); return lines.join("\n"); } /** * 废弃 API 调用错误类 * * 当调用已废弃且配置为抛出错误的 API 时抛出此错误 * 包含完整的废弃配置信息,便于调试和迁移 */ var DeprecatedApiError = class DeprecatedApiError extends Error { /** 废弃配置信息,包含替代方案等详细信息 */ config; /** * 创建废弃 API 错误实例 * * @param message - 错误消息 * @param config - 废弃配置对象 */ constructor(message, config) { super(message); this.name = "DeprecatedApiError"; this.config = config; Error.captureStackTrace?.(this, DeprecatedApiError); } }; registerDeprecatedApi({ name: "getDouyinData", deprecatedIn: "6.0.0", removedIn: "7.0.0", replacement: "douyinFetcher 或 client.douyin.fetcher", migrationGuide: "https://github.com/ikenxuan/amagi/blob/main/packages/core/MIGRATION-v6.md", throwError: true }); registerDeprecatedApi({ name: "getBilibiliData", deprecatedIn: "6.0.0", removedIn: "7.0.0", replacement: "bilibiliFetcher 或 client.bilibili.fetcher", migrationGuide: "https://github.com/ikenxuan/amagi/blob/main/packages/core/MIGRATION-v6.md", throwError: true }); registerDeprecatedApi({ name: "getKuaishouData", deprecatedIn: "6.0.0", removedIn: "7.0.0", replacement: "kuaishouFetcher 或 client.kuaishou.fetcher", migrationGuide: "https://github.com/ikenxuan/amagi/blob/main/packages/core/MIGRATION-v6.md", throwError: true }); registerDeprecatedApi({ name: "getXiaohongshuData", deprecatedIn: "6.0.0", removedIn: "7.0.0", replacement: "xiaohongshuFetcher 或 client.xiaohongshu.fetcher", migrationGuide: "https://github.com/ikenxuan/amagi/blob/main/packages/core/MIGRATION-v6.md", throwError: true }); [ { name: "单个视频作品数据", replacement: "fetchVideoInfo" }, { name: "单个视频下载信息数据", replacement: "fetchVideoStreamUrl" }, { name: "评论数据", replacement: "fetchComments" }, { name: "指定评论的回复", replacement: "fetchCommentReplies" }, { name: "用户主页数据", replacement: "fetchUserCard" }, { name: "用户主页动态列表数据", replacement: "fetchUserDynamicList" }, { name: "用户空间详细信息", replacement: "fetchUserSpaceInfo" }, { name: "获取UP主总播放量", replacement: "fetchUploaderTotalViews" }, { name: "Emoji数据", replacement: "fetchEmojiList" }, { name: "番剧基本信息数据", replacement: "fetchBangumiInfo" }, { name: "番剧下载信息数据", replacement: "fetchBangumiStreamUrl" }, { name: "动态详情数据", replacement: "fetchDynamicDetail" }, { name: "直播间信息", replacement: "fetchLiveRoomInfo" }, { name: "直播间初始化信息", replacement: "fetchLiveRoomInitInfo" }, { name: "登录基本信息", replacement: "fetchLoginStatus" }, { name: "申请二维码", replacement: "requestLoginQrcode" }, { name: "二维码状态", replacement: "checkQrcodeStatus" }, { name: "AV转BV", replacement: "convertAvToBv" }, { name: "BV转AV", replacement: "convertBvToAv" }, { name: "专栏正文内容", replacement: "fetchArticleContent" }, { name: "专栏显示卡片信息", replacement: "fetchArticleCards" }, { name: "专栏文章基本信息", replacement: "fetchArticleInfo" }, { name: "文集基本信息", replacement: "fetchArticleListInfo" }, { name: "实时弹幕", replacement: "fetchVideoDanmaku" }, { name: "从_v_voucher_申请_captcha", replacement: "requestCaptchaFromVoucher" }, { name: "验证验证码结果", replacement: "validateCaptchaResult" }, { name: "视频作品数据", replacement: "fetchVideoWork" }, { name: "图集作品数据", replacement: "fetchImageAlbumWork" }, { name: "合辑作品数据", replacement: "fetchSlidesWork" }, { name: "文字作品数据", replacement: "fetchTextWork" }, { name: "聚合解析", replacement: "parseWork" }, { name: "指定评论回复数据", replacement: "fetchCommentReplies" }, { name: "用户主页视频列表数据", replacement: "fetchUserVideoList" }, { name: "热点词数据", replacement: "fetchSuggestWords" }, { name: "搜索数据", replacement: "searchContent" }, { name: "音乐数据", replacement: "fetchMusicInfo" }, { name: "直播间信息数据", replacement: "fetchLiveRoomInfo" }, { name: "申请二维码数据", replacement: "requestLoginQrcode" }, { name: "动态表情数据", replacement: "fetchDynamicEmojiList" }, { name: "弹幕数据", replacement: "fetchDanmakuList" }, { name: "单个视频作品数据", replacement: "fetchVideoWork" }, { name: "首页推荐数据", replacement: "fetchHomeFeed" }, { name: "单个笔记数据", replacement: "fetchNoteDetail" }, { name: "用户数据", replacement: "fetchUserProfile" }, { name: "用户笔记数据", replacement: "fetchUserNoteList" }, { name: "表情列表", replacement: "fetchEmojiList" }, { name: "搜索笔记", replacement: "searchNotes" } ].forEach(({ name, replacement }) => { registerDeprecatedApi({ name: `methodType: '${name}'`, deprecatedIn: "6.0.0", removedIn: "7.0.0", replacement: `fetcher.${replacement}()`, throwError: true }); }); registerDeprecatedApi({ name: `methodType: '动态卡片数据'`, deprecatedIn: "6.0.0", removedIn: "7.0.0", migrationGuide: "https://amagi-docs.vercel.app/docs/changelog/6.1.3", throwError: false }); registerDeprecatedApi({ name: "fetchDynamicCard", deprecatedIn: "6.1.3", removedIn: "7.0.0", migrationGuide: "https://amagi-docs.vercel.app/docs/changelog/6.1.3", throwError: false }); //#endregion //#region ../amagi/packages/core/src/model/DataFetchers.ts /** * 数据获取器模块 (已废弃) * * 此模块中的 getXXXData 函数已在 v6 版本废弃并移除 * 请使用新的 fetcher API 替代 * * @module model/DataFetchers * @deprecated v6 已废弃,请使用 fetcher API 替代 */ /** * 获取抖音数据 * * @deprecated v6 已废弃,请使用 douyinFetcher 或 client.douyin.fetcher 替代 * @throws {DeprecatedApiError} 调用时抛出废弃错误 * * @example * ```typescript * // 旧用法 (已废弃,会抛出错误) * const data = await getDouyinData('videoWork', { aweme_id: '123' }, cookie) * * // 新用法 * import { douyinFetcher } from '@ikenxuan/amagi' * const data = await douyinFetcher.fetchVideoWork({ aweme_id: '123' }, cookie) * * // 或使用客户端实例 * const client = createAmagiClient({ cookies: { douyin: cookie } }) * const data = await client.douyin.fetcher.fetchVideoWork({ aweme_id: '123' }) * ``` */ function getDouyinData(..._args) { checkDeprecation("getDouyinData"); throw new Error("getDouyinData 已废弃"); } /** * 获取B站数据 * * @deprecated v6 已废弃,请使用 bilibiliFetcher 或 client.bilibili.fetcher 替代 * @throws {DeprecatedApiError} 调用时抛出废弃错误 * * @example * ```typescript * // 旧用法 (已废弃,会抛出错误) * const data = await getBilibiliData('videoInfo', { bvid: 'BV123' }, cookie) * * // 新用法 * import { bilibiliFetcher } from '@ikenxuan/amagi' * const data = await bilibiliFetcher.fetchVideoInfo({ bvid: 'BV123' }, cookie) * * // 或使用客户端实例 * const client = createAmagiClient({ cookies: { bilibili: cookie } }) * const data = await client.bilibili.fetcher.fetchVideoInfo({ bvid: 'BV123' }) * ``` */ function getBilibiliData(..._args) { checkDeprecation("getBilibiliData"); throw new Error("getBilibiliData 已废弃"); } /** * 获取快手数据 * * @deprecated v6 已废弃,请使用 kuaishouFetcher 或 client.kuaishou.fetcher 替代 * @throws {DeprecatedApiError} 调用时抛出废弃错误 * * @example * ```typescript * // 旧用法 (已废弃,会抛出错误) * const data = await getKuaishouData('videoWork', { photoId: '123' }, cookie) * * // 新用法 * import { kuaishouFetcher } from '@ikenxuan/amagi' * const data = await kuaishouFetcher.fetchVideoWork({ photoId: '123' }, cookie) * * // 或使用客户端实例 * const client = createAmagiClient({ cookies: { kuaishou: cookie } }) * const data = await client.kuaishou.fetcher.fetchVideoWork({ photoId: '123' }) * ``` */ function getKuaishouData(..._args) { checkDeprecation("getKuaishouData"); throw new Error("getKuaishouData 已废弃"); } /** * 获取小红书数据 * * @deprecated v6 已废弃,请使用 xiaohongshuFetcher 或 client.xiaohongshu.fetcher 替代 * @throws {DeprecatedApiError} 调用时抛出废弃错误 * * @example * ```typescript * // 旧用法 (已废弃,会抛出错误) * const data = await getXiaohongshuData('noteDetail', { note_id: '123' }, cookie) * * // 新用法 * import { xiaohongshuFetcher } from '@ikenxuan/amagi' * const data = await xiaohongshuFetcher.fetchNoteDetail({ note_id: '123' }, cookie) * * // 或使用客户端实例 * const client = createAmagiClient({ cookies: { xiaohongshu: cookie } }) * const data = await client.xiaohongshu.fetcher.fetchNoteDetail({ note_id: '123' }) * ``` */ function getXiaohongshuData(..._args) { checkDeprecation("getXiaohongshuData"); throw new Error("getXiaohongshuData 已废弃"); } //#endregion //#region ../amagi/packages/core/src/platform/bilibili/API.ts /** * B站 API URL 构建类 * * 提供所有 B站 API 的 URL 构建方法 */ var BilibiliAPI = class { /** 获取登录基本信息 */ getLoginStatus() { return "https://api.bilibili.com/x/web-interface/nav"; } /** 获取视频详细信息 */ getVideoInfo(data) { return `https://api.bilibili.com/x/web-interface/view?bvid=${data.bvid}`; } /** 获取视频流信息 */ getVideoStream(data) { return `https://api.bilibili.com/x/player/playurl?avid=${data.avid}&cid=${data.cid}`; } /** * 获取评论区明细 * @see https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/comment/readme.md#评论区类型代码 */ getComments(data) { const params = new URLSearchParams({ oid: data.oid.toString(), type: data.type.toString(), mode: (data.mode ?? 3).toString(), plat: "1", seek_rpid: "", web_location: "1315875" }); if (data.pagination_str) params.append("pagination_str", JSON.stringify({ offset: data.pagination_str })); else params.append("pagination_str", JSON.stringify({ offset: "" })); return `https://api.bilibili.com/x/v2/reply/wbi/main?${params.toString()}`; } /** 获取评论区状态 */ getCommentStatus(data) { return `https://api.bilibili.com/x/v2/reply/subject/description?type=${data.type}&oid=${data.oid}`; } /** 获取指定评论的回复 */ getCommentReplies(data) { return `https://api.bilibili.com/x/v2/reply/reply?type=${data.type}&oid=${data.oid}&root=${data.root}&ps=${data.number}`; } /** 获取表情列表 */ getEmojiList() { return "https://api.bilibili.com/x/emote/user/panel/web?business=reply&web_location=0.0"; } /** 获取番剧明细 */ getBangumiInfo(data) { if (data.ep_id) return `https://api.bilibili.com/pgc/view/web/season?ep_id=${data.ep_id}`; else if (data.season_id) return `https://api.bilibili.com/pgc/view/web/season?season_id=${data.season_id}`; else throw new Error("Missing required parameter: ep_id or season_id"); } /** 获取番剧视频流信息 */ getBangumiStream(data) { return `https://api.bilibili.com/pgc/player/web/playurl?cid=${data.cid}&ep_id=${data.ep_id}`; } /** 获取用户空间动态 */ getUserDynamicList(data) { return `https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/space?${new URLSearchParams({ host_mid: data.host_mid.toString(), offset: "", platform: "web", features: "itemOpusStyle,listOnlyfans,opusBigCover,onlyfansVote,forwardListHidden,decorationCard,commentsNewVersion,onlyfansAssetsV2,ugcDelete,onlyfansQaCard,avatarAutoTheme,sunflowerStyle,eva3CardOpus,eva3CardVideo,eva3CardComment" }).toString()}`; } /** 获取动态详情 */ getDynamicDetail(data) { return `https://api.bilibili.com/x/polymer/web-dynamic/v1/detail?id=${data.dynamic_id}&features=itemOpusStyle,opusBigCover,onlyfansVote,endFooterHidden,decorationCard,onlyfansAssetsV2,ugcDelete,onlyfansQaCard,editable,opusPrivateVisible,avatarAutoTheme`; } /** * 获取动态卡片信息 * * @deprecated B站官方已于 `2025-08-09` 删除原 `dynamic_svr` 接口,该接口已停用。 * 调用将返回错误信息,请使用 {@link getDynamicDetail} 替代。 */ getDynamicCard(data) { return this.getDynamicDetail(data); } /** 获取用户名片信息 */ getUserCard(data) { return `https://api.bilibili.com/x/web-interface/card?mid=${data.host_mid}&photo=true`; } /** 获取直播间信息 */ getLiveRoomInfo(data) { return `https://api.live.bilibili.com/room/v1/Room/get_info?room_id=${data.room_id}`; } /** 获取直播间初始化信息 */ getLiveRoomInit(data) { return `https://api.live.bilibili.com/room/v1/Room/room_init?id=${data.room_id}`; } /** 申请登录二维码 */ getLoginQrcode() { return "https://passport.bilibili.com/x/passport-login/web/qrcode/generate"; } /** 查询二维码状态 */ getQrcodeStatus(data) { return `https://passport.bilibili.com/x/passport-login/web/qrcode/poll?qrcode_key=${data.qrcode_key}`; } /** 获取UP主总播放量 */ getUploaderTotalViews(data) { return `https://api.bilibili.com/x/space/upstat?mid=${data.host_mid}`; } /** 获取专栏正文内容 */ getArticleContent(data) { return `https://api.bilibili.com/x/article/view?id=${data.id}`; } /** 获取专栏显示卡片信息 */ getArticleCards(data) { return `https://api.bilibili.com/x/article/cards?ids=${Array.isArray(data.ids) ? data.ids.join(",") : data.ids}`; } /** 获取专栏文章基本信息 */ getArticleInfo(data) { return `https://api.bilibili.com/x/article/viewinfo?id=${data.id}`; } /** 获取文集基本信息 */ getArticleListInfo(data) { return `https://api.bilibili.com/x/article/list/web/articles?id=${data.id}`; } /** 获取用户空间详细信息 */ getUserSpaceInfo(data) { return `https://api.bilibili.com/x/space/wbi/acc/info?mid=${data.host_mid}`; } /** 从 v_voucher 申请验证码 */ getCaptchaFromVoucher(data) { return { Url: "https://api.bilibili.com/x/gaia-vgate/v1/register", Body: { ...data.csrf !== void 0 && { csrf: data.csrf }, v_voucher: data.v_voucher } }; } /** 验证验证码结果 */ validateCaptcha(data) { return { Url: "https://api.bilibili.com/x/gaia-vgate/v1/validate", Body: { challenge: data.challenge, token: data.token, validate: data.validate, seccode: data.seccode, ...data.csrf !== void 0 && { csrf: data.csrf } } }; } /** * 获取实时弹幕(web端 protobuf 接口) * @see https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/danmaku/danmaku_proto.md */ getVideoDanmaku(data) { return `https://api.bilibili.com/x/v2/dm/web/seg.so?${new URLSearchParams({ type: "1", oid: data.cid.toString(), segment_index: (data.segment_index ?? 1).toString() }).toString()}`; } }; /** B站 API URL 构建器实例 */ var bilibiliApiUrls = new BilibiliAPI(); //#endregion //#region ../amagi/packages/core/src/platform/bilibili/BilibiliApi.ts /** * 创建废弃的 API 存根函数 */ var createDeprecatedStub$3 = (methodName) => { return (..._args) => { checkDeprecation("getBilibiliData"); throw new Error(`bilibili.${methodName} 已废弃,请使用 bilibiliFetcher 替代`); }; }; /** * B站相关 API 的命名空间。 * * @deprecated v6 已废弃,请使用 bilibiliFetcher 或 client.bilibili.fetcher 替代 */ var bilibili$1 = { /** @deprecated 请使用 bilibiliFetcher.fetchVideoInfo 替代 */ getVideoInfo: createDeprecatedStub$3("getVideoInfo"), /** @deprecated 请使用 bilibiliFetcher.fetchVideoStreamUrl 替代 */ getVideoStream: createDeprecatedStub$3("getVideoStream"), /** @deprecated 请使用 bilibiliFetcher.fetchComments 替代 */ getComments: createDeprecatedStub$3("getComments"), /** @deprecated 请使用 bilibiliFetcher.fetchCommentReplies 替代 */ getCommentReply: createDeprecatedStub$3("getCommentReply"), /** @deprecated 请使用 bilibiliFetcher.fetchUserCard 替代 */ getUserProfile: createDeprecatedStub$3("getUserProfile"), /** @deprecated 请使用 bilibiliFetcher.fetchUserDynamicList 替代 */ getUserDynamic: createDeprecatedStub$3("getUserDynamic"), /** @deprecated 请使用 bilibiliFetcher.fetchEmojiList 替代 */ getEmojiList: createDeprecatedStub$3("getEmojiList"), /** @deprecated 请使用 bilibiliFetcher.fetchBangumiInfo 替代 */ getBangumiInfo: createDeprecatedStub$3("getBangumiInfo"), /** @deprecated 请使用 bilibiliFetcher.fetchBangumiStreamUrl 替代 */ getBangumiStream: createDeprecatedStub$3("getBangumiStream"), /** @deprecated 请使用 bilibiliFetcher.fetchDynamicDetail 替代 */ getDynamicInfo: createDeprecatedStub$3("getDynamicInfo"), /** @deprecated 请使用 bilibiliFetcher.fetchDynamicCard 替代 */ getDynamicCard: createDeprecatedStub$3("getDynamicCard"), /** @deprecated 请使用 bilibiliFetcher.fetchLiveRoomInfo 替代 */ getLiveRoomDetail: createDeprecatedStub$3("getLiveRoomDetail"), /** @deprecated 请使用 bilibiliFetcher.fetchLiveRoomInitInfo 替代 */ getLiveRoomInitInfo: createDeprecatedStub$3("getLiveRoomInitInfo"), /** @deprecated 请使用 bilibiliFetcher.fetchLoginStatus 替代 */ getLoginBasicInfo: createDeprecatedStub$3("getLoginBasicInfo"), /** @deprecated 请使用 bilibiliFetcher.requestLoginQrcode 替代 */ getLoginQrcode: createDeprecatedStub$3("getLoginQrcode"), /** @deprecated 请使用 bilibiliFetcher.checkQrcodeStatus 替代 */ checkQrcodeStatus: createDeprecatedStub$3("checkQrcodeStatus"), /** @deprecated 请使用 bilibiliFetcher.fetchUploaderTotalViews 替代 */ getUserTotalPlayCount: createDeprecatedStub$3("getUserTotalPlayCount"), /** @deprecated 请使用 bilibiliFetcher.convertAvToBv 替代 */ convertAvToBv: createDeprecatedStub$3("convertAvToBv"), /** @deprecated 请使用 bilibiliFetcher.convertBvToAv 替代 */ convertBvToAv: createDeprecatedStub$3("convertBvToAv"), /** @deprecated 请使用 bilibiliFetcher.fetchArticleContent 替代 */ getArticleContent: createDeprecatedStub$3("getArticleContent"), /** @deprecated 请使用 bilibiliFetcher.fetchArticleCards 替代 */ getArticleCard: createDeprecatedStub$3("getArticleCard"), /** @deprecated 请使用 bilibiliFetcher.fetchArticleInfo 替代 */ getArticleInfo: createDeprecatedStub$3("getArticleInfo"), /** @deprecated 请使用 bilibiliFetcher.fetchArticleListInfo 替代 */ getColumnInfo: createDeprecatedStub$3("getColumnInfo"), /** @deprecated 请使用 bilibiliFetcher.fetchUserSpaceInfo 替代 */ getUserProfileDetail: createDeprecatedStub$3("getUserProfileDetail"), /** @deprecated 请使用 bilibiliFetcher.requestCaptchaFromVoucher 替代 */ applyVoucherCaptcha: createDeprecatedStub$3("applyVoucherCaptcha"), /** @deprecated 请使用 bilibiliFetcher.validateCaptchaResult 替代 */ validateCaptcha: createDeprecatedStub$3("validateCaptcha"), /** @deprecated 请使用 bilibiliFetcher.fetchVideoDanmaku 替代 */ getDanmaku: createDeprecatedStub$3("getDanmaku") }; /** * 创建绑定了cookie的B站API对象 * * @deprecated v6 已废弃,请使用 createBoundBilibiliFetcher 替代 */ var createBoundBilibiliApi = (_cookie, _requestConfig) => { return { ...bilibili$1 }; }; //#endregion //#region ../amagi/packages/core/src/model/events.ts /** * Amagi 事件系统 * @module model/events * @description 提供类型安全的事件发射器,用于日志、HTTP、网络和 API 事件的监听与触发 */ /** * 类型安全的事件发射器 * @description 继承自 Node.js EventEmitter,提供泛型约束确保事件名称与数据类型匹配 */ var TypedEventEmitter = class extends EventEmitter { /** * 触发事件 * @param event - 事件名称 * @param data - 事件数据 * @returns 是否有监听器处理了该事件 */ emit(event, data) { return super.emit(event, data); } /** * 注册事件监听器 * @param event - 事件名称 * @param listener - 事件处理函数 * @returns this (支持链式调用) */ on(event, listener) { return super.on(event, listener); } /** * 注册一次性事件监听器 * @param event - 事件名称 * @param listener - 事件处理函数 (只触发一次) * @returns this (支持链式调用) */ once(event, listener) { return super.once(event, listener); } /** * 移除事件监听器 * @param event - 事件名称 * @param listener - 要移除的事件处理函数 * @returns this (支持链式调用) */ off(event, listener) { return super.off(event, listener); } }; /** * Amagi 全局事件发射器实例 * @description 单例模式,所有模块共享同一个事件总线 * @example * ```typescript * import { amagiEvents } from 'amagi/model/events' * * // 监听 API 成功事件 * amagiEvents.on('api:success', (data) => { * console.log(`[${data.platform}] ${data.methodType} 耗时 ${data.duration}ms`) * }) * ``` */ var amagiEvents = new TypedEventEmitter(); /** * 发射日志事件 * @param level - 日志级别 * @param message - 日志消息 * @param args - 附加参数 */ var emitLog = (level, message, ...args) => { amagiEvents.emit(`log:${level}`, { level, message, args: args.length > 0 ? args : void 0, timestamp: /* @__PURE__ */ new Date() }); }; /** * 发射 HTTP 请求事件 * @param data - 请求数据 (不含 timestamp) */ var emitHttpRequest = (data) => { amagiEvents.emit("http:request", { ...data, timestamp: /* @__PURE__ */ new Date() }); }; /** * 发射 HTTP 响应事件 * @param data - 响应数据 (不含 timestamp) */ var emitHttpResponse = (data) => { amagiEvents.emit("http:response", { ...data, timestamp: /* @__PURE__ */ new Date() }); }; /** * 发射网络重试事件 * @param data - 重试数据 (不含 timestamp) */ var emitNetworkRetry = (data) => { amagiEvents.emit("network:retry", { ...data, timestamp: /* @__PURE__ */ new Date() }); }; /** * 发射网络错误事件 * @param data - 错误数据 (不含 timestamp) */ var emitNetworkError = (data) => { amagiEvents.emit("network:error", { ...data, timestamp: /* @__PURE__ */ new Date() }); }; /** * 发射 API 成功事件 * @param data - 成功数据 (不含 timestamp) */ var emitApiSuccess = (data) => { amagiEvents.emit("api:success", { ...data, timestamp: /* @__PURE__ */ new Date() }); }; /** * 发射 API 错误事件 * @param data - 错误数据 (不含 timestamp) */ var emitApiError = (data) => { amagiEvents.emit("api:error", { ...data, timestamp: /* @__PURE__ */ new Date() }); }; /** * 发射 info 级别日志 * @param message - 日志消息 * @param args - 附加参数 */ var emitLogInfo = (message, ...args) => { emitLog("info", message, ...args); }; /** * 发射 warn 级别日志 * @param message - 日志消息 * @param args - 附加参数 */ var emitLogWarn = (message, ...args) => { emitLog("warn", message, ...args); }; /** * 发射 error 级别日志 * @param message - 日志消息 * @param args - 附加参数 */ var emitLogError = (message, ...args) => { emitLog("error", message, ...args); }; /** * 发射 debug 级别日志 * @param message - 日志消息 * @param args - 附加参数 */ var emitLogDebug = (message, ...args) => { emitLog("debug", message, ...args); }; /** * 发射 mark 级别日志 (用于重要标记) * @param message - 日志消息 * @param args - 附加参数 */ var emitLogMark = (message, ...args) => { emitLog("mark", message, ...args); }; //#endregion //#region ../amagi/packages/core/src/validation/utils.ts function smartNumber(errorMessage, minValue = 1, isInteger = false) { if (isInteger) return zod_default.coerce.number({ error: errorMessage }).int({ error: `${errorMessage.replace("不能为空", "")}必须是整数,不能包含小数` }).min(minValue, { error: `${errorMessage.replace("不能为空", "")}必须大于等于${minValue}` }); else return zod_default.coerce.number({ error: errorMessage }).min(minValue, { error: `${errorMessage.replace("不能为空", "")}必须大于等于${minValue}` }); } /** * 智能正整数转换器 - 专门用于正整数类型的转换 * @param errorMessage - 自定义错误信息 * @returns Zod正整数验证器 */ var smartPositiveInteger = (errorMessage) => { return smartNumber(errorMessage, 1, true); }; /** * 从页面HTML中提取用户信息 * @param html - 包含用户页面HTML的字符串 * @returns 提取到的用户信息对象或null */ var extractCreatorInfoFromHtml = (html) => { const match = html.match(/<script>window\.__INITIAL_STATE__=(.+)<\/script>/m); if (!match) return null; try { const jsonStr = match[1].replace(/:undefined/g, ":null"); return JSON.parse(jsonStr)?.user?.userPageData ?? null; } catch (error) { console.error("解析用户信息失败:", error); return null; } }; //#endregion //#region ../amagi/packages/core/src/validation/bilibili.ts /** 视频信息参数验证 */ var BilibiliVideoParamsSchema = zod_default.object({ methodType: zod_default.literal("videoInfo", { error: "方法类型必须是\"videoInfo\"" }), bvid: zod_default.string({ error: "BVID必须是字符串" }).min(1, { error: "BVID不能为空" }) }); /** 视频流参数验证 */ var BilibiliVideoDownloadParamsSchema = zod_default.object({ methodType: zod_default.literal("videoStream", { error: "方法类型必须是\"videoStream\"" }), avid: smartNumber("AVID不能为空", 1, true), cid: smartNumber("CID不能为空", 1, true) }); /** 评论参数验证 */ var BilibiliCommentParamsSchema = zod_default.object({ methodType: zod_default.literal("comments", { error: "方法类型必须是\"comments\"" }), oid: zod_default.string({ error: "OID必须是字符串" }).min(1, { error: "OID不能为空" }), type: smartNumber("评论类型不能为空", 1, true).refine((val) => [ 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 33 ].includes(val), { error: "无效的评论区类型" }), number: zod_default.coerce.number({ error: "评论数量必须是数字" }).int({ error: "评论数量必须是整数" }).positive({ error: "评论数量必须是正数" }).default(20).optional(), pn: zod_default.coerce.number({ error: "页码必须是数字" }).int({ error: "页码必须是整数" }).positive({ error: "页码必须是正数" }).default(1).optional() }); /** 评论回复参数验证 */ var BilibiliCommentReplyParamsSchema = zod_default.object({ methodType: zod_default.literal("commentReplies", { error: "方法类型必须是\"commentReplies\"" }), oid: zod_default.string({ error: "OID必须是字符串" }).min(1, { error: "OID不能为空" }), type: smartNumber("评论类型不能为空", 1, true).refine((val) => [ 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 33 ].includes(val), { error: "无效的评论区类型" }), root: zod_default.string({ error: "根评论ID必须是字符串" }).min(1, { error: "根评论ID不能为空" }), number: zod_default.coerce.number({ error: "评论数量必须是数字" }).int({ error: "评论数量必须是整数" }).positive({ error: "评论数量必须是正数" }).default(20).optional(), pn: zod_default.coerce.number({ error: "页码必须是数字" }).int({ error: "页码必须是整数" }).positive({ error: "页码必须是正数" }).default(1).optional() }); /** 用户参数验证 */ var BilibiliUserParamsSchema = zod_default.object({ methodType: zod_default.enum([ "userCard", "userDynamicList", "uploaderTotalViews", "userSpaceInfo" ], { error: "方法类型必须是指定的枚举值之一" }), host_mid: smartNumber("UP主UID不能为空", 1, true) }); /** 表情参数验证 */ var BilibiliEmojiParamsSchema = zod_default.object({ methodType: zod_default.literal("emojiList", { error: "方法类型必须是\"emojiList\"" }) }); /** 番剧信息参数验证 */ var BilibiliBangumiInfoParamsSchema = zod_default.object({ methodType: zod_default.literal("bangumiInfo", { error: "方法类型必须是\"bangumiInfo\"" }), ep_id: zod_default.string({ error: "番剧EP ID必须是字符串" }).min(1, { error: "番剧EP ID不能为空" }).optional(), season_id: zod_default.string({ error: "番剧季度ID必须是字符串" }).optional() }).refine((data) => data.ep_id ?? data.season_id, { error: "ep_id 和 season_id 至少需要提供一个", path: ["ep_id"] }); /** 番剧流参数验证 */ var BilibiliBangumiStreamParamsSchema = zod_default.object({ methodType: zod_default.literal("bangumiStream", { error: "方法类型必须是\"bangumiStream\"" }), cid: smartNumber("CID不能为空", 1, true), ep_id: zod_default.string({ error: "番剧EP ID必须是字符串" }).min(1, { error: "番剧EP ID不能为空" }) }); /** 动态参数验证 */ var BilibiliDynamicParamsSchema = zod_default.object({ methodType: zod_default.enum(["dynamicDetail", "dynamicCard"], { error: "方法类型必须是\"dynamicDetail\"或\"dynamicCard\"" }), dynamic_id: zod_default.string({ error: "动态ID必须是字符串" }).min(1, { error: "动态ID不能为空" }) }); /** 直播间参数验证 */ var BilibiliLiveParamsSchema = zod_default.object({ methodType: zod_default.enum(["liveRoomInfo", "liveRoomInit"], { error: "方法类型必须是\"liveRoomInfo\"或\"liveRoomInit\"" }), room_id: zod_default.string({ error: "直播间ID必须是字符串" }).min(1, { error: "直播间ID不能为空" }) }); /** 登录状态参数验证 */ var BilibiliLoginParamsSchema = zod_default.object({ methodType: zod_default.literal("loginStatus", { error: "方法类型必须是\"loginStatus\"" }) }); /** 申请二维码参数验证 */ var BilibiliQrcodeParamsSchema = zod_default.object({ methodType: zod_default.literal("loginQrcode", { error: "方法类型必须是\"loginQrcode\"" }) }); /** 二维码状态参数验证 */ var BilibiliQrcodeStatusParamsSchema = zod_default.object({ methodType: zod_default.literal("qrcodeStatus", { error: "方法类型必须是\"qrcodeStatus\"" }), qrcode_key: zod_default.string({ error: "二维码key必须是字符串" }).min(1, { error: "二维码key不能为空" }) }); /** AV转BV参数验证 */ var BilibiliAv2BvParamsSchema = zod_default.object({ methodType: zod_default.literal("avToBv", { error: "方法类型必须是\"avToBv\"" }), avid: zod_default.coerce.number({ error: "AVID必须是数字" }).int({ error: "AVID必须是整数" }).positive({ error: "AVID必须是正数" }) }); /** BV转AV参数验证 */ var BilibiliBv2AvParamsSchema = zod_default.object({ methodType: zod_default.literal("bvToAv", { error: "方法类型必须是\"bvToAv\"" }), bvid: zod_default.string({ error: "BVID必须是字符串" }).min(1, { error: "BVID不能为空" }) }); /** 专栏内容参数验证 */ var BilibiliArticleParamsSchema = zod_default.object({ methodType: zod_default.literal("articleContent", { error: "方法类型必须是\"articleContent\"" }), id: zod_default.string({ error: "专栏ID必须是字符串" }).min(1, { error: "专栏ID不能为空" }) }); /** 专栏卡片参数验证 */ var BilibiliArticleCardParamsSchema = zod_default.object({ methodType: zod_default.literal("articleCards", { error: "方法类型必须是\"articleCards\"" }), ids: zod_default.union([zod_default.array(zod_default.string({ error: "被查询的 id 列表必须是字符串数组" })).min(1, { error: "被查询的 id 列表不能为空" }), zod_default.string({ error: "被查询的 id 列表必须是字符串" }).min(1, { error: "被查询的 id 列表不能为空" })]) }); /** 专栏信息参数验证 */ var BilibiliArticleInfoParamsSchema = zod_default.object({ methodType: zod_default.literal("articleInfo", { error: "方法类型必须是\"articleInfo\"" }), id: zod_default.string({ error: "专栏ID必须是字符串" }).min(1, { error: "专栏ID不能为空" }) }); /** 文集信息参数验证 */ var BilibiliColumnInfoParamsSchema = zod_default.object({ methodType: zod_default.literal("articleListInfo", { error: "方法类型必须是\"articleListInfo\"" }), id: zod_default.string({ error: "文集ID必须是字符串" }).min(1, { error: "文集ID不能为空" }) }); /** 验证码申请参数验证 */ var BilibiliApplyCaptchaParamsSchema = zod_default.object({ methodType: zod_default.literal("captchaFromVoucher", { error: "方法类型必须是\"captchaFromVoucher\"" }), csrf: zod_default.string({ error: "CSRF Token必须是字符串" }).optional(), v_voucher: zod_default.string({ error: "验证码ID必须是字符串" }).min(1, { error: "验证码ID不能为空" }) }); /** 验证码验证参数验证 */ var BilibiliValidateCaptchaParamsSchema = zod_default.object({ methodType: zod_default.literal("validateCaptcha", { error: "方法类型必须是\"validateCaptcha\"" }), csrf: zod_default.string({ error: "CSRF Token必须是字符串" }).optional(), challenge: zod_default.string({ error: "验证码challenge必须是字符串" }).min(1, { error: "验证码challenge不能为空" }), token: zod_default.string({ error: "验证码token必须是字符串" }).min(1, { error: "验证码token不能为空" }), validate: zod_default.string({ error: "验证码validate必须是字符串" }).min(1, { error: "验证码validate不能为空" }), seccode: zod_default.string({ error: "验证码seccode必须是字符串" }).min(1, { error: "验证码seccode不能为空" }) }); /** 弹幕参数验证 */ var BilibiliDanmakuParamsSchema = zod_default.object({ methodType: zod_default.literal("videoDanmaku", { error: "方法类型必须是\"videoDanmaku\"" }), cid: smartNumber("CID不能为空", 1, true), segment_index: zod_default.coerce.number({ error: "分段序号必须是数字" }).int({ error: "分段序号必须是整数" }).positive({ error: "分段序号必须是正数" }).default(1).optional() }); /** B站参数验证模式映射 */ var BilibiliValidationSchemas = { videoInfo: BilibiliVideoParamsSchema, videoStream: BilibiliVideoDownloadParamsSchema, comments: BilibiliCommentParamsSchema, commentReplies: BilibiliCommentReplyParamsSchema, userCard: BilibiliUserParamsSchema, userDynamicList: BilibiliUserParamsSchema, userSpaceInfo: BilibiliUserParamsSchema, emojiList: BilibiliEmojiParamsSchema, bangumiInfo: BilibiliBangumiInfoParamsSchema, bangumiStream: BilibiliBangumiStreamParamsSchema, dynamicDetail: BilibiliDynamicParamsSchema, dynamicCard: BilibiliDynamicParamsSchema, liveRoomInfo: BilibiliLiveParamsSchema, liveRoomInit: BilibiliLiveParamsSchema, loginStatus: BilibiliLoginParamsSchema, loginQrcode: BilibiliQrcodeParamsSchema, qrcodeStatus: BilibiliQrcodeStatusParamsSchema, uploaderTotalViews: BilibiliUserParamsSchema, avToBv: BilibiliAv2BvParamsSchema, bvToAv: BilibiliBv2AvParamsSchema, articleContent: BilibiliArticleParamsSchema, articleCards: BilibiliArticleCardParamsSchema, articleInfo: BilibiliArticleInfoParamsSchema, articleListInfo: BilibiliColumnInfoParamsSchema, captchaFromVoucher: BilibiliApplyCaptchaParamsSchema, validateCaptcha: BilibiliValidateCaptchaParamsSchema, videoDanmaku: BilibiliDanmakuParamsSchema }; /** B站方法路由映射 */ var BilibiliMethodRoutes = { videoInfo: "/fetch_one_video", videoStream: "/fetch_video_playurl", comments: "/fetch_work_comments", commentReplies: "/fetch_comment_reply", userCard: "/fetch_user_profile", userDynamicList: "/fetch_user_dynamic", userSpaceInfo: "/fetch_user_space_info", emojiList: "/fetch_emoji_list", bangumiInfo: "/fetch_bangumi_video_info", bangumiStream: "/fetch_bangumi_video_playurl", dynamicDetail: "/fetch_dynamic_info", dynamicCard: "/fetch_dynamic_card", liveRoomInfo: "/fetch_live_room_detail", liveRoomInit: "/fetch_liveroom_def", loginStatus: "/login_basic_info", loginQrcode: "/new_login_qrcode", qrcodeStatus: "/check_qrcode", uploaderTotalViews: "/fetch_user_full_view", avToBv: "/av_to_bv", bvToAv: "/bv_to_av", articleContent: "/fetch_article_content", articleCards: "/fetch_article_card", articleInfo: "/fetch_article_info", articleListInfo: "/fetch_column_info", captchaFromVoucher: "/apply_captcha", validateCaptcha: "/validate_captcha", videoDanmaku: "/fetch_danmaku" }; //#endregion //#region ../amagi/packages/core/src/validation/douyin.ts /** 作品参数验证 */ var DouyinWorkParamsSchema = zod_default.object({ methodType: zod_default.enum([ "videoWork", "imageAlbumWork", "slidesWork", "parseWork", "textWork" ], { error: "方法类型必须是指定的枚举值之一" }), aweme_id: zod_default.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" }) }); /** 评论参数验证 */ var DouyinCommentParamsSchema = zod_default.object({ methodType: zod_default.literal("comments", { error: "方法类型必须是\"comments\"" }), aweme_id: zod_default.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" }), number: smartPositiveInteger("评论数量必须是正整数").optional().default(50), cursor: zod_default.coerce.number({ error: "游标必须是数字" }).int({ error: "游标必须是整数" }).min(0, { error: "游标不能小于0" }).default(0).optional() }); /** 热点词参数验证 */ var DouyinHotWordsParamsSchema = zod_default.object({ methodType: zod_default.literal("suggestWords", { error: "方法类型必须是\"suggestWords\"" }), query: zod_default.string({ error: "搜索词必须是字符串" }).min(1, { error: "搜索词不能为空" }) }); /** 搜索参数验证 */ var DouyinSearchParamsSchema = zod_default.object({ methodType: zod_default.literal("search", { error: "方法类型必须是\"search\"" }), query: zod_default.string({ error: "搜索词必须是字符串" }).min(1, { error: "搜索词不能为空" }), type: zod_default.enum([ "general", "user", "video" ], { error: "搜索类型必须是\"general\"、\"user\"或\"video\"" }).optional().default("general"), number: smartPositiveInteger("搜索数量必须是正整数").optional().default(10), search_id: zod_default.string({ error: "搜索ID必须是字符串" }).optional() }); /** 评论回复参数验证 */ var DouyinCommentReplyParamsSchema = zod_default.object({ methodType: zod_default.literal("commentReplies", { error: "方法类型必须是\"commentReplies\"" }), aweme_id: zod_default.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" }), comment_id: zod_default.string({ error: "评论ID必须是字符串" }).min(1, { error: "评论ID不能为空" }), number: smartPositiveInteger("评论数量必须是正整数").optional().default(5), cursor: zod_default.coerce.number({ error: "游标必须是数字" }).int({ error: "游标必须是整数" }).min(0, { error: "游标不能小于0" }).default(0).optional() }); /** 用户参数验证 */ var DouyinUserParamsSchema = zod_default.object({ methodType: zod_default.literal("userProfile", { error: "方法类型必须是\"userProfile\"" }), sec_uid: zod_default.string({ error: "用户ID必须是字符串" }).min(1, { error: "用户ID不能为空" }) }); /** 用户列表参数验证(视频列表、喜欢列表、推荐列表) */ var DouyinUserListParamsSchema = zod_default.object({ methodType: zod_default.enum([ "userVideoList", "userFavoriteList", "userRecommendList" ], { error: "方法类型必须是指定的枚举值之一" }), sec_uid: zod_default.string({ error: "用户ID必须是字符串" }).min(1, { error: "用户ID不能为空" }), number: smartPositiveInteger("获取数量必须是正整数").optional().default(18), max_cursor: zod_default.string({ error: "游标必须是字符串" }).optional() }); /** 音乐参数验证 */ var DouyinMusicParamsSchema = zod_default.object({ methodType: zod_default.literal("musicInfo", { error: "方法类型必须是\"musicInfo\"" }), music_id: zod_default.string({ error: "音乐ID必须是字符串" }).min(1, { error: "音乐ID不能为空" }) }); /** 直播间参数验证 */ var DouyinLiveRoomParamsSchema = zod_default.object({ methodType: zod_default.literal("liveRoomInfo", { error: "方法类型必须是\"liveRoomInfo\"" }), web_rid: zod_default.string({ error: "直播间ID必须是字符串" }).min(1, { error: "直播间ID不能为空" }), room_id: zod_default.string({ error: "直播间ID必须是字符串" }).min(1, { error: "直播间ID不能为空" }) }); /** 二维码参数验证 */ var DouyinQrcodeParamsSchema = zod_default.object({ methodType: zod_default.literal("loginQrcode", { error: "方法类型必须是\"loginQrcode\"" }), verify_fp: zod_default.string({ error: "fp指纹必须是字符串" }).min(1, { error: "fp指纹不能为空" }) }); /** 表情列表参数验证 */ var DouyinEmojiListParamsSchema = zod_default.object({ methodType: zod_default.literal("emojiList", { error: "方法类型必须是\"emojiList\"" }) }); /** 动态表情参数验证 */ var DouyinEmojiProParamsSchema = zod_default.object({ methodType: zod_default.literal("dynamicEmojiList", { error: "方法类型必须是\"dynamicEmojiList\"" }) }); /** 弹幕参数验证 */ var DouyinDanmakuParamsSchema = zod_default.object({ methodType: zod_default.literal("danmakuList", { error: "方法类型必须是\"danmakuList\"" }), aweme_id: zod_default.string({ error: "视频ID必须是字符串" }).min(1, { error: "视频ID不能为空" }), start_time: zod_default.coerce.number({ error: "开始时间必须是数字" }).int({ error: "开始时间必须是整数" }).min(0, { error: "开始时间不能小于0" }).optional(), end_time: zod_default.coerce.number({ error: "结束时间必须是数字" }).int({ error: "结束时间必须是整数" }).min(0, { error: "结束时间不能小于0" }).optional(), duration: zod_default.coerce.number({ error: "视频时长必须是数字" }).int({ error: "视频时长必须是整数" }).min(0, { error: "视频时长不能小于0" }) }).refine((data) => { if (data.end_time !== void 0) return data.end_time <= data.duration; return true; }, { error: "获取弹幕区间的结束时间不能超过视频总时长", path: ["end_time"] }).refine((data) => { if (data.start_time !== void 0 && data.end_time !== void 0) return data.start_time < data.end_time; return true; }, { error: "获取弹幕区间的开始时间必须小于结束时间", path: ["start_time"] }); /** 抖音参数验证模式映射 */ var DouyinValidationSchemas = { textWork: DouyinWorkParamsSchema, parseWork: DouyinWorkParamsSchema, videoWork: DouyinWorkParamsSchema, imageAlbumWork: DouyinWorkParamsSchema, slidesWork: DouyinWorkParamsSchema, comments: DouyinCommentParamsSchema, userProfile: DouyinUserParamsSchema, userVideoList: DouyinUserListParamsSchema, userFavoriteList: DouyinUserListParamsSchema, userRecommendList: DouyinUserListParamsSchema, suggestWords: DouyinHotWordsParamsSchema, search: DouyinSearchParamsSchema, musicInfo: DouyinMusicParamsSchema, liveRoomInfo: DouyinLiveRoomParamsSchema, loginQrcode: DouyinQrcodeParamsSchema, emojiList: DouyinEmojiListParamsSchema, dynamicEmojiList: DouyinEmojiProParamsSchema, commentReplies: DouyinCommentReplyParamsSchema, danmakuList: DouyinDanmakuParamsSchema }; /** 抖音方法路由映射 */ var DouyinMethodRoutes = { parseWork: "/fetch_one_work", textWork: "/fetch_one_work", videoWork: "/fetch_one_work", imageAlbumWork: "/fetch_one_work", slidesWork: "/fetch_one_work", comments: "/fetch_work_comments", commentReplies: "/fetch_video_comment_replies", userProfile: "/fetch_user_info", userVideoList: "/fetch_user_post_videos", userFavoriteList: "/fetch_user_favorite_list", userRecommendList: "/fetch_user_recommend_list", search: "/fetch_search_info", suggestWords: "/fetch_suggest_words", musicInfo: "/fetch_music_work", emojiList: "/fetch_emoji_list", dynamicEmojiList: "/fetch_emoji_pro_list", liveRoomInfo: "/fetch_user_live_videos", danmakuList: "/fetch_work_danmaku", loginQrcode: "/fetch_login_qrcode" }; //#endregion //#region ../amagi/packages/core/src/validation/kuaishou.ts /** * 快手视频参数验证模式 */ var KuaishouVideoParamsSchema = zod_default.object({ methodType: zod_default.literal("videoWork", { error: "methodType must be \"videoWork\"" }), photoId: zod_default.string({ error: "photoId must be a string" }).min(1, { error: "photoId cannot be empty" }) }); /** * 快手评论参数验证模式 */ var KuaishouCommentParamsSchema = zod_default.object({ methodType: zod_default.literal("comments", { error: "methodType must be \"comments\"" }), photoId: zod_default.string({ error: "photoId must be a string" }).min(1, { error: "photoId cannot be empty" }) }); /** * 快手用户主页参数验证模式 */ var KuaishouUserProfileParamsSchema = zod_default.object({ methodType: zod_default.literal("userProfile", { error: "methodType must be \"userProfile\"" }), principalId: zod_default.string({ error: "principalId must be a string" }).min(1, { error: "principalId cannot be empty" }) }); /** * 快手用户作品列表参数验证模式 */ var KuaishouUserWorkListParamsSchema = zod_default.object({ methodType: zod_default.literal("userWorkList", { error: "methodType must be \"userWorkList\"" }), principalId: zod_default.string({ error: "principalId must be a string" }).min(1, { error: "principalId cannot be empty" }), pcursor: zod_default.string({ error: "pcursor must be a string" }).optional(), count: zod_default.number({ error: "count must be a number" }).int({ error: "count must be an integer" }).positive({ error: "count must be positive" }).max(100, { error: "count must be less than or equal to 100" }).optional() }); /** * 快手直播间信息参数验证模式 */ var KuaishouLiveRoomInfoParamsSchema = zod_default.object({ methodType: zod_default.literal("liveRoomInfo", { error: "methodType must be \"liveRoomInfo\"" }), principalId: zod_default.string({ error: "principalId must be a string" }).min(1, { error: "principalId cannot be empty" }) }); /** * 快手表情参数验证模式 */ var KuaishouEmojiParamsSchema = zod_default.object({ methodType: zod_default.literal("emojiList", { error: "methodType must be \"emojiList\"" }) }); /** * 快手参数验证模式映射 */ var KuaishouValidationSchemas = { videoWork: KuaishouVideoParamsSchema, comments: KuaishouCommentParamsSchema, userProfile: KuaishouUserProfileParamsSchema, userWorkList: KuaishouUserWorkListParamsSchema, liveRoomInfo: KuaishouLiveRoomInfoParamsSchema, emojiList: KuaishouEmojiParamsSchema }; /** * 快手方法路由映射 */ var KuaishouMethodRoutes = { videoWork: "/fetch_one_work", comments: "/fetch_work_comments", userProfile: "/fetch_user_profile", userWorkList: "/fetch_user_work_list", liveRoomInfo: "/fetch_live_room_info", emojiList: "/fetch_emoji_list" }; //#endregion //#region ../amagi/packages/core/src/platform/xiaohongshu/sign/index.ts /** * 小红书签名算法类 */ var xiaohongshuSign = class { static client = new Xhshow(); /** * 生成GET请求的X-S签名 * @param path - API路径 * @param a1Cookie - a1 cookie值 * @param clientType - 客户端类型,默认为 'xhs-pc-web' * @param params - 查询参数对象 * @returns X-S签名 */ static generateXSGet(path, a1Cookie, clientType = "xhs-pc-web", params = {}) { return this.client.signXsGet(path, a1Cookie, clientType, params); } /** * 生成POST请求的X-S签名 * @param path - API路径 * @param a1Cookie - a1 cookie值 * @param clientType - 客户端类型,默认为 'xhs-pc-web' * @param body - 请求体对象 * @returns X-S签名 */ static generateXSPost(path, a1Cookie, clientType = "xhs-pc-web", body = {}) { return this.client.signXsPost(path, a1Cookie, clientType, body); } /** * 生成X-S-Common参数 * @param cookies - cookie字符串 * @returns Base64编码的随机字符串 */ static generateXSCommon(cookies) { return this.client.signXsCommon(cookies); } /** * 生成X-T时间戳 * @returns 当前时间戳字符串 */ static generateXT() { return this.client.getXT(); } /** * 生成X-B3-Traceid * @returns 16位随机字符串 */ static generateXB3Traceid() { return this.client.getB3TraceId(); } /** * 从cookie字符串中提取a1值 * @param cookieString - 完整的cookie字符串 * @returns a1 cookie值 */ static extractA1FromCookie(cookieString) { const match = cookieString.match(/a1=([^;]+)/); return match ? match[1] : ""; } /** * 生成搜索ID * @returns 搜索ID字符串 */ static getSearchId = () => (BigInt(Date.now()) << 64n) + BigInt(Math.floor(Math.random() * 2147483646)).toString(36); }; //#endregion //#region ../amagi/packages/core/src/platform/xiaohongshu/API.ts /** * 搜索排序类型枚举 */ var SearchSortType = /* @__PURE__ */ function(SearchSortType) { /** * 默认排序 */ SearchSortType["GENERAL"] = "general"; /** * 最受欢迎(按热度降序) */ SearchSortType["MOST_POPULAR"] = "popularity_descending"; /** * 最新发布(按时间降序) */ SearchSortType["LATEST"] = "time_descending"; return SearchSortType; }({}); /** * 搜索笔记类型枚举 */ var SearchNoteType = /* @__PURE__ */ function(SearchNoteType) { /** * 默认(全部类型) */ SearchNoteType[SearchNoteType["ALL"] = 0] = "ALL"; /** * 仅视频 */ SearchNoteType[SearchNoteType["VIDEO"] = 1] = "VIDEO"; /** * 仅图片 */ SearchNoteType[SearchNoteType["IMAGE"] = 2] = "IMAGE"; return SearchNoteType; }({}); /** * 构建查询字符串 * @param params - 参数对象 * @returns 查询字符串 */ var buildQueryString$1 = (params) => { return Object.entries(params).filter(([_, value]) => value !== void 0 && value !== null).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join("&"); }; /** * 小红书API地址配置 */ var xiaohongshuApiUrls = { /** * 获取首页推荐数据的接口地址 * @param data - 请求参数 * @returns 完整的接口URL */ homeFeed(data = {}) { return { apiPath: "/api/sns/web/v1/homefeed", Url: "https://edith.xiaohongshu.com/api/sns/web/v1/homefeed", Body: { cursor_score: data.cursor_score ?? "1.7599348899670024E9", num: data.num ?? 33, refresh_type: data.refresh_type ?? 3, note_index: d