@ikenxuan/amagi
Version:
抖音、B站的 web 端相关数据接口基于 Node.js 的实现
1,305 lines (1,297 loc) • 75 kB
JavaScript
import axios, { AxiosError } from 'axios';
import crypto from 'crypto';
import express from 'express';
import chalk from 'chalk';
import log4js from 'log4js';
// src/platform/bilibili/API.ts
var BiLiBiLiAPI = class {
\u767B\u5F55\u57FA\u672C\u4FE1\u606F() {
return "https://api.bilibili.com/x/web-interface/nav";
}
\u89C6\u9891\u8BE6\u7EC6\u4FE1\u606F(data2) {
return `https://api.bilibili.com/x/web-interface/view?bvid=${data2.bvid}`;
}
\u89C6\u9891\u6D41\u4FE1\u606F(data2) {
return `https://api.bilibili.com/x/player/playurl?avid=${data2.avid}&cid=${data2.cid}`;
}
/** 评论区类型,type参数详见 [评论区类型代码](https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/comment/readme.md#评论区类型代码) */
\u8BC4\u8BBA\u533A\u660E\u7EC6(data2) {
return `https://api.bilibili.com/x/v2/reply?sort=1&ps=${data2.number ?? 20}&type=${data2.type}&oid=${data2.oid}&pn=${data2.pn}`;
}
\u8BC4\u8BBA\u533A\u72B6\u6001(data2) {
return `https://api.bilibili.com/x/v2/reply/subject/description?type=${data2.type}&oid=${data2.oid}`;
}
\u8868\u60C5\u5217\u8868() {
return "https://api.bilibili.com/x/emote/user/panel/web?business=reply&web_location=0.0";
}
\u756A\u5267\u660E\u7EC6(data2) {
if (data2.ep_id) {
return `https://api.bilibili.com/pgc/view/web/season?ep_id=${data2.ep_id}`;
} else if (data2.season_id) {
return `https://api.bilibili.com/pgc/view/web/season?season_id=${data2.season_id}`;
} else {
throw new Error("\u62DF\u9020\u63A5\u53E3\u5730\u5740\u51FA\u9519\uFF0C\u7F3A\u5C11 ep_id \u6216 season_id \u53C2\u6570");
}
}
\u756A\u5267\u89C6\u9891\u6D41\u4FE1\u606F(data2) {
return `https://api.bilibili.com/pgc/player/web/playurl?cid=${data2.cid}&ep_id=${data2.ep_id}`;
}
\u7528\u6237\u7A7A\u95F4\u52A8\u6001(data2) {
return `https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/space?host_mid=${data2.host_mid}`;
}
\u52A8\u6001\u8BE6\u60C5(data2) {
return `https://api.bilibili.com/x/polymer/web-dynamic/v1/detail?id=${data2.dynamic_id}`;
}
\u52A8\u6001\u5361\u7247\u4FE1\u606F(data2) {
return `https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/get_dynamic_detail?dynamic_id=${data2.dynamic_id}`;
}
\u7528\u6237\u540D\u7247\u4FE1\u606F(data2) {
return `https://api.bilibili.com/x/web-interface/card?mid=${data2.host_mid}&photo=true`;
}
\u76F4\u64AD\u95F4\u4FE1\u606F(data2) {
return `https://api.live.bilibili.com/room/v1/Room/get_info?room_id=${data2.room_id}`;
}
\u76F4\u64AD\u95F4\u521D\u59CB\u5316\u4FE1\u606F(data2) {
return `https://api.live.bilibili.com/room/v1/Room/room_init?id=${data2.room_id}`;
}
\u7533\u8BF7\u4E8C\u7EF4\u7801() {
return "https://passport.bilibili.com/x/passport-login/web/qrcode/generate";
}
\u4E8C\u7EF4\u7801\u72B6\u6001(data2) {
return `https://passport.bilibili.com/x/passport-login/web/qrcode/poll?qrcode_key=${data2.qrcode_key}`;
}
\u83B7\u53D6UP\u4E3B\u603B\u64AD\u653E\u91CF(data2) {
return `https://api.bilibili.com/x/space/upstat?mid=${data2.host_mid}`;
}
};
var bilibiliAPI = new BiLiBiLiAPI();
// src/platform/bilibili/getdata.ts
var defheaders = {
accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"cache-control": "max-age=0",
priority: "u=0, i",
"sec-ch-ua": "'Microsoft Edge';v='131', 'Chromium';v='131', 'Not_A Brand';v='24'",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "'Windows'",
"sec-fetch-dest": "document",
"sec-fetch-mode": "navigate",
"sec-fetch-site": "none",
"sec-fetch-user": "?1",
"upgrade-insecure-requests": "1",
referer: "https://www.bilibili.com/"
};
var BilibiliData = async (data2, cookie) => {
const headers2 = {
...defheaders,
cookie: cookie ? cookie.replace(/\s+/g, "") : ""
};
switch (data2.methodType) {
case "\u5355\u4E2A\u89C6\u9891\u4F5C\u54C1\u6570\u636E": {
BilibiliValidateData(data2, ["bvid"]);
const INFODATA = await GlobalGetData({
url: bilibiliAPI.\u89C6\u9891\u8BE6\u7EC6\u4FE1\u606F({ bvid: data2.bvid }),
...data2
});
return INFODATA;
}
case "\u5355\u4E2A\u89C6\u9891\u4E0B\u8F7D\u4FE1\u606F\u6570\u636E": {
BilibiliValidateData(data2, ["avid", "cid"]);
const BASEURL = bilibiliAPI.\u89C6\u9891\u6D41\u4FE1\u606F({ avid: data2.avid, cid: data2.cid });
const SIGN = await qtparam(BASEURL, headers2.cookie);
const DATA = await GlobalGetData({
url: bilibiliAPI.\u89C6\u9891\u6D41\u4FE1\u606F({ avid: data2.avid, cid: data2.cid }) + SIGN.QUERY,
headers: headers2,
...data2
});
return DATA;
}
case "\u8BC4\u8BBA\u6570\u636E": {
BilibiliValidateData(data2, ["oid", "type"]);
let { oid, number, pn, type } = data2;
let fetchedComments = [];
pn = pn ?? 1;
const maxRequestCount = 100;
const commentGrowthStabilized = 5;
let lastFetchedCount = 0;
let stabilizedCount = 0;
let requestCount = 0;
let tmpresp;
try {
while (fetchedComments.length < Number(number ?? 20) && requestCount < maxRequestCount) {
if (number === 0 || number === void 0) {
requestCount = 0;
} else {
requestCount = Math.min(20, Number(number) - fetchedComments.length);
}
const url = bilibiliAPI.\u8BC4\u8BBA\u533A\u660E\u7EC6({
type,
oid,
number: requestCount,
pn
});
const checkStatusUrl = bilibiliAPI.\u8BC4\u8BBA\u533A\u72B6\u6001({ oid, type });
const checkStatusRes = await GlobalGetData({
url: checkStatusUrl,
headers: headers2,
...data2
});
if (checkStatusRes.data === null) {
logger.error("\u8BC4\u8BBA\u533A\u672A\u5F00\u653E");
return {
code: 404,
message: "\u8BC4\u8BBA\u533A\u672A\u5F00\u653E",
data: null
};
}
const response = await GlobalGetData({
url,
headers: headers2,
...data2
});
tmpresp = response;
const currentCount = response.data.replies ? response.data.replies.length : 0;
fetchedComments.push(...response.data.replies || []);
if (currentCount === lastFetchedCount) {
stabilizedCount++;
} else {
stabilizedCount = 0;
}
lastFetchedCount = currentCount;
if (stabilizedCount >= commentGrowthStabilized || requestCount >= maxRequestCount) {
break;
}
pn++;
requestCount++;
}
} catch {
return false;
}
const finalResponse = {
...tmpresp,
data: {
...tmpresp.data,
// 去重
replies: Array.from(new Map(fetchedComments.map((item) => [item.rpid, item])).values()).slice(0, Number(data2.number))
}
};
return finalResponse;
}
case "Emoji\u6570\u636E": {
return await GlobalGetData({
url: bilibiliAPI.\u8868\u60C5\u5217\u8868(),
...data2
});
}
case "\u756A\u5267\u57FA\u672C\u4FE1\u606F\u6570\u636E": {
let id = data2.ep_id ? data2.ep_id : data2.season_id;
if (!id) {
BilibiliValidateData(data2, ["ep_id"]);
return false;
}
const idType = id ? id.startsWith("ep") ? "ep_id" : "season_id" : "ep_id";
const newId = idType === "ep_id" ? id.replace("ep", "") : id.replace("ss", "");
const INFO = await GlobalGetData({
url: bilibiliAPI.\u756A\u5267\u660E\u7EC6({ [idType]: newId }),
headers: headers2,
...data2
});
return INFO;
}
case "\u756A\u5267\u4E0B\u8F7D\u4FE1\u606F\u6570\u636E": {
BilibiliValidateData(data2, ["cid", "ep_id"]);
const BASEURL = bilibiliAPI.\u756A\u5267\u89C6\u9891\u6D41\u4FE1\u606F({ cid: data2.cid, ep_id: data2.ep_id.replace("ep", "") });
const SIGN = await qtparam(BASEURL, headers2.cookie);
const DATA = await GlobalGetData({
url: bilibiliAPI.\u756A\u5267\u89C6\u9891\u6D41\u4FE1\u606F({ cid: data2.cid, ep_id: data2.ep_id.replace("ep", "") }) + SIGN.QUERY,
headers: headers2,
...data2
});
return DATA;
}
case "\u7528\u6237\u4E3B\u9875\u52A8\u6001\u5217\u8868\u6570\u636E": {
BilibiliValidateData(data2, ["host_mid"]);
delete headers2.referer;
const { host_mid } = data2;
const result = await GlobalGetData({
url: bilibiliAPI.\u7528\u6237\u7A7A\u95F4\u52A8\u6001({ host_mid }),
headers: headers2,
...data2
});
return result;
}
case "\u52A8\u6001\u8BE6\u60C5\u6570\u636E": {
BilibiliValidateData(data2, ["dynamic_id"]);
delete headers2.referer;
const dynamicINFO = await GlobalGetData({
url: bilibiliAPI.\u52A8\u6001\u8BE6\u60C5({ dynamic_id: data2.dynamic_id }),
headers: headers2,
...data2
});
return dynamicINFO;
}
case "\u52A8\u6001\u5361\u7247\u6570\u636E": {
BilibiliValidateData(data2, ["dynamic_id"]);
delete headers2.referer;
const { dynamic_id } = data2;
const dynamicINFO_CARD = await GlobalGetData({
url: bilibiliAPI.\u52A8\u6001\u5361\u7247\u4FE1\u606F({ dynamic_id }),
headers: headers2,
...data2
});
return dynamicINFO_CARD;
}
case "\u7528\u6237\u4E3B\u9875\u6570\u636E": {
BilibiliValidateData(data2, ["host_mid"]);
const { host_mid } = data2;
const result = await GlobalGetData({
url: bilibiliAPI.\u7528\u6237\u540D\u7247\u4FE1\u606F({ host_mid }),
headers: headers2,
...data2
});
return result;
}
case "\u76F4\u64AD\u95F4\u4FE1\u606F": {
BilibiliValidateData(data2, ["room_id"]);
const result = await GlobalGetData({
url: bilibiliAPI.\u76F4\u64AD\u95F4\u4FE1\u606F({ room_id: data2.room_id }),
headers: headers2,
...data2
});
return result;
}
case "\u76F4\u64AD\u95F4\u521D\u59CB\u5316\u4FE1\u606F": {
BilibiliValidateData(data2, ["room_id"]);
const result = await GlobalGetData({
url: bilibiliAPI.\u76F4\u64AD\u95F4\u521D\u59CB\u5316\u4FE1\u606F({ room_id: data2.room_id }),
headers: headers2,
...data2
});
return result;
}
case "\u7533\u8BF7\u4E8C\u7EF4\u7801": {
const result = await GlobalGetData({
url: bilibiliAPI.\u7533\u8BF7\u4E8C\u7EF4\u7801(),
headers: headers2,
...data2
});
return result;
}
case "\u4E8C\u7EF4\u7801\u72B6\u6001": {
BilibiliValidateData(data2, ["qrcode_key"]);
const result = await new Networks({
url: bilibiliAPI.\u4E8C\u7EF4\u7801\u72B6\u6001({ qrcode_key: data2.qrcode_key }),
headers: headers2,
...data2
}).getHeadersAndData();
return result;
}
case "\u767B\u5F55\u57FA\u672C\u4FE1\u606F": {
const result = await GlobalGetData({
url: bilibiliAPI.\u767B\u5F55\u57FA\u672C\u4FE1\u606F(),
headers: headers2,
...data2
});
return result;
}
case "\u83B7\u53D6UP\u4E3B\u603B\u64AD\u653E\u91CF": {
BilibiliValidateData(data2, ["host_mid"]);
const result = await GlobalGetData({
url: bilibiliAPI.\u83B7\u53D6UP\u4E3B\u603B\u64AD\u653E\u91CF({ host_mid: data2.host_mid }),
headers: headers2,
...data2
});
return result;
}
case "AV\u8F6CBV": {
BilibiliValidateData(data2, ["avid"]);
const result = av2bv(Number(data2.avid.toString().replace(/^av/i, "")));
return {
code: 0,
message: "success",
data: {
bvid: result
}
};
}
case "BV\u8F6CAV": {
BilibiliValidateData(data2, ["bvid"]);
const result = "av" + bv2av(data2.bvid);
return {
code: 0,
message: "success",
data: {
aid: result
}
};
}
default:
return null;
}
};
var GlobalGetData = async (options) => {
const result = await new Networks(options).getData();
if (result && result.code === 0) {
return result;
} else if (result.code === 12061) {
logger.warn(`\u83B7\u53D6\u54CD\u5E94\u6570\u636E\u5931\u8D25\uFF01
\u8BF7\u6C42\u63A5\u53E3\u7C7B\u578B\uFF1A${options.methodType}
\u8BF7\u6C42URL\uFF1A${options.url}
\u9519\u8BEF\u4EE3\u7801\uFF1A${result.code}\uFF0C
\u542B\u4E49\uFF1A${result.message}`);
return result;
} else {
const errorMessage = errorMap[result.code] || result.message || "\u672A\u77E5\u9519\u8BEF";
logger.warn(`\u83B7\u53D6\u54CD\u5E94\u6570\u636E\u5931\u8D25\uFF01
\u8BF7\u6C42\u63A5\u53E3\u7C7B\u578B\uFF1A${options.methodType}
\u8BF7\u6C42URL\uFF1A${options.url}
\u9519\u8BEF\u4EE3\u7801\uFF1A${result.code}\uFF0C
\u542B\u4E49\uFF1A${errorMessage}`);
return result;
}
};
var errorMap = {
"-1": "\u5E94\u7528\u7A0B\u5E8F\u4E0D\u5B58\u5728\u6216\u5DF2\u88AB\u5C01\u7981",
"-2": "Access Key \u9519\u8BEF",
"-3": "API \u6821\u9A8C\u5BC6\u5319\u9519\u8BEF",
"-4": "\u8C03\u7528\u65B9\u5BF9\u8BE5 Method \u6CA1\u6709\u6743\u9650",
"-101": "\u8D26\u53F7\u672A\u767B\u5F55",
"-102": "\u8D26\u53F7\u88AB\u5C01\u505C",
"-103": "\u79EF\u5206\u4E0D\u8DB3",
"-104": "\u786C\u5E01\u4E0D\u8DB3",
"-105": "\u9A8C\u8BC1\u7801\u9519\u8BEF",
"-106": "\u8D26\u53F7\u975E\u6B63\u5F0F\u4F1A\u5458\u6216\u5728\u9002\u5E94\u671F",
"-107": "\u5E94\u7528\u4E0D\u5B58\u5728\u6216\u8005\u88AB\u5C01\u7981",
"-108": "\u672A\u7ED1\u5B9A\u624B\u673A",
"-110": "\u672A\u7ED1\u5B9A\u624B\u673A",
"-111": "csrf \u6821\u9A8C\u5931\u8D25",
"-112": "\u7CFB\u7EDF\u5347\u7EA7\u4E2D",
"-113": "\u8D26\u53F7\u5C1A\u672A\u5B9E\u540D\u8BA4\u8BC1",
"-114": "\u8BF7\u5148\u7ED1\u5B9A\u624B\u673A",
"-115": "\u8BF7\u5148\u5B8C\u6210\u5B9E\u540D\u8BA4\u8BC1",
"-304": "\u6728\u6709\u6539\u52A8",
"-307": "\u649E\u8F66\u8DF3\u8F6C",
"-352": "\u98CE\u63A7\u6821\u9A8C\u5931\u8D25 (UA \u6216 wbi \u53C2\u6570\u4E0D\u5408\u6CD5)",
"-400": "\u8BF7\u6C42\u9519\u8BEF",
"-401": "\u672A\u8BA4\u8BC1 (\u6216\u975E\u6CD5\u8BF7\u6C42)",
"-403": "\u8BBF\u95EE\u6743\u9650\u4E0D\u8DB3",
"-404": "\u5565\u90FD\u6728\u6709",
"-405": "\u4E0D\u652F\u6301\u8BE5\u65B9\u6CD5",
"-409": "\u51B2\u7A81",
"-412": "\u8BF7\u6C42\u88AB\u62E6\u622A (\u5BA2\u6237\u7AEF ip \u88AB\u670D\u52A1\u7AEF\u98CE\u63A7)",
"-500": "\u670D\u52A1\u5668\u9519\u8BEF",
"-503": "\u8FC7\u8F7D\u4FDD\u62A4,\u670D\u52A1\u6682\u4E0D\u53EF\u7528",
"-504": "\u670D\u52A1\u8C03\u7528\u8D85\u65F6",
"-509": "\u8D85\u51FA\u9650\u5236",
"-616": "\u4E0A\u4F20\u6587\u4EF6\u4E0D\u5B58\u5728",
"-617": "\u4E0A\u4F20\u6587\u4EF6\u592A\u5927",
"-625": "\u767B\u5F55\u5931\u8D25\u6B21\u6570\u592A\u591A",
"-626": "\u7528\u6237\u4E0D\u5B58\u5728",
"-628": "\u5BC6\u7801\u592A\u5F31",
"-629": "\u7528\u6237\u540D\u6216\u5BC6\u7801\u9519\u8BEF",
"-632": "\u64CD\u4F5C\u5BF9\u8C61\u6570\u91CF\u9650\u5236",
"-643": "\u88AB\u9501\u5B9A",
"-650": "\u7528\u6237\u7B49\u7EA7\u592A\u4F4E",
"-652": "\u91CD\u590D\u7684\u7528\u6237",
"-658": "Token \u8FC7\u671F",
"-662": "\u5BC6\u7801\u65F6\u95F4\u6233\u8FC7\u671F",
"-688": "\u5730\u7406\u533A\u57DF\u9650\u5236",
"-689": "\u7248\u6743\u9650\u5236",
"-701": "\u6263\u8282\u64CD\u5931\u8D25",
"-799": "\u8BF7\u6C42\u8FC7\u4E8E\u9891\u7E41\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",
"-8888": "\u5BF9\u4E0D\u8D77\uFF0C\u670D\u52A1\u5668\u5F00\u5C0F\u5DEE\u4E86~ (\u0CA5\uFE4F\u0CA5)"
};
// src/platform/bilibili/qtparam.ts
async function qtparam(BASEURL, cookie) {
if (cookie === "") return { QUERY: "&platform=html5", STATUS: "!isLogin" };
const logininfo = await new Networks({ url: bilibiliAPI.\u767B\u5F55\u57FA\u672C\u4FE1\u606F(), headers: { Cookie: cookie } }).getData();
const sign = await wbi_sign(BASEURL, cookie);
const qn = [6, 16, 32, 64, 74, 80, 112, 116, 120, 125, 126, 127];
let isvip;
logininfo.data.vipStatus === 1 ? isvip = true : isvip = false;
if (isvip) {
return { QUERY: `&fnval=16&fourk=1&${sign}`, STATUS: "isLogin", isvip };
} else return { QUERY: `&qn=${qn[3]}&fnval=16`, STATUS: "isLogin", isvip };
}
var mixinKeyEncTab = [
46,
47,
18,
2,
53,
8,
23,
32,
15,
50,
10,
31,
58,
3,
45,
35,
27,
43,
5,
49,
33,
9,
42,
19,
29,
28,
14,
39,
12,
38,
41,
13,
37,
48,
7,
16,
24,
55,
40,
61,
26,
17,
0,
1,
60,
51,
30,
4,
22,
25,
54,
21,
56,
59,
6,
63,
57,
62,
11,
36,
20,
34,
44,
52
];
var getMixinKey = (orig) => mixinKeyEncTab.map((n) => orig[n]).join("").slice(0, 32);
function encWbi(params, img_key, sub_key) {
const mixin_key = getMixinKey(img_key + sub_key);
const curr_time = Math.round(Date.now() / 1e3);
const chr_filter = /[!'()*]/g;
Object.assign(params, { wts: curr_time });
const query = Object.keys(params).sort().map((key) => {
const value = params[key].toString().replace(chr_filter, "");
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
}).join("&");
const wbi_sign2 = crypto.createHash("md5").update(query + mixin_key).digest("hex");
return `&wts=${curr_time}&w_rid=${wbi_sign2}`;
}
async function getWbiKeys(cookie) {
const res = await axios("https://api.bilibili.com/x/web-interface/nav", {
headers: {
Cookie: cookie
}
});
const responseJson = res.data;
const response = responseJson;
const {
data: {
wbi_img: { img_url, sub_url }
}
} = response;
return {
img_key: img_url.slice(img_url.lastIndexOf("/") + 1, img_url.lastIndexOf(".")),
sub_key: sub_url.slice(sub_url.lastIndexOf("/") + 1, sub_url.lastIndexOf("."))
};
}
async function wbi_sign(BASEURL, cookie) {
const web_keys = await getWbiKeys(cookie);
const url = new URL(BASEURL);
const params = {};
for (const [key, value] of url.searchParams.entries()) {
params[key] = value;
}
const query = encWbi(params, web_keys.img_key, web_keys.sub_key);
return query;
}
var registerBilibiliRoutes = (cookie) => {
const router = express.Router();
router.get("/new_login_qrcode", async (req, res) => {
const data2 = await BilibiliData({
methodType: "\u7533\u8BF7\u4E8C\u7EF4\u7801"
}, req.headers.cookie || cookie);
res.json(data2);
});
router.get("/check_qrcode", async (req, res) => {
const data2 = await BilibiliData({
methodType: "\u4E8C\u7EF4\u7801\u72B6\u6001",
qrcode_key: req.query.qrcode_key
}, req.headers.cookie || cookie);
res.json(data2);
});
router.get("/login_basic_info", async (req, res) => {
const data2 = await BilibiliData({
methodType: "\u767B\u5F55\u57FA\u672C\u4FE1\u606F"
}, req.headers.cookie || cookie);
res.json(data2);
});
router.get("/fetch_one_video", async (req, res) => {
const data2 = await BilibiliData({
methodType: "\u5355\u4E2A\u89C6\u9891\u4F5C\u54C1\u6570\u636E",
bvid: req.query.bvid
}, req.headers.cookie || cookie);
res.json(data2);
});
router.get("/fetch_video_playurl", async (req, res) => {
const data2 = await BilibiliData({
methodType: "\u5355\u4E2A\u89C6\u9891\u4E0B\u8F7D\u4FE1\u606F\u6570\u636E",
avid: parseInt(req.query.avid),
cid: parseInt(req.query.cid)
}, req.headers.cookie || cookie);
res.json(data2);
});
router.get("/fetch_work_comments", async (req, res) => {
const data2 = await BilibiliData({
methodType: "\u8BC4\u8BBA\u6570\u636E",
oid: Number(req.query.oid),
number: Number(req.query.number),
type: Number(req.query.type ?? 1)
}, req.headers.cookie || cookie);
res.json(data2);
});
router.get("/fetch_work_comments", async (req, res) => {
const data2 = await BilibiliData({
methodType: "Emoji\u6570\u636E"
}, req.headers.cookie || cookie);
res.json(data2);
});
router.get("/fetch_bangumi_video_info", async (req, res) => {
const data2 = await BilibiliData({
methodType: "\u756A\u5267\u57FA\u672C\u4FE1\u606F\u6570\u636E",
ep_id: req.query.ep_id
}, req.headers.cookie || cookie);
res.json(data2);
});
router.get("/fetch_bangumi_video_playurl", async (req, res) => {
const data2 = await BilibiliData({
methodType: "\u756A\u5267\u4E0B\u8F7D\u4FE1\u606F\u6570\u636E",
cid: parseInt(req.query.cid),
ep_id: req.query.ep_id
}, req.headers.cookie || cookie);
res.json(data2);
});
router.get("/fetch_user_dynamic", async (req, res) => {
const data2 = await BilibiliData({
methodType: "\u7528\u6237\u4E3B\u9875\u52A8\u6001\u5217\u8868\u6570\u636E",
host_mid: parseInt(req.query.host_mid)
}, req.headers.cookie || cookie);
res.json(data2);
});
router.get("/fetch_dynamic_info", async (req, res) => {
const data2 = await BilibiliData({
methodType: "\u52A8\u6001\u8BE6\u60C5\u6570\u636E",
dynamic_id: req.query.dynamic_id
}, req.headers.cookie || cookie);
res.json(data2);
});
router.get("/fetch_dynamic_card", async (req, res) => {
const data2 = await BilibiliData({
methodType: "\u52A8\u6001\u5361\u7247\u6570\u636E",
dynamic_id: req.query.dynamic_id
}, req.headers.cookie || cookie);
res.json(data2);
});
router.get("/fetch_user_profile", async (req, res) => {
const data2 = await BilibiliData({
methodType: "\u7528\u6237\u4E3B\u9875\u6570\u636E",
host_mid: parseInt(req.query.host_mid)
}, req.headers.cookie || cookie);
res.json(data2);
});
router.get("/fetch_live_room_detail", async (req, res) => {
const data2 = await BilibiliData({
methodType: "\u76F4\u64AD\u95F4\u4FE1\u606F",
room_id: req.query.room_id
}, req.headers.cookie || cookie);
res.json(data2);
});
router.get("/fetch_liveroom_def", async (req, res) => {
const data2 = await BilibiliData({
methodType: "\u76F4\u64AD\u95F4\u521D\u59CB\u5316\u4FE1\u606F",
room_id: req.query.room_id
}, req.headers.cookie || cookie);
res.json(data2);
});
router.get("/bv_to_av", async (req, res) => {
const data2 = await BilibiliData({
methodType: "BV\u8F6CAV",
bvid: req.query.bvid
}, req.headers.cookie || cookie);
res.json(data2);
});
router.get("/av_to_bv", async (req, res) => {
const data2 = await BilibiliData({
methodType: "AV\u8F6CBV",
avid: parseInt(req.query.avid)
}, req.headers.cookie || cookie);
res.json(data2);
});
router.get("/fetch_user_full_view", async (req, res) => {
const data2 = await BilibiliData({
methodType: "\u83B7\u53D6UP\u4E3B\u603B\u64AD\u653E\u91CF",
host_mid: parseInt(req.query.host_mid)
}, req.headers.cookie || cookie);
res.json(data2);
});
return router;
};
// src/platform/bilibili/sign/bv2av.ts
var XOR_CODE = 23442827791579n;
var MASK_CODE = 2251799813685247n;
var MAX_AID = 1n << 51n;
var BASE = 58n;
var data = "FcwAPNKTMug3GV5Lj7EJnHpWsx4tb8haYeviqBz6rkCy12mUSDQX9RdoZf";
function av2bv(aid) {
const bytes = ["B", "V", "1", "0", "0", "0", "0", "0", "0", "0", "0", "0"];
let bvIndex = bytes.length - 1;
let tmp = (MAX_AID | BigInt(aid)) ^ XOR_CODE;
while (tmp > 0) {
bytes[bvIndex] = data[Number(tmp % BigInt(BASE))];
tmp = tmp / BASE;
bvIndex -= 1;
}
[bytes[3], bytes[9]] = [bytes[9], bytes[3]];
[bytes[4], bytes[7]] = [bytes[7], bytes[4]];
return bytes.join("");
}
function bv2av(bvid) {
const bvidArr = Array.from(bvid);
[bvidArr[3], bvidArr[9]] = [bvidArr[9], bvidArr[3]];
[bvidArr[4], bvidArr[7]] = [bvidArr[7], bvidArr[4]];
bvidArr.splice(0, 3);
const tmp = bvidArr.reduce((pre, bvidChar) => pre * BASE + BigInt(data.indexOf(bvidChar)), 0n);
return Number(tmp & MASK_CODE ^ XOR_CODE);
}
// src/platform/douyin/sign/a_bogus.ts
var SM3 = class {
reg;
chunk;
size;
constructor() {
this.reg = [];
this.chunk = [];
this.size = 0;
this.reset();
}
reset() {
this.reg[0] = 1937774191;
this.reg[1] = 1226093241;
this.reg[2] = 388252375;
this.reg[3] = 3666478592;
this.reg[4] = 2842636476;
this.reg[5] = 372324522;
this.reg[6] = 3817729613;
this.reg[7] = 2969243214;
this.chunk = [];
this.size = 0;
}
write(e) {
const a = typeof e === "string" ? this.stringToBytes(e) : e;
this.size += a.length;
let f = 64 - this.chunk.length;
if (a.length < f) {
this.chunk = this.chunk.concat(a);
} else {
this.chunk = this.chunk.concat(a.slice(0, f));
while (this.chunk.length >= 64) {
this._compress(this.chunk);
f < a.length ? this.chunk = a.slice(f, Math.min(f + 64, a.length)) : this.chunk = [];
f += 64;
}
}
}
sum(e, t) {
if (e) {
this.reset();
this.write(e);
}
this._fill();
for (let f = 0; f < this.chunk.length; f += 64) {
this._compress(this.chunk.slice(f, f + 64));
}
let i = null;
if (t === "hex") {
i = "";
for (let f = 0; f < 8; f++) {
i += this.padHex(this.reg[f].toString(16), 8);
}
} else {
i = new Array(32);
for (let f = 0; f < 8; f++) {
let c = this.reg[f];
i[4 * f + 3] = (255 & c) >>> 0;
c >>>= 8;
i[4 * f + 2] = (255 & c) >>> 0;
c >>>= 8;
i[4 * f + 1] = (255 & c) >>> 0;
c >>>= 8;
i[4 * f] = (255 & c) >>> 0;
}
}
this.reset();
return i;
}
_compress(t) {
if (t.length < 64) {
console.error("compress error: not enough data");
} else {
for (var f = ((e) => {
for (var r = new Array(132), t2 = 0; t2 < 16; t2++) {
r[t2] = e[4 * t2] << 24, r[t2] |= e[4 * t2 + 1] << 16, r[t2] |= e[4 * t2 + 2] << 8, r[t2] |= e[4 * t2 + 3], r[t2] >>>= 0;
}
for (var n = 16; n < 68; n++) {
let a = r[n - 16] ^ r[n - 9] ^ this.le(r[n - 3], 15);
a = a ^ this.le(a, 15) ^ this.le(a, 23), r[n] = (a ^ this.le(r[n - 13], 7) ^ r[n - 6]) >>> 0;
}
for (n = 0; n < 64; n++) r[n + 68] = (r[n] ^ r[n + 4]) >>> 0;
return r;
})(t), i = this.reg.slice(0), c = 0; c < 64; c++) {
let o = this.le(i[0], 12) + i[4] + this.le(this.de(c), c);
const s = ((o = this.le(o = (4294967295 & o) >>> 0, 7)) ^ this.le(i[0], 12)) >>> 0;
let u = this.pe(c, i[0], i[1], i[2]);
u = (4294967295 & (u = u + i[3] + s + f[c + 68])) >>> 0;
let b = this.he(c, i[4], i[5], i[6]);
b = (4294967295 & (b = b + i[7] + o + f[c])) >>> 0, i[3] = i[2], i[2] = this.le(i[1], 9), i[1] = i[0], i[0] = u, i[7] = i[6], i[6] = this.le(i[5], 19), i[5] = i[4], i[4] = (b ^ this.le(b, 9) ^ this.le(b, 17)) >>> 0;
}
for (let l = 0; l < 8; l++) this.reg[l] = (this.reg[l] ^ i[l]) >>> 0;
}
}
_fill() {
let a = 8 * this.size;
let f = this.chunk.push(128) % 64;
while (64 - f < 8) {
f -= 64;
}
while (f < 56) {
this.chunk.push(0);
f++;
}
for (let i = 0; i < 4; i++) {
const c = Math.floor(a / 4294967296);
this.chunk.push(c >>> 8 * (3 - i) & 255);
}
for (let i = 0; i < 4; i++) {
this.chunk.push(a >>> 8 * (3 - i) & 255);
}
}
de(e) {
return e >= 0 && e < 16 ? 2043430169 : e >= 16 && e < 64 ? 2055708042 : (console.error("invalid j for constant Tj"), 0);
}
pe(e, r, t, n) {
return e >= 0 && e < 16 ? (r ^ t ^ n) >>> 0 : e >= 16 && e < 64 ? (r & t | r & n | t & n) >>> 0 : (console.error("invalid j for bool function FF"), 0);
}
he(e, r, t, n) {
return e >= 0 && e < 16 ? (r ^ t ^ n) >>> 0 : e >= 16 && e < 64 ? (r & t | ~r & n) >>> 0 : (console.error("invalid j for bool function GG"), 0);
}
le(e, r) {
return (e << (r %= 32) | e >>> 32 - r) >>> 0;
}
stringToBytes(str) {
const n = encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (_, r) => String.fromCharCode(parseInt(r, 16)));
const a = new Array(n.length);
for (let i = 0; i < n.length; i++) {
a[i] = n.charCodeAt(i);
}
return a;
}
padHex(num, size) {
return num.padStart(size, "0");
}
};
function rc4_encrypt(plaintext, key) {
const s = [];
for (var i = 0; i < 256; i++) {
s[i] = i;
}
var j = 0;
for (var i = 0; i < 256; i++) {
j = (j + s[i] + key.charCodeAt(i % key.length)) % 256;
var temp = s[i];
s[i] = s[j];
s[j] = temp;
}
var i = 0;
var j = 0;
const cipher = [];
for (let k = 0; k < plaintext.length; k++) {
i = (i + 1) % 256;
j = (j + s[i]) % 256;
var temp = s[i];
s[i] = s[j];
s[j] = temp;
const t = (s[i] + s[j]) % 256;
cipher.push(String.fromCharCode(s[t] ^ plaintext.charCodeAt(k)));
}
return cipher.join("");
}
function result_encrypt(long_str, num) {
const s_obj = {
s0: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
s1: "Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=",
s2: "Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=",
s3: "ckdp1h4ZKsUB80/Mfvw36XIgR25+WQAlEi7NLboqYTOPuzmFjJnryx9HVGDaStCe",
s4: "Dkdpgh2ZmsQB80/MfvV36XI1R45-WUAlEixNLwoqYTOPuzKFjJnry79HbGcaStCe"
};
const constant = {
0: 16515072,
1: 258048,
2: 4032,
str: s_obj[num]
};
let result = "";
let lound = 0;
let long_int = get_long_int(lound, long_str);
for (let i = 0; i < long_str.length / 3 * 4; i++) {
if (Math.floor(i / 4) !== lound) {
lound += 1;
long_int = get_long_int(lound, long_str);
}
let key = i % 4;
let temp_int;
switch (key) {
case 0:
temp_int = (long_int & constant["0"]) >> 18;
result += constant["str"].charAt(temp_int);
break;
case 1:
temp_int = (long_int & constant["1"]) >> 12;
result += constant["str"].charAt(temp_int);
break;
case 2:
temp_int = (long_int & constant["2"]) >> 6;
result += constant["str"].charAt(temp_int);
break;
case 3:
temp_int = long_int & 63;
result += constant["str"].charAt(temp_int);
break;
}
}
return result;
}
function get_long_int(round, long_str) {
round = round * 3;
return long_str.charCodeAt(round) << 16 | long_str.charCodeAt(round + 1) << 8 | long_str.charCodeAt(round + 2);
}
function gener_random(random, option) {
return [
random & 255 & 170 | option[0] & 85,
// 163
random & 255 & 85 | option[0] & 170,
// 87
random >> 8 & 255 & 170 | option[1] & 85,
// 37
random >> 8 & 255 & 85 | option[1] & 170
// 41
];
}
function generate_rc4_bb_str(url_search_params, user_agent, window_env_str, suffix = "cus", Arguments = [0, 1, 14]) {
let sm3 = new SM3();
let start_time = Date.now();
const url_search_params_list = sm3.sum(sm3.sum(url_search_params + suffix));
const cus = sm3.sum(sm3.sum(suffix));
const ua = sm3.sum(result_encrypt(rc4_encrypt(user_agent, String.fromCharCode.apply(null, [390625e-8, 1, 14])), "s3"));
const end_time = Date.now();
let b = {
8: 3,
// 固定
10: end_time,
// 3次加密结束时间
15: {
aid: 6383,
pageId: 6241},
16: start_time,
// 3次加密开始时间
18: 44};
b[20] = b[16] >> 24 & 255;
b[21] = b[16] >> 16 & 255;
b[22] = b[16] >> 8 & 255;
b[23] = b[16] & 255;
b[24] = b[16] / 256 / 256 / 256 / 256 >> 0;
b[25] = b[16] / 256 / 256 / 256 / 256 / 256 >> 0;
b[26] = Arguments[0] >> 24 & 255;
b[27] = Arguments[0] >> 16 & 255;
b[28] = Arguments[0] >> 8 & 255;
b[29] = Arguments[0] & 255;
b[30] = Arguments[1] / 256 & 255;
b[31] = Arguments[1] % 256 & 255;
b[32] = Arguments[1] >> 24 & 255;
b[33] = Arguments[1] >> 16 & 255;
b[34] = Arguments[2] >> 24 & 255;
b[35] = Arguments[2] >> 16 & 255;
b[36] = Arguments[2] >> 8 & 255;
b[37] = Arguments[2] & 255;
b[38] = url_search_params_list[21];
b[39] = url_search_params_list[22];
b[40] = cus[21];
b[41] = cus[22];
b[42] = ua[23];
b[43] = ua[24];
b[44] = b[10] >> 24 & 255;
b[45] = b[10] >> 16 & 255;
b[46] = b[10] >> 8 & 255;
b[47] = b[10] & 255;
b[48] = b[8];
b[49] = b[10] / 256 / 256 / 256 / 256 >> 0;
b[50] = b[10] / 256 / 256 / 256 / 256 / 256 >> 0;
b[51] = b[15].pageId;
b[52] = b[15].pageId >> 24 & 255;
b[53] = b[15].pageId >> 16 & 255;
b[54] = b[15].pageId >> 8 & 255;
b[55] = b[15].pageId & 255;
b[56] = b[15].aid;
b[57] = b[15].aid & 255;
b[58] = b[15].aid >> 8 & 255;
b[59] = b[15].aid >> 16 & 255;
b[60] = b[15].aid >> 24 & 255;
const window_env_list = [];
for (let index = 0; index < window_env_str.length; index++) {
window_env_list.push(window_env_str.charCodeAt(index));
}
b[64] = window_env_list.length;
b[65] = b[64] & 255;
b[66] = b[64] >> 8 & 255;
b[69] = [].length;
b[70] = b[69] & 255;
b[71] = b[69] >> 8 & 255;
b[72] = b[18] ^ b[20] ^ b[26] ^ b[30] ^ b[38] ^ b[40] ^ b[42] ^ b[21] ^ b[27] ^ b[31] ^ b[35] ^ b[39] ^ b[41] ^ b[43] ^ b[22] ^ b[28] ^ b[32] ^ b[36] ^ b[23] ^ b[29] ^ b[33] ^ b[37] ^ b[44] ^ b[45] ^ b[46] ^ b[47] ^ b[48] ^ b[49] ^ b[50] ^ b[24] ^ b[25] ^ b[52] ^ b[53] ^ b[54] ^ b[55] ^ b[57] ^ b[58] ^ b[59] ^ b[60] ^ b[65] ^ b[66] ^ b[70] ^ b[71];
let bb = [
b[18],
b[20],
b[52],
b[26],
b[30],
b[34],
b[58],
b[38],
b[40],
b[53],
b[42],
b[21],
b[27],
b[54],
b[55],
b[31],
b[35],
b[57],
b[39],
b[41],
b[43],
b[22],
b[28],
b[32],
b[60],
b[36],
b[23],
b[29],
b[33],
b[37],
b[44],
b[45],
b[59],
b[46],
b[47],
b[48],
b[49],
b[50],
b[24],
b[25],
b[65],
b[66],
b[70],
b[71]
];
bb = bb.concat(window_env_list).concat(b[72]);
return rc4_encrypt(String.fromCharCode.apply(null, bb), String.fromCharCode.apply(null, [121]));
}
function generate_random_str() {
let random_str_list = [];
random_str_list = random_str_list.concat(gener_random(Math.random() * 1e4, [3, 45]));
random_str_list = random_str_list.concat(gener_random(Math.random() * 1e4, [1, 0]));
random_str_list = random_str_list.concat(gener_random(Math.random() * 1e4, [1, 5]));
return String.fromCharCode.apply(null, random_str_list);
}
var a_bogus_default = (url, user_agent) => {
let result_str = generate_random_str() + generate_rc4_bb_str(new URLSearchParams(new URL(url).search).toString(), user_agent, "1536|747|1536|834|0|30|0|0|1536|834|1536|864|1525|747|24|24|Win32");
return result_encrypt(result_str, "s4") + "=";
};
// src/platform/douyin/sign/index.ts
var headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
};
var douyinSign = class {
/** 生成一个指定长度的随机字符串 */
static Mstoken(length) {
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const randomBytes = crypto.randomBytes(length);
return Array.from(randomBytes, (byte) => characters[byte % characters.length]).join("");
}
/** a_bogus 签名算法 */
static AB(url) {
return a_bogus_default(url, headers["User-Agent"]);
}
/** 生成一个唯一的验证字符串 */
static VerifyFpManager() {
const e = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("");
const t = e.length;
const n = (/* @__PURE__ */ new Date()).getTime().toString(36);
const r = [];
r[8] = "_";
r[13] = "_";
r[18] = "_";
r[23] = "_";
r[14] = "4";
for (let o, i = 0; i < 36; i++) {
if (!r[i]) {
o = 0 | Math.random() * t;
r[i] = e[i === 19 ? 3 & o | 8 : o];
}
}
return "verify_" + n + "_" + r.join("");
}
};
// src/platform/douyin/API.ts
var fp = douyinSign.VerifyFpManager();
var DouyinAPI = class {
\u89C6\u9891\u6216\u56FE\u96C6(data2) {
return `https://www.douyin.com/aweme/v1/web/aweme/detail/?device_platform=webapp&aid=6383&channel=channel_pc_web&aweme_id=${data2.aweme_id}&update_version_code=170400&pc_client_type=1&version_code=190500&version_name=19.5.0&cookie_enabled=true&screen_width=2328&screen_height=1310&browser_language=zh-CN&browser_platform=Win32&browser_name=Chrome&browser_version=125.0.0.0&browser_online=true&engine_name=Blink&engine_version=125.0.0.0&os_name=Windows&os_version=10&cpu_core_num=16&device_memory=8&platform=PC&downlink=10&effective_type=4g&round_trip_time=150&webid=7351848354471872041&msToken=${douyinSign.Mstoken(
116
)}&verifyFp=${fp}&fp=${fp}`;
}
\u8BC4\u8BBA(data2) {
return `https://www.douyin.com/aweme/v1/web/comment/list/?device_platform=webapp&aid=6383&channel=channel_pc_web&aweme_id=${data2.aweme_id}&cursor=${data2.cursor ?? 0}&count=${data2.number ?? 50}&item_type=0&insert_ids=&whale_cut_token=&cut_version=1&rcFT=&pc_client_type=1&version_code=170400&version_name=17.4.0&cookie_enabled=true&screen_width=1552&screen_height=970&browser_language=zh-CN&browser_platform=Win32&browser_name=Chrome&browser_version=125.0.0.0&browser_online=true&engine_name=Blink&engine_version=125.0.0.0&os_name=Windows&os_version=10&cpu_core_num=16&device_memory=8&platform=PC&downlink=10&effective_type=4g&msToken=${douyinSign.Mstoken(
116
)}&verifyFp=${fp}&fp=${fp}`;
}
\u4E8C\u7EA7\u8BC4\u8BBA(data2) {
return `https://www.douyin.com/aweme/v1/web/comment/list/reply/?device_platform=webapp&aid=6383&channel=channel_pc_web&item_id=${data2.aweme_id}&comment_id=${data2.comment_id}&cut_version=1&cursor=${data2.cursor}&count=${data2.number}&item_type=0&update_version_code=170400&pc_client_type=1&pc_libra_divert=Windows&support_h265=1&support_dash=1&version_code=170400&version_name=17.4.0&cookie_enabled=true&screen_width=1552&screen_height=970&browser_language=zh-CN&browser_platform=Win32&browser_name=Edge&browser_version=132.0.0.0&browser_online=true&engine_name=Blink&engine_version=132.0.0.0&os_name=Windows&os_version=10&cpu_core_num=16&device_memory=8&platform=PC&downlink=10&effective_type=4g&round_trip_time=50&webid=7386217876267796006&verifyFp=${fp}&fp=${fp}`;
}
\u52A8\u56FE(data2) {
return `https://www.iesdouyin.com/web/api/v2/aweme/slidesinfo/?reflow_source=reflow_page&web_id=7326472315356857893&device_id=7326472315356857893&aweme_ids=[${data2.aweme_id}]&request_source=200&msToken=${douyinSign.Mstoken(
116
)}&verifyFp=${fp}&fp=${fp}`;
}
\u8868\u60C5() {
return "https://www.douyin.com/aweme/v1/web/emoji/list";
}
\u7528\u6237\u4E3B\u9875\u89C6\u9891(data2) {
return `https://www.douyin.com/aweme/v1/web/aweme/post/?device_platform=webapp&aid=6383&channel=channel_pc_web&sec_user_id=${data2.sec_uid}&max_cursor=0&locate_query=false&show_live_replay_strategy=1&need_time_list=1&time_list_query=0&whale_cut_token=&cut_version=1&count=18&publish_video_strategy_type=2&pc_client_type=1&version_code=170400&version_name=17.4.0&cookie_enabled=true&screen_width=1552&screen_height=970&browser_language=zh-CN&browser_platform=Win32&browser_name=Chrome&browser_version=125.0.0.0&browser_online=true&engine_name=Blink&engine_version=125.0.0.0&os_name=Windows&os_version=10&cpu_core_num=16&device_memory=8&platform=PC&downlink=10&effective_type=4g&round_trip_time=50&webid=7338423850134226495&msToken=${douyinSign.Mstoken(
116
)}&verifyFp=${fp}&fp=${fp}`;
}
\u7528\u6237\u4E3B\u9875\u4FE1\u606F(data2) {
return `https://www.douyin.com/aweme/v1/web/user/profile/other/?device_platform=webapp&aid=6383&channel=channel_pc_web&publish_video_strategy_type=2&source=channel_pc_web&sec_user_id=${data2.sec_uid}&personal_center_strategy=1&pc_client_type=1&version_code=170400&version_name=17.4.0&cookie_enabled=true&screen_width=1552&screen_height=970&browser_language=zh-CN&browser_platform=Win32&browser_name=Chrome&browser_version=125.0.0.0&browser_online=true&engine_name=Blink&engine_version=125.0.0.0&os_name=Windows&os_version=10&cpu_core_num=16&device_memory=8&platform=PC&downlink=10&effective_type=4g&round_trip_time=0&webid=7327957959955580467&msToken=${douyinSign.Mstoken(
116
)}&verifyFp=${fp}&fp=${fp}`;
}
\u70ED\u70B9\u8BCD(data2) {
return `https://www.douyin.com/aweme/v1/web/api/suggest_words/?device_platform=webapp&aid=6383&channel=channel_pc_web&query=${data2.query}&business_id=30088&from_group_id=7129543174929812767&pc_client_type=1&version_code=170400&version_name=17.4.0&cookie_enabled=true&screen_width=1552&screen_height=970&browser_language=zh - CN&browser_platform=Win32&browser_name=Chrome&browser_version=125.0.0.0&browser_online=true&engine_name=Blink&engine_version=125.0.0.0&os_name=Windows&os_version=10&cpu_core_num=16&device_memory=8&platform=PC&downlink=10&effective_type=4g&round_trip_time=50&webid=7327957959955580467&msToken=${douyinSign.Mstoken(
116
)}&verifyFp=${fp}&fp=${fp}`;
}
\u641C\u7D22(data2) {
return `https://www.douyin.com/aweme/v1/web/general/search/single/?device_platform=webapp&aid=6383&channel=channel_pc_web&search_channel=aweme_general&sort_type=0&publish_time=0&keyword=${data2.query}&search_source=normal_search&query_correct_type=1&is_filter_search=0&from_group_id=&offset=0&count=15&pc_client_type=1&version_code=190600&version_name=19.6.0&cookie_enabled=true&screen_width=1552&screen_height=970&browser_language=zh-CN&browser_platform=Win32&browser_name=Chrome&browser_version=125.0.0.0&browser_online=true&engine_name=Blink&engine_version=125.0.0.0&os_name=Windows&os_version=10&cpu_core_num=16&device_memory=8&platform=PC&downlink=10&effective_type=4g&round_trip_time=50&webid=7338423850134226495&msToken=${douyinSign.Mstoken(
116
)}&verifyFp=${fp}&fp=${fp}&search_id=${data2.search_id ?? ""}&count=${data2.number ?? 10}`;
}
\u4E92\u52A8\u8868\u60C5() {
return `https://www.douyin.com/aweme/v1/web/im/strategy/config?device_platform=webapp&aid=1128&channel=channel_pc_web&publish_video_strategy_type=2&app_id=1128&scenes=[%22interactive_resources%22]&pc_client_type=1&version_code=170400&version_name=17.4.0&cookie_enabled=true&screen_width=2328&screen_height=1310&browser_language=zh-CN&browser_platform=Win32&browser_name=Chrome&browser_version=126.0.0.0&browser_online=true&engine_name=Blink&engine_version=126.0.0.0&os_name=Windows&os_version=10&cpu_core_num=16&device_memory=8&platform=PC&downlink=1.5&effective_type=4g&round_trip_time=350&webid=7347329698282833447&msToken=${douyinSign.Mstoken(
116
)}&verifyFp=${fp}&fp=${fp}`;
}
\u80CC\u666F\u97F3\u4E50(data2) {
return `https://www.douyin.com/aweme/v1/web/music/detail/?device_platform=webapp&aid=6383&channel=channel_pc_web&music_id=${data2.music_id}&scene=1&pc_client_type=1&version_code=170400&version_name=17.4.0&cookie_enabled=true&screen_width=2328&screen_height=1310&browser_language=zh-CN&browser_platform=Win32&browser_name=Chrome&browser_version=126.0.0.0&browser_online=true&engine_name=Blink&engine_version=126.0.0.0&os_name=Windows&os_version=10&cpu_core_num=16&device_memory=8&platform=PC&downlink=1.5&effective_type=4g&round_trip_time=350&webid=7347329698282833447&msToken=${douyinSign.Mstoken(
116
)}&verifyFp=${fp}&fp=${fp}`;
}
\u76F4\u64AD\u95F4\u4FE1\u606F(data2) {
return `https://live.douyin.com/webcast/room/web/enter/?aid=6383&app_name=douyin_web&live_id=1&device_platform=web&language=zh-CN&enter_from=web_share_link&cookie_enabled=true&screen_width=2048&screen_height=1152&browser_language=zh-CN&browser_platform=Win32&browser_name=Chrome&browser_version=125.0.0.0&web_rid=${data2.web_rid}&room_id_str=${data2.room_id}&enter_source=&is_need_double_stream=false&insert_task_id=&live_reason=&msToken=${douyinSign.Mstoken(
116
)}&verifyFp=${fp}&fp=${fp}`;
}
\u7533\u8BF7\u4E8C\u7EF4\u7801(data2) {
return `https://sso.douyin.com/get_qrcode/?verifyFp=${data2.verify_fp}&fp=${data2.verify_fp}`;
}
};
var douyinAPI = new DouyinAPI();
// src/platform/douyin/getdata.ts
var defheaders2 = {
accept: "*/*",
priority: "u=0, i",
"content-type": "application/json",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
referer: "https://www.douyin.com/",
"accept-encoding": "gzip, deflate, br",
connection: "keep-alive"
};
var DouyinData = async (data2, cookie) => {
const headers2 = {
...defheaders2,
cookie: cookie ? cookie.replace(/\s+/g, "") : ""
};
switch (data2.methodType) {
case "\u805A\u5408\u89E3\u6790":
case "\u89C6\u9891\u4F5C\u54C1\u6570\u636E":
case "\u56FE\u96C6\u4F5C\u54C1\u6570\u636E":
case "\u5408\u8F91\u4F5C\u54C1\u6570\u636E": {
DouyinValidateData(data2, ["aweme_id"]);
const url = douyinAPI.\u89C6\u9891\u6216\u56FE\u96C6({ aweme_id: data2.aweme_id });
const VideoData = await GlobalGetData2({
url: `${url}&a_bogus=${douyinSign.AB(url)}`,
headers: headers2,
...data2
});
return VideoData;
}
case "\u8BC4\u8BBA\u6570\u636E": {
DouyinValidateData(data2, ["aweme_id"]);
const urlGenerator = (params) => douyinAPI.\u8BC4\u8BBA(params);
const response = await fetchPaginatedData(urlGenerator, data2, 50, headers2);
return response;
}
case "\u6307\u5B9A\u8BC4\u8BBA\u56DE\u590D\u6570\u636E": {
DouyinValidateData(data2, ["aweme_id", "comment_id"]);
const urlGenerator = (params) => douyinAPI.\u4E8C\u7EA7\u8BC4\u8BBA(params);
const response = await fetchPaginatedData(
urlGenerator,
data2,
3,
{
...headers2,
referer: `https://www.douyin.com/note/${data2.aweme_id}`
}
);
return response;
}
case "\u7528\u6237\u4E3B\u9875\u6570\u636E": {
DouyinValidateData(data2, ["sec_uid"]);
const url = douyinAPI.\u7528\u6237\u4E3B\u9875\u4FE1\u606F({ sec_uid: data2.sec_uid });
const UserInfoData = await GlobalGetData2({
url: `${url}&a_bogus=${douyinSign.AB(url)}`,
headers: {
...headers2,
Referer: `https://www.douyin.com/user/${data2.sec_uid}`
},
...data2
});
return UserInfoData;
}
case "Emoji\u6570\u636E": {
const url = douyinAPI.\u8868\u60C5();
const EmojiData = await GlobalGetData2({
url,
headers: headers2,
...data2
});
return EmojiData;
}
case "\u7528\u6237\u4E3B\u9875\u89C6\u9891\u5217\u8868\u6570\u636E": {
DouyinValidateData(data2, ["sec_uid"]);
const url = douyinAPI.\u7528\u6237\u4E3B\u9875\u89C6\u9891({ sec_uid: data2.sec_uid });
const UserVideoListData = await GlobalGetData2({
url: `${url}&a_bogus=${douyinSign.AB(url)}`,
headers: {
...headers2,
Referer: `https://www.douyin.com/user/${data2.sec_uid}`
},
...data2
});
return UserVideoListData;
}
case "\u70ED\u70B9\u8BCD\u6570\u636E": {
DouyinValidateData(data2, ["query"]);
const url = douyinAPI.\u70ED\u70B9\u8BCD({ query: data2.query, number: data2.number ?? 10 });
const SuggestWordsData = await GlobalGetData2({
url: `${url}&a_bogus=${douyinSign.AB(url)}`,
headers: {
...headers2,
Referer: `https://www.douyin.com/search/${encodeURIComponent(String(data2.query))}`
},
...data2
});
return SuggestWordsData;
}
case "\u641C\u7D22\u6570\u636E": {
DouyinValidateData(data2, ["query"]);
let search_id = "";
const maxPageSize = 15;
let fetchedSearchList = [];
let tmpresp = {};
while (fetchedSearchList.length < Number(data2.number ?? 10)) {
const requestCount = Math.min(Number(data2.number ?? 50) - fetchedSearchList.length, maxPageSize);
const url = douyinAPI.\u641C\u7D22({
query: data2.query,
number: requestCount,
search_id: search_id === "" ? void 0 : search_id
});
const response = await GlobalGetData2({
url: `${url}&a_bogus=${douyinSign.AB(url)}`,
headers: {
...headers2,
Referer: `https://www.douyin.com/search/${encodeURIComponent(String(data2.query))}`
},
...data2
});
if (!response.data) {
response.data = [];
}
fetchedSearchList.push(...response.data);
tmpresp = response;
search_id = response.log_pb.impr_id;
}
const finalResponse = {
...tmpresp,
data: data2.number === 0 ? [] : fetchedSearchList.slice(0, Number(data2.number ?? 10))
};
return finalResponse;
}
case "\u52A8\u6001\u8868\u60C5\u6570\u636E": {
const url = douyinAPI.\u4E92\u52A8\u8868\u60C5();
const ExpressionPlusData = await GlobalGetData2({
url: `${url}&a_bogus=${douyinSign.AB(url)}`,
headers: headers2,
...data2
});
return ExpressionPlusData;
}
case "\u97F3\u4E50\u6570\u636E": {
DouyinValidateData(data2, ["music_id"]);
const url = douyinAPI.\u80CC\u666F\u97F3\u4E50({ music_id: data2.music_id });
const MusicData = await GlobalGetData2({
url: `${url}&a_bogus=${douyinSign.AB(url)}`,
headers: headers2,
...data2
});
return MusicData;
}
case "\u76F4\u64AD\u95F4\u4FE1\u606F\u6570\u636E": {
DouyinValidateData(data2, ["sec_uid"]);
let url = douyinAPI.\u7528\u6237\u4E3B\u9875\u4FE1\u606F({ sec_uid: data2.sec_uid });
const UserInfoData = await GlobalGetData2({
url: `${url}&a_bogus=${douyinSign.AB(url)}`,
headers: {
...headers2,
Referer: `https://www.douyin.com/user/${data2.sec_uid}`
},
...data2
});
if (UserInfoData.user.live_status !== 1) logger.error(UserInfoData.user.nickname + "\u672A\u5F00\u542F\u76F4\u64AD\uFF01");
if (!UserInfoData.user.room_data) {
logger.erro