specific-ai-cli 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.en.md +177 -0
- package/README.ja.md +177 -0
- package/README.ko.md +177 -0
- package/README.md +174 -2
- package/README.zh-TW.md +177 -0
- package/assets/banner.txt +3 -0
- package/dist/cli/argv.js +98 -0
- package/dist/cli/commands/auth.js +11 -0
- package/dist/cli/commands/config.js +23 -0
- package/dist/cli/commands/doctor.js +134 -0
- package/dist/cli/commands/platforms.js +24 -0
- package/dist/cli/commands/version.js +4 -0
- package/dist/cli/confirm.js +22 -0
- package/dist/cli/dispatch.js +440 -0
- package/dist/cli/help.js +223 -0
- package/dist/cli/hints.js +60 -0
- package/dist/cli/main.js +18 -0
- package/dist/cli/output.js +66 -0
- package/dist/core/auth-handlers.js +41 -0
- package/dist/core/auth-store.js +119 -0
- package/dist/core/capabilities.js +163 -0
- package/dist/core/config.js +121 -0
- package/dist/core/cookies.js +164 -0
- package/dist/core/errors.js +37 -0
- package/dist/core/files.js +89 -0
- package/dist/core/fsutil.js +52 -0
- package/dist/core/hash.js +4 -0
- package/dist/core/http.js +331 -0
- package/dist/core/image.js +280 -0
- package/dist/core/log.js +40 -0
- package/dist/core/login.js +191 -0
- package/dist/core/mp4.js +130 -0
- package/dist/core/normalize.js +207 -0
- package/dist/core/options.js +110 -0
- package/dist/core/paths.js +38 -0
- package/dist/core/pb.js +59 -0
- package/dist/core/py.js +181 -0
- package/dist/core/rand.js +131 -0
- package/dist/core/registry.js +129 -0
- package/dist/core/schemas.js +41 -0
- package/dist/core/stream.js +104 -0
- package/dist/core/toolkit.js +35 -0
- package/dist/core/vm.js +73 -0
- package/dist/core/vocab.js +157 -0
- package/dist/platforms/_shared/impaas.js +410 -0
- package/dist/platforms/bilibili/index.js +216 -0
- package/dist/platforms/bilibili/web/api.js +806 -0
- package/dist/platforms/bilibili/web/client.js +311 -0
- package/dist/platforms/bilibili/web/commands.js +783 -0
- package/dist/platforms/bilibili/web/ddddocr.js +342 -0
- package/dist/platforms/bilibili/web/gaia.js +130 -0
- package/dist/platforms/bilibili/web/geetest-manual.js +154 -0
- package/dist/platforms/bilibili/web/geetest-vision.js +232 -0
- package/dist/platforms/bilibili/web/geetest.js +450 -0
- package/dist/platforms/bilibili/web/normalize.js +234 -0
- package/dist/platforms/bilibili/web/profile.js +135 -0
- package/dist/platforms/bilibili/web/resolve.js +112 -0
- package/dist/platforms/bilibili/web/sign.js +223 -0
- package/dist/platforms/bilibili/web/upos.js +102 -0
- package/dist/platforms/douyin/index.js +142 -0
- package/dist/platforms/douyin/web/api.js +863 -0
- package/dist/platforms/douyin/web/client.js +413 -0
- package/dist/platforms/douyin/web/commands.js +712 -0
- package/dist/platforms/douyin/web/creator.js +601 -0
- package/dist/platforms/douyin/web/crypto.js +247 -0
- package/dist/platforms/douyin/web/dtrait.js +190 -0
- package/dist/platforms/douyin/web/im.js +502 -0
- package/dist/platforms/douyin/web/image.js +5 -0
- package/dist/platforms/douyin/web/live.js +225 -0
- package/dist/platforms/douyin/web/mssdk.js +148 -0
- package/dist/platforms/douyin/web/normalize.js +326 -0
- package/dist/platforms/douyin/web/passport.js +1247 -0
- package/dist/platforms/douyin/web/profile.js +221 -0
- package/dist/platforms/douyin/web/proto.js +26 -0
- package/dist/platforms/douyin/web/resolve.js +88 -0
- package/dist/platforms/douyin/web/sign.js +436 -0
- package/dist/platforms/douyin/web/tos.js +78 -0
- package/dist/platforms/index.js +17 -0
- package/dist/platforms/jd/index.js +67 -0
- package/dist/platforms/jd/web/aks.js +115 -0
- package/dist/platforms/jd/web/api.js +549 -0
- package/dist/platforms/jd/web/chat.js +132 -0
- package/dist/platforms/jd/web/client.js +470 -0
- package/dist/platforms/jd/web/commands.js +557 -0
- package/dist/platforms/jd/web/jcap/helper.js +90 -0
- package/dist/platforms/jd/web/jcap/host.js +107 -0
- package/dist/platforms/jd/web/jcap/lsd.js +300 -0
- package/dist/platforms/jd/web/jcap/solver.js +995 -0
- package/dist/platforms/jd/web/jcap.js +150 -0
- package/dist/platforms/jd/web/js.js +420 -0
- package/dist/platforms/jd/web/login.js +775 -0
- package/dist/platforms/jd/web/normalize.js +297 -0
- package/dist/platforms/jd/web/profile.js +256 -0
- package/dist/platforms/jd/web/util.js +175 -0
- package/dist/platforms/jd/web/webm.js +133 -0
- package/dist/platforms/kuaishou/index.js +98 -0
- package/dist/platforms/kuaishou/web/api.js +694 -0
- package/dist/platforms/kuaishou/web/captcha-crypto.js +134 -0
- package/dist/platforms/kuaishou/web/captcha-fp.js +180 -0
- package/dist/platforms/kuaishou/web/captcha.js +273 -0
- package/dist/platforms/kuaishou/web/client.js +487 -0
- package/dist/platforms/kuaishou/web/commands.js +863 -0
- package/dist/platforms/kuaishou/web/gap.js +144 -0
- package/dist/platforms/kuaishou/web/gdfp.js +376 -0
- package/dist/platforms/kuaishou/web/gql.js +11 -0
- package/dist/platforms/kuaishou/web/live.js +125 -0
- package/dist/platforms/kuaishou/web/normalize.js +241 -0
- package/dist/platforms/kuaishou/web/oracle.js +329 -0
- package/dist/platforms/kuaishou/web/profile.js +259 -0
- package/dist/platforms/kuaishou/web/resolve.js +84 -0
- package/dist/platforms/kuaishou/web/session.js +592 -0
- package/dist/platforms/kuaishou/web/sign.js +568 -0
- package/dist/platforms/taobao/index.js +56 -0
- package/dist/platforms/taobao/web/api.js +96 -0
- package/dist/platforms/taobao/web/client.js +102 -0
- package/dist/platforms/taobao/web/commands.js +172 -0
- package/dist/platforms/taobao/web/im.js +68 -0
- package/dist/platforms/taobao/web/normalize.js +103 -0
- package/dist/platforms/taobao/web/profile.js +85 -0
- package/dist/platforms/taobao/web/resolve.js +51 -0
- package/dist/platforms/taobao/web/sign.js +35 -0
- package/dist/platforms/tiktok/index.js +120 -0
- package/dist/platforms/tiktok/web/api.js +1234 -0
- package/dist/platforms/tiktok/web/client.js +362 -0
- package/dist/platforms/tiktok/web/commands.js +821 -0
- package/dist/platforms/tiktok/web/im.js +133 -0
- package/dist/platforms/tiktok/web/jsrun.js +126 -0
- package/dist/platforms/tiktok/web/normalize.js +286 -0
- package/dist/platforms/tiktok/web/profile.js +169 -0
- package/dist/platforms/tiktok/web/resolve.js +156 -0
- package/dist/platforms/tiktok/web/sign.js +585 -0
- package/dist/platforms/tiktok/web/upload.js +805 -0
- package/dist/platforms/tiktok/web/wire.js +490 -0
- package/dist/platforms/weibo/index.js +91 -0
- package/dist/platforms/weibo/web/api.js +206 -0
- package/dist/platforms/weibo/web/client.js +155 -0
- package/dist/platforms/weibo/web/commands.js +202 -0
- package/dist/platforms/weibo/web/normalize.js +137 -0
- package/dist/platforms/weibo/web/profile.js +246 -0
- package/dist/platforms/weibo/web/resolve.js +60 -0
- package/dist/platforms/weibo/web/sign.js +85 -0
- package/dist/platforms/x/index.js +107 -0
- package/dist/platforms/x/web/api.js +443 -0
- package/dist/platforms/x/web/article.js +212 -0
- package/dist/platforms/x/web/client.js +202 -0
- package/dist/platforms/x/web/commands.js +363 -0
- package/dist/platforms/x/web/graphql.js +108 -0
- package/dist/platforms/x/web/normalize.js +235 -0
- package/dist/platforms/x/web/profile.js +99 -0
- package/dist/platforms/x/web/resolve.js +44 -0
- package/dist/platforms/x/web/transaction.js +171 -0
- package/dist/platforms/xhs/index.js +101 -0
- package/dist/platforms/xhs/web/api.js +278 -0
- package/dist/platforms/xhs/web/client.js +540 -0
- package/dist/platforms/xhs/web/commands.js +1046 -0
- package/dist/platforms/xhs/web/creator-api.js +609 -0
- package/dist/platforms/xhs/web/creator.js +203 -0
- package/dist/platforms/xhs/web/js.js +194 -0
- package/dist/platforms/xhs/web/login.js +230 -0
- package/dist/platforms/xhs/web/normalize.js +166 -0
- package/dist/platforms/xhs/web/profile.js +127 -0
- package/dist/platforms/xhs/web/push.js +361 -0
- package/dist/platforms/xhs/web/resolve.js +69 -0
- package/dist/platforms/xhs/web/state.js +368 -0
- package/dist/platforms/xianyu/index.js +59 -0
- package/dist/platforms/xianyu/web/api.js +312 -0
- package/dist/platforms/xianyu/web/client.js +134 -0
- package/dist/platforms/xianyu/web/commands.js +305 -0
- package/dist/platforms/xianyu/web/im.js +73 -0
- package/dist/platforms/xianyu/web/normalize.js +123 -0
- package/dist/platforms/xianyu/web/profile.js +146 -0
- package/dist/platforms/xianyu/web/resolve.js +48 -0
- package/dist/platforms/xianyu/web/sign.js +79 -0
- package/package.json +77 -4
- package/static/douyin/Live.proto +194 -0
- package/static/douyin/Request.proto +89 -0
- package/static/douyin/Response.proto +46 -0
- package/static/douyin/acrawler_runtime/ac_vm.js +2 -0
- package/static/douyin/acrawler_runtime/browser_window_shape.json +1 -0
- package/static/douyin/acrawler_runtime/canvas_actual_exact.json +1 -0
- package/static/douyin/acrawler_runtime/run_ac_node.js +1005 -0
- package/static/douyin/acrawler_runtime/runner_window_keys_baseline.txt +240 -0
- package/static/douyin/challenge_profile.json +801 -0
- package/static/douyin/challenge_template_runner.js +217 -0
- package/static/douyin/dtrait_profile.json +66 -0
- package/static/douyin/mstoken_common_profile.json +1 -0
- package/static/douyin/mstoken_profile.json +214 -0
- package/static/jd/h5st5_env.js +750 -0
- package/static/jd/h5st5_lib.js +5 -0
- package/static/jd/h5st5_server.js +49 -0
- package/static/jd/jcap/env/env_core.js +512 -0
- package/static/jd/jcap/env/run.js +1307 -0
- package/static/jd/jcap/run/jcap_ujb96b.js +39 -0
- package/static/jd/package.json +4 -0
- package/static/jd/pc_tk_lib.js +1 -0
- package/static/jd/pc_tk_server.js +63 -0
- package/static/jd/summer_cryptico_runner.js +50 -0
- package/static/jd/webm/env/run.js +453 -0
- package/static/jd/webm/run/jdwebm-riskhandle.js +49 -0
- package/static/kuaishou/bundles/weapon/kwf-0.0.2.2cee19b4b7dec496.js +1 -0
- package/static/kuaishou/bundles/weapon/kws-0-0.0.1-obfuscated.4b7f3de1ab0ddcc2.js +1 -0
- package/static/kuaishou/bundles/weapon/kws-1-0.0.1-obfuscated.346ebdb1c78df316.js +1 -0
- package/static/kuaishou/bundles/weapon/kws-10-0.0.1-obfuscated.a33db41897b983af.js +1 -0
- package/static/kuaishou/bundles/weapon/kws-11-0.0.1-obfuscated.5e0a90af726d8a7e.js +1 -0
- package/static/kuaishou/bundles/weapon/kws-12-0.0.1-obfuscated.20ea29345706ec8c.js +1 -0
- package/static/kuaishou/bundles/weapon/kws-13-0.0.1-obfuscated.6b74e9640ff18648.js +1 -0
- package/static/kuaishou/bundles/weapon/kws-14-0.0.1-obfuscated.551e4429d156bf66.js +1 -0
- package/static/kuaishou/bundles/weapon/kws-15-0.0.1-obfuscated.8625b087aaba4a60.js +1 -0
- package/static/kuaishou/bundles/weapon/kws-16-0.0.1-obfuscated.d5ffa4020f3be99a.js +1 -0
- package/static/kuaishou/bundles/weapon/kws-17-0.0.1-obfuscated.6d13e19b22f50a80.js +1 -0
- package/static/kuaishou/bundles/weapon/kws-18-0.0.1-obfuscated.6d31405044166289.js +1 -0
- package/static/kuaishou/bundles/weapon/kws-19-0.0.1-obfuscated.a9a8d925942f19e4.js +1 -0
- package/static/kuaishou/bundles/weapon/kws-2-0.0.1-obfuscated.b849a136ae4a6b3e.js +1 -0
- package/static/kuaishou/bundles/weapon/kws-3-0.0.1-obfuscated.f9e77ebf6186e2ac.js +1 -0
- package/static/kuaishou/bundles/weapon/kws-4-0.0.1-obfuscated.2c3c155aa52ceb0e.js +1 -0
- package/static/kuaishou/bundles/weapon/kws-5-0.0.1-obfuscated.4e553d17691b3c5a.js +1 -0
- package/static/kuaishou/bundles/weapon/kws-6-0.0.1-obfuscated.f73ddd3ff13e1217.js +1 -0
- package/static/kuaishou/bundles/weapon/kws-7-0.0.1-obfuscated.1628b8729beaab7e.js +1 -0
- package/static/kuaishou/bundles/weapon/kws-8-0.0.1-obfuscated.6da6baef7aa81fff.js +1 -0
- package/static/kuaishou/bundles/weapon/kws-9-0.0.1-obfuscated.8645d55e5323b743.js +1 -0
- package/static/kuaishou/fixtures/current_follow_script_813.network-response +2 -0
- package/static/kuaishou/fixtures/live_ws_maps.json +61 -0
- package/static/kuaishou/fixtures/live_ws_proto.json +1342 -0
- package/static/kuaishou/js/cp-kwf.js +1 -0
- package/static/kuaishou/tools/kwf_oracle.js +799 -0
- package/static/kuaishou/tools/kws_oracle.js +885 -0
- package/static/kuaishou/tools/like_token_oracle.js +70 -0
- package/static/taobao/taobao_js_20260407.js +570 -0
- package/static/tiktok/Tiktok_Request.json +597 -0
- package/static/tiktok/package.json +3 -0
- package/static/tiktok/shop_bsid/core.js +1 -0
- package/static/tiktok/shop_bsid/env_core.js +512 -0
- package/static/tiktok/shop_bsid/loader.js +1 -0
- package/static/tiktok/shop_bsid/run.js +753 -0
- package/static/tiktok/shop_bsid/sign.js +100 -0
- package/static/tiktok/shop_bsid/webmssdk.js +1 -0
- package/static/tiktok/shop_bsid/webmssdk_ex.js +1 -0
- package/static/tiktok/signing/env/env_core.js +512 -0
- package/static/tiktok/signing/env/sign.js +455 -0
- package/static/tiktok/signing/sdk_config.json +230 -0
- package/static/tiktok/signing/source/webmssdk.js +1 -0
- package/static/tiktok/signing/source/webmssdk_ex.js +1 -0
- package/static/tiktok/signing/source/webmssdk_legacy.js +1 -0
- package/static/x/graphql.json +7777 -0
- package/static/x/transaction_l1.json +12 -0
- package/static/xhs/package.json +3 -0
- package/static/xhs/xhs_core/js/b1.js +210 -0
- package/static/xhs/xhs_core/js/mns.js +340 -0
- package/static/xhs/xhs_core/js/mns_0101_keystream.json +5 -0
- package/static/xhs/xhs_core/js/mns_keystreams.json +1 -0
- package/static/xhs/xhs_core/js/sign.js +225 -0
- package/static/xhs/xhs_core/js/websectiga_cli.js +220 -0
- package/static/xhs/xhs_core/js/websectiga_env.js +512 -0
- package/static/xhs/xhs_core/js/xs_common.js +79 -0
- package/static/xhs/xhs_creator/js/profile.js +115 -0
- package/static/xhs/xhs_creator/js/rap_fingerprint_creator.json +6 -0
- package/static/xhs/xhs_creator/js/reference_profile.json +282 -0
- package/static/xhs/xhs_creator/js/xhs_creator_sign.js +29 -0
- package/static/xhs/xhs_creator/js/xhs_creator_signature.js +23 -0
- package/static/xhs/xhs_pc/js/aes_decrypt.js +22 -0
- package/static/xhs/xhs_pc/js/aes_encrypt.js +30 -0
- package/static/xhs/xhs_pc/js/b1.js +9 -0
- package/static/xhs/xhs_pc/js/deflate.js +320 -0
- package/static/xhs/xhs_pc/js/mns.js +4 -0
- package/static/xhs/xhs_pc/js/profile.js +141 -0
- package/static/xhs/xhs_pc/js/rap.js +173 -0
- package/static/xhs/xhs_pc/js/rap_cli.js +30 -0
- package/static/xhs/xhs_pc/js/rap_crypto.js +73 -0
- package/static/xhs/xhs_pc/js/rap_fingerprint_template.json +8 -0
- package/static/xhs/xhs_pc/js/reference_profile.json +262 -0
- package/static/xhs/xhs_pc/js/sign.js +6 -0
- package/static/xhs/xhs_pc/js/web_ssk.js +82 -0
- package/static/xhs/xhs_pc/js/xs_common.js +4 -0
- package/static/xianyu/et_f.js +2 -0
- package/static/xianyu/gen_tfstk.js +410 -0
- package/static/xianyu/goofish_js_version_2.js +568 -0
|
@@ -0,0 +1,806 @@
|
|
|
1
|
+
import { SpecificAIError } from '../../../core/errors.js';
|
|
2
|
+
import {} from '../../../core/http.js';
|
|
3
|
+
import { compactJson, jsonDumps, quote } from '../../../core/py.js';
|
|
4
|
+
import * as rand from '../../../core/rand.js';
|
|
5
|
+
import { API, headers, LIVE_API, MEMBER, ORIGIN, PASSPORT, PROFILE } from './profile.js';
|
|
6
|
+
import { bv2av, dumps, qvId, randomHex } from './sign.js';
|
|
7
|
+
/**
|
|
8
|
+
* 上游 apis/*.py 的请求构造,一个函数对应一个上游方法,字段与顺序照抄(对拍测试逐字节比较)。
|
|
9
|
+
* 返回平台原始 JSON 的 data(`call`)或整个 JSON(`raw`)。
|
|
10
|
+
*/
|
|
11
|
+
const MAIN = ORIGIN.main;
|
|
12
|
+
const VIDEO_SPMID = '333.788.0.0';
|
|
13
|
+
const STATISTICS = '{"appId":100,"platform":5}';
|
|
14
|
+
const STATISTICS_DM = '{"appId":100,"platform":5,"abtest":"","version":""}';
|
|
15
|
+
/** 设置 web_location:已有同名参数时原位替换,否则追加(上游 with_web_location)。 */
|
|
16
|
+
function withLocation(params, value) {
|
|
17
|
+
const i = params.findIndex(([k]) => k === 'web_location');
|
|
18
|
+
if (i >= 0)
|
|
19
|
+
params[i] = ['web_location', value];
|
|
20
|
+
else
|
|
21
|
+
params.push(['web_location', value]);
|
|
22
|
+
return params;
|
|
23
|
+
}
|
|
24
|
+
// ================================================================ 主站(BiliApi)
|
|
25
|
+
export function nav(b) {
|
|
26
|
+
return b.json({ url: `${API}/x/web-interface/nav`, headers: headers('GET', { accept: '*/*' }).get() });
|
|
27
|
+
}
|
|
28
|
+
export async function searchType(b, keyword, order = 'totalrank', page = 1, searchType = 'video') {
|
|
29
|
+
const h = headers('GET', { origin: ORIGIN.search }).referer(`https://search.bilibili.com/all?keyword=${quote(keyword)}`);
|
|
30
|
+
const params = [
|
|
31
|
+
['__refresh__', 'true'],
|
|
32
|
+
['_extra', ''],
|
|
33
|
+
['ad_resource', '5654'],
|
|
34
|
+
['category_id', ''],
|
|
35
|
+
['context', ''],
|
|
36
|
+
['dynamic_offset', (page - 1) * 24],
|
|
37
|
+
['from_source', ''],
|
|
38
|
+
['from_spmid', '333.337'],
|
|
39
|
+
['gaia_vtoken', ''],
|
|
40
|
+
['highlight', 1],
|
|
41
|
+
['keyword', keyword],
|
|
42
|
+
['order', order],
|
|
43
|
+
['page', page],
|
|
44
|
+
['page_size', 42],
|
|
45
|
+
['platform', 'pc'],
|
|
46
|
+
['qv_id', qvId()],
|
|
47
|
+
['search_type', searchType],
|
|
48
|
+
['single_column', 0],
|
|
49
|
+
['source_tag', 3],
|
|
50
|
+
];
|
|
51
|
+
return b.get(`${API}/x/web-interface/wbi/search/type`, { headers: h.get(), query: await b.wbi(withLocation(params, '1430654')) });
|
|
52
|
+
}
|
|
53
|
+
export async function videoInfo(b, bvid) {
|
|
54
|
+
const h = headers('GET').referer(`${MAIN}/video/${bvid}`);
|
|
55
|
+
return b.get(`${API}/x/web-interface/wbi/view`, { headers: h.get(), query: await b.wbi([['bvid', bvid]]) });
|
|
56
|
+
}
|
|
57
|
+
/** 稿件完整信息,含相关推荐 `Related`(上游 get_video_detail)。 */
|
|
58
|
+
export async function videoDetail(b, bvid, page = 1) {
|
|
59
|
+
const h = headers('GET').referer(`${MAIN}/video/${bvid}`);
|
|
60
|
+
const params = withLocation([
|
|
61
|
+
['aid', bv2av(bvid)],
|
|
62
|
+
['p', page],
|
|
63
|
+
['isGaiaAvoided', 'false'],
|
|
64
|
+
['platform', 'web'],
|
|
65
|
+
], '1315873');
|
|
66
|
+
return b.get(`${API}/x/web-interface/wbi/view/detail`, { headers: h.get(), query: await b.wbi(params) });
|
|
67
|
+
}
|
|
68
|
+
export async function playerInfo(b, aid, cid) {
|
|
69
|
+
const h = headers('GET').referer(`${MAIN}/`);
|
|
70
|
+
const params = withLocation([
|
|
71
|
+
['aid', aid],
|
|
72
|
+
['cid', cid],
|
|
73
|
+
['isGaiaAvoided', 'false'],
|
|
74
|
+
], '1315873');
|
|
75
|
+
return b.get(`${API}/x/player/wbi/v2`, { headers: h.get(), query: await b.wbiDm(params) });
|
|
76
|
+
}
|
|
77
|
+
export async function playUrl(b, bvid, cid, qn = 80, fnval = 4048) {
|
|
78
|
+
const h = headers('GET').referer(`${MAIN}/video/${bvid}`);
|
|
79
|
+
const params = [
|
|
80
|
+
['avid', bv2av(bvid)],
|
|
81
|
+
['bvid', bvid],
|
|
82
|
+
['cid', cid],
|
|
83
|
+
['qn', qn],
|
|
84
|
+
['fnver', 0],
|
|
85
|
+
['fnval', fnval],
|
|
86
|
+
['fourk', 1],
|
|
87
|
+
['gaia_source', ''],
|
|
88
|
+
['from_client', 'BROWSER'],
|
|
89
|
+
['is_main_page', 'true'],
|
|
90
|
+
['need_fragment', 'false'],
|
|
91
|
+
['isGaiaAvoided', 'false'],
|
|
92
|
+
['session', randomHex(32)],
|
|
93
|
+
];
|
|
94
|
+
return b.get(`${API}/x/player/wbi/playurl`, { headers: h.get(), query: await b.wbi(withLocation(params, '1315873')) });
|
|
95
|
+
}
|
|
96
|
+
export async function danmakuSeg(b, aid, cid, segment = 1) {
|
|
97
|
+
const h = headers('GET', { accept: '*/*' }).referer(`${MAIN}/`);
|
|
98
|
+
const params = withLocation([
|
|
99
|
+
['type', 1],
|
|
100
|
+
['oid', cid],
|
|
101
|
+
['pid', aid],
|
|
102
|
+
['segment_index', segment],
|
|
103
|
+
['pull_mode', 1],
|
|
104
|
+
['ps', 0],
|
|
105
|
+
['pe', 120000],
|
|
106
|
+
], '1315873');
|
|
107
|
+
return b.bytes({ url: `${API}/x/v2/dm/wbi/web/seg.so`, headers: h.get(), query: await b.wbi(params) });
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* 评论区:type 1 视频(oid 为 aid)、12 专栏(cv 号)、17 动态(动态 ID);mode 3 热门、2 时间。
|
|
111
|
+
* offset 是翻页游标:首页传空串,下一页传上一页响应的 cursor.pagination_reply.next_offset。
|
|
112
|
+
* 旧的页码参数 next 服务端已经不认(cursor.next 恒为 0),只靠它翻页会一直拿到首页。上游 get_replies。
|
|
113
|
+
*/
|
|
114
|
+
export async function replies(b, oid, type = 1, offset = '', mode = 3) {
|
|
115
|
+
const h = headers('GET').referer(`${MAIN}/`);
|
|
116
|
+
const params = [
|
|
117
|
+
['oid', oid],
|
|
118
|
+
['type', type],
|
|
119
|
+
['mode', mode],
|
|
120
|
+
['pagination_str', jsonDumps({ offset }, { separators: [',', ':'] })],
|
|
121
|
+
['plat', 1],
|
|
122
|
+
['seek_rpid', ''],
|
|
123
|
+
];
|
|
124
|
+
return b.get(`${API}/x/v2/reply/wbi/main`, { headers: h.get(), query: await b.wbi(withLocation(params, '1315875')) });
|
|
125
|
+
}
|
|
126
|
+
export async function userInfo(b, mid) {
|
|
127
|
+
const h = headers('GET', { origin: ORIGIN.space }).referer(`https://space.bilibili.com/${mid}`);
|
|
128
|
+
const params = withLocation([
|
|
129
|
+
['mid', mid],
|
|
130
|
+
['token', ''],
|
|
131
|
+
['platform', 'web'],
|
|
132
|
+
], '1550101');
|
|
133
|
+
return b.get(`${API}/x/space/wbi/acc/info`, { headers: h.get(), query: await b.wbiDm(params) });
|
|
134
|
+
}
|
|
135
|
+
export async function userVideos(b, mid, page = 1, pageSize = 42, order = 'pubdate', keyword = '') {
|
|
136
|
+
const h = headers('GET', { origin: ORIGIN.space }).referer(`https://space.bilibili.com/${mid}/video`);
|
|
137
|
+
const params = withLocation([
|
|
138
|
+
['pn', page],
|
|
139
|
+
['ps', pageSize],
|
|
140
|
+
['tid', 0],
|
|
141
|
+
['special_type', ''],
|
|
142
|
+
['order', order],
|
|
143
|
+
['mid', mid],
|
|
144
|
+
['index', 0],
|
|
145
|
+
['keyword', keyword],
|
|
146
|
+
['order_avoided', 'true'],
|
|
147
|
+
['platform', 'web'],
|
|
148
|
+
], '333.1387');
|
|
149
|
+
return b.get(`${API}/x/space/wbi/arc/search`, { headers: h.get(), query: await b.wbiDm(params) });
|
|
150
|
+
}
|
|
151
|
+
export async function rcmdFeed(b, freshIdx = 1, ps = 12, lastShowlist = '') {
|
|
152
|
+
const h = headers('GET').referer(`${MAIN}/`);
|
|
153
|
+
const params = [
|
|
154
|
+
['web_location', '1430650'],
|
|
155
|
+
['y_num', 4],
|
|
156
|
+
['fresh_type', 4],
|
|
157
|
+
['feed_version', 'V8'],
|
|
158
|
+
['fresh_idx_1h', freshIdx],
|
|
159
|
+
['fetch_row', 4],
|
|
160
|
+
['fresh_idx', freshIdx],
|
|
161
|
+
['brush', freshIdx],
|
|
162
|
+
['device', 'win'],
|
|
163
|
+
['homepage_ver', 1],
|
|
164
|
+
['ps', ps],
|
|
165
|
+
['last_y_num', 5],
|
|
166
|
+
['screen', PROFILE.browserResolution],
|
|
167
|
+
['seo_info', ''],
|
|
168
|
+
['tt_exp', ''],
|
|
169
|
+
['last_showlist', lastShowlist],
|
|
170
|
+
['uniq_id', String(rand.randint(10 ** 12, 10 ** 13 - 1))],
|
|
171
|
+
];
|
|
172
|
+
return b.get(`${API}/x/web-interface/wbi/index/top/feed/rcmd`, { headers: h.get(), query: await b.wbi(params) });
|
|
173
|
+
}
|
|
174
|
+
export async function popular(b, page = 1, pageSize = 20) {
|
|
175
|
+
const h = headers('GET').referer(`${MAIN}/v/popular/all/`);
|
|
176
|
+
const params = withLocation([
|
|
177
|
+
['ps', pageSize],
|
|
178
|
+
['pn', page],
|
|
179
|
+
], '333.934');
|
|
180
|
+
return b.get(`${API}/x/web-interface/popular`, { headers: h.get(), query: await b.wbi(params) });
|
|
181
|
+
}
|
|
182
|
+
// ================================================================ 互动(BiliInteractApi)
|
|
183
|
+
function playerFields(paused = false, played = 0) {
|
|
184
|
+
return [
|
|
185
|
+
['eab_x', paused ? 2 : 1],
|
|
186
|
+
['ramval', played],
|
|
187
|
+
['source', 'web_normal'],
|
|
188
|
+
['ga', 1],
|
|
189
|
+
];
|
|
190
|
+
}
|
|
191
|
+
export function like(b, bvid, on = true) {
|
|
192
|
+
const h = headers('FORM').referer(`${MAIN}/video/${bvid}`);
|
|
193
|
+
const form = [
|
|
194
|
+
['aid', bv2av(bvid)],
|
|
195
|
+
['like', on ? 1 : 2],
|
|
196
|
+
['from_spmid', ''],
|
|
197
|
+
['spmid', VIDEO_SPMID],
|
|
198
|
+
['statistics', STATISTICS],
|
|
199
|
+
...playerFields(),
|
|
200
|
+
['csrf', b.csrf],
|
|
201
|
+
];
|
|
202
|
+
return b.post(`${API}/x/web-interface/archive/like`, { headers: h.get(), form });
|
|
203
|
+
}
|
|
204
|
+
export function addCoin(b, bvid, num = 1, alsoLike = false) {
|
|
205
|
+
const h = headers('FORM').referer(`${MAIN}/video/${bvid}`);
|
|
206
|
+
const form = [
|
|
207
|
+
['aid', bv2av(bvid)],
|
|
208
|
+
['multiply', num],
|
|
209
|
+
['select_like', alsoLike ? 1 : 0],
|
|
210
|
+
['cross_domain', 'true'],
|
|
211
|
+
['from_spmid', ''],
|
|
212
|
+
['spmid', VIDEO_SPMID],
|
|
213
|
+
['statistics', STATISTICS],
|
|
214
|
+
...playerFields(),
|
|
215
|
+
['csrf', b.csrf],
|
|
216
|
+
];
|
|
217
|
+
return b.post(`${API}/x/web-interface/coin/add`, { headers: h.get(), form });
|
|
218
|
+
}
|
|
219
|
+
/** 我创建的收藏夹(上游 get_fav_folders),data.list[].id 即收藏时用的 media_id。 */
|
|
220
|
+
export function favFolders(b, mid) {
|
|
221
|
+
const h = headers('GET').referer(`${MAIN}/`);
|
|
222
|
+
const query = [
|
|
223
|
+
['up_mid', mid ?? b.mid],
|
|
224
|
+
['web_location', '333.999'],
|
|
225
|
+
];
|
|
226
|
+
return b.get(`${API}/x/v3/fav/folder/created/list-all`, { headers: h.get(), query });
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* 非上游:同一个接口多带 `type=2&rid=<aid>`(网页端收藏弹窗的请求),每项多一个 fav_state(这个稿件在不在该收藏夹里)。
|
|
230
|
+
* 只给 `item uncollect` 不带 --folder 时找「收着它的收藏夹」用,没有对拍。
|
|
231
|
+
*/
|
|
232
|
+
export function favFoldersOf(b, aid) {
|
|
233
|
+
const h = headers('GET').referer(`${MAIN}/`);
|
|
234
|
+
const query = [
|
|
235
|
+
['up_mid', b.mid],
|
|
236
|
+
['type', 2],
|
|
237
|
+
['rid', aid],
|
|
238
|
+
['web_location', '333.999'],
|
|
239
|
+
];
|
|
240
|
+
return b.get(`${API}/x/v3/fav/folder/created/list-all`, { headers: h.get(), query });
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* 非上游:收藏夹内容(`folder items`)。上游没有这个接口,按网页端收藏夹页的请求补的,没有对拍。
|
|
244
|
+
* media_id 是收藏夹 ID(folder list 的 id)。
|
|
245
|
+
*/
|
|
246
|
+
export function favResources(b, mediaId, page = 1, pageSize = 20) {
|
|
247
|
+
const h = headers('GET').referer('https://space.bilibili.com/');
|
|
248
|
+
const query = [
|
|
249
|
+
['media_id', mediaId],
|
|
250
|
+
['pn', page],
|
|
251
|
+
['ps', pageSize],
|
|
252
|
+
['keyword', ''],
|
|
253
|
+
['order', 'mtime'],
|
|
254
|
+
['type', 0],
|
|
255
|
+
['tid', 0],
|
|
256
|
+
['platform', 'web'],
|
|
257
|
+
['web_location', '333.1387'],
|
|
258
|
+
];
|
|
259
|
+
return b.get(`${API}/x/v3/fav/resource/list`, { headers: h.get(), query });
|
|
260
|
+
}
|
|
261
|
+
export async function favour(b, aid, addMediaIds = '', delMediaIds = '') {
|
|
262
|
+
if (!addMediaIds && !delMediaIds) {
|
|
263
|
+
const folders = (await favFolders(b))?.list ?? [];
|
|
264
|
+
if (!folders.length)
|
|
265
|
+
throw new SpecificAIError('UPSTREAM', '没有可用的收藏夹', { hint: '先在网页端建一个收藏夹,或者用 --folder 指定' });
|
|
266
|
+
addMediaIds = String(folders[0].id);
|
|
267
|
+
}
|
|
268
|
+
const h = headers('FORM').referer(`${MAIN}/`);
|
|
269
|
+
const form = [
|
|
270
|
+
['rid', aid],
|
|
271
|
+
['type', 2],
|
|
272
|
+
];
|
|
273
|
+
if (addMediaIds)
|
|
274
|
+
form.push(['add_media_ids', addMediaIds]);
|
|
275
|
+
if (delMediaIds)
|
|
276
|
+
form.push(['del_media_ids', delMediaIds]);
|
|
277
|
+
form.push(['platform', 'web'], ['from_spmid', ''], ['spmid', VIDEO_SPMID], ['statistics', STATISTICS], ['csrf', b.csrf]);
|
|
278
|
+
return b.post(`${API}/x/v3/fav/resource/deal`, { headers: h.get(), form });
|
|
279
|
+
}
|
|
280
|
+
export function triple(b, bvid) {
|
|
281
|
+
const h = headers('FORM').referer(`${MAIN}/video/${bvid}`);
|
|
282
|
+
const form = [
|
|
283
|
+
['aid', bv2av(bvid)],
|
|
284
|
+
['from_spmid', ''],
|
|
285
|
+
['spmid', VIDEO_SPMID],
|
|
286
|
+
['statistics', STATISTICS],
|
|
287
|
+
...playerFields(),
|
|
288
|
+
['csrf', b.csrf],
|
|
289
|
+
];
|
|
290
|
+
return b.post(`${API}/x/web-interface/archive/like/triple`, { headers: h.get(), form });
|
|
291
|
+
}
|
|
292
|
+
/** 发评论;回复楼中楼时 root 为根评论、parent 为被回复的那条,parent 缺省同 root。 */
|
|
293
|
+
export async function addReply(b, oid, message, type = 1, root = '', parent = '') {
|
|
294
|
+
const h = headers('FORM').referer(`${MAIN}/`);
|
|
295
|
+
const query = await b.wbiDm([]);
|
|
296
|
+
const form = [
|
|
297
|
+
['plat', 1],
|
|
298
|
+
['oid', oid],
|
|
299
|
+
['type', type],
|
|
300
|
+
['message', message],
|
|
301
|
+
['at_name_to_mid', '{}'],
|
|
302
|
+
];
|
|
303
|
+
if (root)
|
|
304
|
+
form.push(['root', root], ['parent', parent || root]);
|
|
305
|
+
form.push(['gaia_source', 'main_web'], ['csrf', b.csrf], ['statistics', STATISTICS]);
|
|
306
|
+
return b.post(`${API}/x/v2/reply/add`, { headers: h.get(), query, form });
|
|
307
|
+
}
|
|
308
|
+
export function deleteReply(b, oid, rpid, type = 1) {
|
|
309
|
+
const h = headers('FORM').referer(`${MAIN}/`);
|
|
310
|
+
const form = [
|
|
311
|
+
['oid', oid],
|
|
312
|
+
['type', type],
|
|
313
|
+
['rpid', rpid],
|
|
314
|
+
['csrf', b.csrf],
|
|
315
|
+
];
|
|
316
|
+
return b.post(`${API}/x/v2/reply/del`, { headers: h.get(), form });
|
|
317
|
+
}
|
|
318
|
+
/** 弹幕的 rnd:会话内自增序号(上游 itertools.count(1)),每条命令从 1 开始。 */
|
|
319
|
+
let dmSeq = 0;
|
|
320
|
+
export async function sendVideoDanmaku(b, aid, cid, message, progress = 0, style = {}) {
|
|
321
|
+
const h = headers('FORM').referer(`${MAIN}/`);
|
|
322
|
+
const query = await b.wbiDm([
|
|
323
|
+
['web_location', '1315873'],
|
|
324
|
+
['csrf', b.csrf],
|
|
325
|
+
]);
|
|
326
|
+
const form = [
|
|
327
|
+
['color', style.color ?? 16777215],
|
|
328
|
+
['fontsize', style.fontsize ?? 25],
|
|
329
|
+
['pool', 0],
|
|
330
|
+
['mode', style.mode ?? 1],
|
|
331
|
+
['type', 1],
|
|
332
|
+
['oid', cid],
|
|
333
|
+
['msg', message],
|
|
334
|
+
['aid', aid],
|
|
335
|
+
['progress', progress],
|
|
336
|
+
['rnd', ++dmSeq],
|
|
337
|
+
['plat', 1],
|
|
338
|
+
['checkbox_type', 0],
|
|
339
|
+
['colorful', ''],
|
|
340
|
+
['gaiasource', 'main_web'],
|
|
341
|
+
['polaris_app_id', 100],
|
|
342
|
+
['polaris_platform', 5],
|
|
343
|
+
['spmid', VIDEO_SPMID],
|
|
344
|
+
['from_spmid', VIDEO_SPMID],
|
|
345
|
+
['statistics', STATISTICS_DM],
|
|
346
|
+
['csrf', b.csrf],
|
|
347
|
+
];
|
|
348
|
+
return b.post(`${API}/x/v2/dm/post`, { headers: h.get(), query, form });
|
|
349
|
+
}
|
|
350
|
+
// ================================================================ 创作(BiliCreatorApi)
|
|
351
|
+
const UPLOAD_PAGE = 'https://member.bilibili.com/platform/upload/video/frame';
|
|
352
|
+
export function archivePre(b) {
|
|
353
|
+
const h = headers('GET', { origin: ORIGIN.member, sameOrigin: true }).referer(UPLOAD_PAGE);
|
|
354
|
+
return b.get(`${MEMBER}/x/vupre/web/archive/pre`, {
|
|
355
|
+
headers: h.get(),
|
|
356
|
+
query: [
|
|
357
|
+
['lang', 'cn'],
|
|
358
|
+
['t', rand.now()],
|
|
359
|
+
],
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
export function myArchives(b, page = 1, pageSize = 20, status = 'is_pubing,pubed,not_pubed') {
|
|
363
|
+
const h = headers('GET', { origin: ORIGIN.member, sameOrigin: true });
|
|
364
|
+
return b.get(`${MEMBER}/x/web/archives`, {
|
|
365
|
+
headers: h.get(),
|
|
366
|
+
query: [
|
|
367
|
+
['status', status],
|
|
368
|
+
['pn', page],
|
|
369
|
+
['ps', pageSize],
|
|
370
|
+
['coop', 1],
|
|
371
|
+
['interactive', 1],
|
|
372
|
+
],
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
export function uploadCover(b, data, suffix) {
|
|
376
|
+
const h = headers('FORM', { origin: ORIGIN.member, sameOrigin: true });
|
|
377
|
+
const form = [
|
|
378
|
+
['cover', `data:image/${suffix};base64,${Buffer.from(data).toString('base64')}`],
|
|
379
|
+
['csrf', b.csrf],
|
|
380
|
+
];
|
|
381
|
+
return b.post(`${MEMBER}/x/vu/web/cover/up`, { headers: h.get(), form });
|
|
382
|
+
}
|
|
383
|
+
export function submitArchive(b, a) {
|
|
384
|
+
const h = headers('POST', { origin: ORIGIN.member, sameOrigin: true }).referer(UPLOAD_PAGE);
|
|
385
|
+
const body = {
|
|
386
|
+
copyright: a.copyright ?? 1,
|
|
387
|
+
source: a.source ?? '',
|
|
388
|
+
cover: a.cover ?? '',
|
|
389
|
+
title: a.title,
|
|
390
|
+
tid: a.tid,
|
|
391
|
+
tag: a.tag,
|
|
392
|
+
desc: a.desc ?? '',
|
|
393
|
+
desc_format_id: 0,
|
|
394
|
+
dynamic: a.dynamic ?? '',
|
|
395
|
+
recreate: -1,
|
|
396
|
+
interactive: 0,
|
|
397
|
+
no_reprint: a.noReprint ?? 1,
|
|
398
|
+
subtitle: { open: 0, lan: '' },
|
|
399
|
+
videos: a.videos.map((v) => ({ filename: v.filename, title: v.title || a.title, desc: v.desc ?? '', cid: v.biz_id ?? null })),
|
|
400
|
+
human_type2: 0,
|
|
401
|
+
topic_id: 0,
|
|
402
|
+
mission_id: 0,
|
|
403
|
+
topic_name: '',
|
|
404
|
+
topic_from: '',
|
|
405
|
+
act_reserve_create: 0,
|
|
406
|
+
is_only_self: a.private === false ? 0 : 1,
|
|
407
|
+
web_os: 2,
|
|
408
|
+
csrf: b.csrf,
|
|
409
|
+
};
|
|
410
|
+
return b.post(`${MEMBER}/x/vu/web/add/v3`, {
|
|
411
|
+
headers: h.get(),
|
|
412
|
+
query: [
|
|
413
|
+
['web_location', '333.1024'],
|
|
414
|
+
['t', rand.now()],
|
|
415
|
+
['csrf', b.csrf],
|
|
416
|
+
],
|
|
417
|
+
json: body,
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
/** 撤稿。平台要求先过极验,不带验证结果固定返回 340022(上游 delete_archive)。 */
|
|
421
|
+
export function deleteArchive(b, aid, gt) {
|
|
422
|
+
const h = headers('FORM', { origin: ORIGIN.member, sameOrigin: true }).referer('https://member.bilibili.com/platform/upload-manager/article');
|
|
423
|
+
const form = [
|
|
424
|
+
['aid', aid],
|
|
425
|
+
['csrf', b.csrf],
|
|
426
|
+
];
|
|
427
|
+
if (gt?.validate)
|
|
428
|
+
form.push(['validate', gt.validate], ['seccode', gt.seccode || `${gt.validate}|jordan`], ['challenge', gt.challenge ?? '']);
|
|
429
|
+
return b.post(`${MEMBER}/x/web/archive/delete`, { headers: h.get(), form });
|
|
430
|
+
}
|
|
431
|
+
export function uploadDynamicImage(b, data, filename, contentType) {
|
|
432
|
+
const h = headers('GET', { origin: ORIGIN.dynamic });
|
|
433
|
+
const multipart = [
|
|
434
|
+
{ name: 'file_up', filename, data, contentType },
|
|
435
|
+
{ name: 'biz', data: 'new_dyn' },
|
|
436
|
+
{ name: 'category', data: 'daily' },
|
|
437
|
+
{ name: 'csrf', data: b.csrf },
|
|
438
|
+
];
|
|
439
|
+
return b.post(`${API}/x/dynamic/feed/draw/upload_bfs`, { headers: h.get(), multipart, timeout: 120 });
|
|
440
|
+
}
|
|
441
|
+
export function createDynamic(b, text, pics) {
|
|
442
|
+
const h = headers('POST', { origin: ORIGIN.dynamic });
|
|
443
|
+
const dynReq = {
|
|
444
|
+
content: { contents: [{ raw_text: text, type: 1, biz_id: '' }] },
|
|
445
|
+
scene: pics.length ? 2 : 1,
|
|
446
|
+
attach_card: null,
|
|
447
|
+
upload_id: `${b.mid}_${rand.nowSeconds()}_${rand.randint(1000, 9999)}`,
|
|
448
|
+
meta: { app_meta: { from: 'create.dynamic.web', mobi_app: 'web' } },
|
|
449
|
+
};
|
|
450
|
+
if (pics.length)
|
|
451
|
+
dynReq.pics = pics;
|
|
452
|
+
return b.post(`${API}/x/dynamic/feed/create/dyn`, {
|
|
453
|
+
headers: h.get(),
|
|
454
|
+
query: [
|
|
455
|
+
['platform', 'web'],
|
|
456
|
+
['csrf', b.csrf],
|
|
457
|
+
],
|
|
458
|
+
json: { dyn_req: dynReq },
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
export function removeDynamic(b, id) {
|
|
462
|
+
const h = headers('POST', { origin: ORIGIN.dynamic });
|
|
463
|
+
return b.post(`${API}/x/dynamic/feed/operate/remove`, { headers: h.get(), query: [['csrf', b.csrf]], json: { dyn_id_str: id } });
|
|
464
|
+
}
|
|
465
|
+
/** 上游 save_article_draft / submit_article 的表单:banner_url(封面)固定为空串,上游没有专栏封面。 */
|
|
466
|
+
function articleForm(b, a) {
|
|
467
|
+
return [
|
|
468
|
+
['title', a.title],
|
|
469
|
+
['content', a.content],
|
|
470
|
+
['summary', a.summary ?? ''],
|
|
471
|
+
['banner_url', ''],
|
|
472
|
+
['category', a.category ?? 0],
|
|
473
|
+
['tags', a.tags ?? ''],
|
|
474
|
+
['list_id', 0],
|
|
475
|
+
['reprint', 0],
|
|
476
|
+
['media_id', 0],
|
|
477
|
+
['spoiler', 0],
|
|
478
|
+
['original', 1],
|
|
479
|
+
['csrf', b.csrf],
|
|
480
|
+
];
|
|
481
|
+
}
|
|
482
|
+
const EDITOR = 'https://member.bilibili.com/read/editor/';
|
|
483
|
+
/** 保存专栏草稿;传 aid 时更新已有草稿。返回的 aid 是草稿 ID。 */
|
|
484
|
+
export function saveArticleDraft(b, a, aid) {
|
|
485
|
+
const h = headers('FORM').referer(EDITOR);
|
|
486
|
+
const form = articleForm(b, a);
|
|
487
|
+
if (aid)
|
|
488
|
+
form.push(['aid', aid]);
|
|
489
|
+
return b.post(`${API}/x/article/creative/draft/addupdate`, { headers: h.get(), form });
|
|
490
|
+
}
|
|
491
|
+
export function submitArticle(b, aid, a) {
|
|
492
|
+
const h = headers('FORM').referer(EDITOR);
|
|
493
|
+
return b.post(`${API}/x/article/creative/article/submit`, { headers: h.get(), form: [['aid', aid], ...articleForm(b, a)] });
|
|
494
|
+
}
|
|
495
|
+
/** 按 ID 读专栏草稿(上游 get_article_draft)。 */
|
|
496
|
+
export function articleDraft(b, aid) {
|
|
497
|
+
return b.get(`${API}/x/article/creative/draft/view`, { headers: headers('GET').referer(EDITOR).get(), query: [['aid', aid]] });
|
|
498
|
+
}
|
|
499
|
+
export function deleteArticleDraft(b, aid) {
|
|
500
|
+
const form = [
|
|
501
|
+
['aid', aid],
|
|
502
|
+
['csrf', b.csrf],
|
|
503
|
+
];
|
|
504
|
+
return b.post(`${API}/x/article/creative/draft/delete`, { headers: headers('FORM').referer(EDITOR).get(), form });
|
|
505
|
+
}
|
|
506
|
+
// ================================================================ 直播(BiliLiveApi)
|
|
507
|
+
const LIVE = ORIGIN.live;
|
|
508
|
+
export function roomInit(b, roomId) {
|
|
509
|
+
const h = headers('GET', { origin: LIVE }).referer(`${LIVE}/${roomId}`);
|
|
510
|
+
return b.get(`${LIVE_API}/room/v1/Room/room_init`, { headers: h.get(), query: [['id', roomId]] });
|
|
511
|
+
}
|
|
512
|
+
export function roomByMid(b, mid) {
|
|
513
|
+
return b.get(`${LIVE_API}/room/v1/Room/getRoomInfoOld`, { headers: headers('GET', { origin: LIVE }).get(), query: [['mid', mid]] });
|
|
514
|
+
}
|
|
515
|
+
export async function roomInfo(b, roomId) {
|
|
516
|
+
const h = headers('GET', { origin: LIVE }).referer(`${LIVE}/${roomId}`);
|
|
517
|
+
const params = withLocation([['room_id', roomId]], '444.8');
|
|
518
|
+
return b.get(`${LIVE_API}/xlive/web-room/v1/index/getInfoByRoom`, { headers: h.get(), query: await b.wbi(params) });
|
|
519
|
+
}
|
|
520
|
+
export async function roomPlayInfo(b, roomId, qn = 0) {
|
|
521
|
+
const h = headers('GET', { origin: LIVE }).referer(`${LIVE}/${roomId}`);
|
|
522
|
+
const params = [
|
|
523
|
+
['room_id', roomId],
|
|
524
|
+
['protocol', '0,1'],
|
|
525
|
+
['format', '0,1,2'],
|
|
526
|
+
['codec', '0,1,2'],
|
|
527
|
+
['qn', qn],
|
|
528
|
+
['platform', 'web'],
|
|
529
|
+
['ptype', 8],
|
|
530
|
+
['dolby', 5],
|
|
531
|
+
['panorama', 1],
|
|
532
|
+
['eotf', '0,1,2'],
|
|
533
|
+
['supported_drms', '0,1,2,3'],
|
|
534
|
+
['req_reason', 0],
|
|
535
|
+
];
|
|
536
|
+
return b.get(`${LIVE_API}/xlive/web-room/v2/index/getRoomPlayInfo`, { headers: h.get(), query: await b.wbi(withLocation(params, '444.8')) });
|
|
537
|
+
}
|
|
538
|
+
export async function danmuInfo(b, roomId) {
|
|
539
|
+
const h = headers('GET', { origin: LIVE }).referer(`${LIVE}/${roomId}`);
|
|
540
|
+
const params = withLocation([
|
|
541
|
+
['id', roomId],
|
|
542
|
+
['type', 0],
|
|
543
|
+
], '444.8');
|
|
544
|
+
return b.get(`${LIVE_API}/xlive/web-room/v1/index/getDanmuInfo`, { headers: h.get(), query: await b.wbi(params) });
|
|
545
|
+
}
|
|
546
|
+
export function danmakuHistory(b, roomId) {
|
|
547
|
+
const h = headers('GET', { origin: LIVE }).referer(`${LIVE}/${roomId}`);
|
|
548
|
+
return b.get(`${LIVE_API}/xlive/web-room/v1/dM/gethistory`, {
|
|
549
|
+
headers: h.get(),
|
|
550
|
+
query: [
|
|
551
|
+
['roomid', roomId],
|
|
552
|
+
['room_type', 0],
|
|
553
|
+
],
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
export async function giftList(b, roomId, areaParentId, areaId, ruid) {
|
|
557
|
+
const h = headers('GET', { origin: LIVE }).referer(`${LIVE}/${roomId}`);
|
|
558
|
+
const params = [
|
|
559
|
+
['platform', 'pc'],
|
|
560
|
+
['room_id', roomId],
|
|
561
|
+
['area_parent_id', areaParentId],
|
|
562
|
+
['area_id', areaId],
|
|
563
|
+
['source', 'live'],
|
|
564
|
+
['build', 0],
|
|
565
|
+
['ruid', ruid],
|
|
566
|
+
['base_version', 0],
|
|
567
|
+
['receive_users', ''],
|
|
568
|
+
];
|
|
569
|
+
return b.get(`${LIVE_API}/xlive/web-room/v1/giftPanel/roomGiftList`, { headers: h.get(), query: await b.wbi(withLocation(params, '444.8')) });
|
|
570
|
+
}
|
|
571
|
+
export function areaList(b) {
|
|
572
|
+
return b.get(`${LIVE_API}/xlive/web-interface/v1/index/getWebAreaList`, { headers: headers('GET', { origin: LIVE }).get(), query: [['source_id', 2]] });
|
|
573
|
+
}
|
|
574
|
+
export function bagList(b, roomId) {
|
|
575
|
+
const h = headers('GET', { origin: LIVE }).referer(`${LIVE}/${roomId}`);
|
|
576
|
+
return b.get(`${LIVE_API}/xlive/web-room/v1/gift/bag_list`, {
|
|
577
|
+
headers: h.get(),
|
|
578
|
+
query: [
|
|
579
|
+
['t', rand.now()],
|
|
580
|
+
['room_id', roomId],
|
|
581
|
+
],
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
export function sendGift(b, roomId, ruid, giftId, giftNum = 1, bagId = 0, coinType = 'silver', price = 0) {
|
|
585
|
+
const path = bagId && bagId !== '0' ? '/xlive/revenue/v2/gift/sendBagMultiUser' : coinType === 'gold' ? '/xlive/revenue/v2/gift/sendGoldMultiUser' : '/xlive/revenue/v2/gift/sendSilverMultiUser';
|
|
586
|
+
const h = headers('FORM', { origin: LIVE }).referer(`${LIVE}/${roomId}`);
|
|
587
|
+
const query = [
|
|
588
|
+
['uid', b.mid],
|
|
589
|
+
['gift_id', giftId],
|
|
590
|
+
['ruid', ruid],
|
|
591
|
+
['send_ruid', 0],
|
|
592
|
+
['gift_num', giftNum],
|
|
593
|
+
['coin_type', coinType],
|
|
594
|
+
['bag_id', bagId],
|
|
595
|
+
['platform', 'pc'],
|
|
596
|
+
['biz_code', 'Live'],
|
|
597
|
+
['biz_id', roomId],
|
|
598
|
+
['storm_beat_id', 0],
|
|
599
|
+
['metadata', ''],
|
|
600
|
+
['price', price],
|
|
601
|
+
['receive_users', dumps([{ uid: Number(ruid) }])],
|
|
602
|
+
['all_flag', 1],
|
|
603
|
+
[
|
|
604
|
+
'live_statistics',
|
|
605
|
+
dumps({
|
|
606
|
+
pc_client: 'pc_web',
|
|
607
|
+
jumpfrom: '-99998',
|
|
608
|
+
room_category: '-99998',
|
|
609
|
+
source_event: 0,
|
|
610
|
+
official_channel: { program_room_id: '-99998', program_up_id: '-99998' },
|
|
611
|
+
}),
|
|
612
|
+
],
|
|
613
|
+
['statistics', dumps({ platform: 5, pc_client: 'pc_web', appId: 100 })],
|
|
614
|
+
['web_location', '444.8'],
|
|
615
|
+
['csrf_token', b.csrf],
|
|
616
|
+
['csrf', b.csrf],
|
|
617
|
+
['visit_id', ''],
|
|
618
|
+
];
|
|
619
|
+
return b.post(`${LIVE_API}${path}`, { headers: h.get(), query });
|
|
620
|
+
}
|
|
621
|
+
export async function sendLiveDanmaku(b, roomId, msg, style = {}) {
|
|
622
|
+
const h = headers('GET', { origin: LIVE }).referer(`${LIVE}/${roomId}`);
|
|
623
|
+
const query = await b.wbi([['web_location', '444.8']]);
|
|
624
|
+
const fields = [
|
|
625
|
+
['bubble', 0],
|
|
626
|
+
['msg', msg],
|
|
627
|
+
['color', style.color ?? 16777215],
|
|
628
|
+
['mode', style.mode ?? 1],
|
|
629
|
+
['room_type', 0],
|
|
630
|
+
['jumpfrom', 0],
|
|
631
|
+
['reply_mid', style.replyMid ?? 0],
|
|
632
|
+
['reply_attr', 0],
|
|
633
|
+
['replay_dmid', ''],
|
|
634
|
+
['statistics', STATISTICS],
|
|
635
|
+
['reply_type', 0],
|
|
636
|
+
['reply_uname', style.replyUname ?? ''],
|
|
637
|
+
['data_extend', dumps({ trackid: '-99998' })],
|
|
638
|
+
['fontsize', style.fontsize ?? 25],
|
|
639
|
+
['rnd', rand.nowSeconds()],
|
|
640
|
+
['roomid', roomId],
|
|
641
|
+
['csrf', b.csrf],
|
|
642
|
+
['csrf_token', b.csrf],
|
|
643
|
+
];
|
|
644
|
+
const multipart = fields.map(([name, value]) => ({ name, data: String(value) }));
|
|
645
|
+
return b.post(`${LIVE_API}/msg/send`, { headers: h.get(), query, multipart });
|
|
646
|
+
}
|
|
647
|
+
export function startLive(b, roomId, areaV2, platform = 'pc_link') {
|
|
648
|
+
const h = headers('FORM', { origin: LIVE }).referer(`${LIVE}/${roomId}`);
|
|
649
|
+
const form = [
|
|
650
|
+
['room_id', roomId],
|
|
651
|
+
['platform', platform],
|
|
652
|
+
['area_v2', areaV2],
|
|
653
|
+
['backup_stream', 0],
|
|
654
|
+
['csrf', b.csrf],
|
|
655
|
+
['csrf_token', b.csrf],
|
|
656
|
+
];
|
|
657
|
+
return b.post(`${LIVE_API}/room/v1/Room/startLive`, { headers: h.get(), form });
|
|
658
|
+
}
|
|
659
|
+
export function stopLive(b, roomId, platform = 'pc_link') {
|
|
660
|
+
const h = headers('FORM', { origin: LIVE }).referer(`${LIVE}/${roomId}`);
|
|
661
|
+
const form = [
|
|
662
|
+
['room_id', roomId],
|
|
663
|
+
['platform', platform],
|
|
664
|
+
['csrf', b.csrf],
|
|
665
|
+
['csrf_token', b.csrf],
|
|
666
|
+
];
|
|
667
|
+
return b.post(`${LIVE_API}/room/v1/Room/stopLive`, { headers: h.get(), form });
|
|
668
|
+
}
|
|
669
|
+
// ================================================================ 登录(BiliLoginApi)
|
|
670
|
+
const LOCALE_JSON = compactJson({ c_locale: { language: 'zh', region: 'CN' }, always_translate: true });
|
|
671
|
+
function passportParams(params) {
|
|
672
|
+
const merged = [...params];
|
|
673
|
+
if (!merged.some(([k]) => k === 'web_location'))
|
|
674
|
+
merged.push(['web_location', '333.1228']);
|
|
675
|
+
merged.push(['x-bili-redirect', 1], ['x-bili-locale-json', LOCALE_JSON]);
|
|
676
|
+
return merged;
|
|
677
|
+
}
|
|
678
|
+
const PASSPORT_BARE = [
|
|
679
|
+
['x-bili-redirect', 1],
|
|
680
|
+
['x-bili-locale-json', LOCALE_JSON],
|
|
681
|
+
];
|
|
682
|
+
function passportHeaders(type = 'GET') {
|
|
683
|
+
return headers(type, { origin: PASSPORT, accept: '*/*', sameOrigin: true }).set('accept-language', 'zh-CN,zh;q=0.9').referer(`${PASSPORT}/login`).get();
|
|
684
|
+
}
|
|
685
|
+
export function qrcodeGenerate(b) {
|
|
686
|
+
return b.json({
|
|
687
|
+
url: `${PASSPORT}/x/passport-login/web/qrcode/generate`,
|
|
688
|
+
headers: passportHeaders(),
|
|
689
|
+
query: passportParams([
|
|
690
|
+
['source', 'main_web'],
|
|
691
|
+
['go_url', ''],
|
|
692
|
+
]),
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
export function qrcodePoll(b, qrcodeKey, bRet) {
|
|
696
|
+
const query = passportParams([
|
|
697
|
+
['qrcode_key', qrcodeKey],
|
|
698
|
+
['source', 'main_web'],
|
|
699
|
+
]);
|
|
700
|
+
if (bRet)
|
|
701
|
+
query.push(['b_ret', bRet]);
|
|
702
|
+
return b.json({
|
|
703
|
+
url: `${PASSPORT}/x/passport-login/web/qrcode/poll`,
|
|
704
|
+
headers: passportHeaders(),
|
|
705
|
+
query,
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
export function captcha(b) {
|
|
709
|
+
return b.json({
|
|
710
|
+
url: `${PASSPORT}/x/passport-login/captcha`,
|
|
711
|
+
headers: passportHeaders(),
|
|
712
|
+
query: passportParams([['source', 'main-fe']]),
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
export function smsSend(b, tel, gt, cid = 86) {
|
|
716
|
+
const form = [
|
|
717
|
+
['source', 'main_web'],
|
|
718
|
+
['tel', tel],
|
|
719
|
+
['cid', cid],
|
|
720
|
+
['go_url', ''],
|
|
721
|
+
['token', gt.token],
|
|
722
|
+
['validate', gt.validate],
|
|
723
|
+
['seccode', gt.seccode || `${gt.validate}|jordan`],
|
|
724
|
+
['challenge', gt.challenge],
|
|
725
|
+
];
|
|
726
|
+
return b.json({
|
|
727
|
+
method: 'POST',
|
|
728
|
+
url: `${PASSPORT}/x/passport-login/web/sms/send`,
|
|
729
|
+
headers: passportHeaders('FORM'),
|
|
730
|
+
query: PASSPORT_BARE,
|
|
731
|
+
form,
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
export function smsLogin(b, tel, code, captchaKey, cid = 86) {
|
|
735
|
+
const form = [
|
|
736
|
+
['source', 'main_web'],
|
|
737
|
+
['captcha_key', captchaKey],
|
|
738
|
+
['cid', cid],
|
|
739
|
+
['tel', tel],
|
|
740
|
+
['code', code],
|
|
741
|
+
['go_url', ''],
|
|
742
|
+
];
|
|
743
|
+
return b.json({
|
|
744
|
+
method: 'POST',
|
|
745
|
+
url: `${PASSPORT}/x/passport-login/web/login/sms`,
|
|
746
|
+
headers: passportHeaders('FORM'),
|
|
747
|
+
query: PASSPORT_BARE,
|
|
748
|
+
form,
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
export function loginKey(b) {
|
|
752
|
+
const h = headers('GET', { origin: PASSPORT }).referer(`${PASSPORT}/login`);
|
|
753
|
+
return b.json({ url: `${PASSPORT}/x/passport-login/web/key`, headers: h.get() });
|
|
754
|
+
}
|
|
755
|
+
export function passwordLogin(b, username, encPassword, gt) {
|
|
756
|
+
const h = headers('FORM', { origin: PASSPORT }).referer(`${PASSPORT}/login`);
|
|
757
|
+
const form = [
|
|
758
|
+
['username', username],
|
|
759
|
+
['password', encPassword],
|
|
760
|
+
['keep', 0],
|
|
761
|
+
['token', gt.token],
|
|
762
|
+
['challenge', gt.challenge],
|
|
763
|
+
['validate', gt.validate],
|
|
764
|
+
['seccode', gt.seccode || `${gt.validate}|jordan`],
|
|
765
|
+
['source', 'main-fe-header'],
|
|
766
|
+
['go_url', 'https://www.bilibili.com/'],
|
|
767
|
+
];
|
|
768
|
+
return b.json({ method: 'POST', url: `${PASSPORT}/x/passport-login/web/login`, headers: h.get(), form });
|
|
769
|
+
}
|
|
770
|
+
export function cookieInfo(b) {
|
|
771
|
+
return b.json({
|
|
772
|
+
url: `${PASSPORT}/x/passport-login/web/cookie/info`,
|
|
773
|
+
headers: headers('GET', { origin: PASSPORT }).get(),
|
|
774
|
+
query: [
|
|
775
|
+
['web_location', '333.788'],
|
|
776
|
+
['csrf', b.csrf],
|
|
777
|
+
],
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
export async function refreshCsrf(b, correspondPath) {
|
|
781
|
+
const h = headers('DOC').remove('sec-fetch-user').set('sec-fetch-site', 'same-origin').set('sec-fetch-dest', 'iframe');
|
|
782
|
+
h.insertBefore('accept-encoding', 'referer', 'https://www.bilibili.com/');
|
|
783
|
+
const res = await b.request({ url: `https://www.bilibili.com/correspond/1/${correspondPath}`, headers: h.get() });
|
|
784
|
+
if (res.status !== 200)
|
|
785
|
+
return '';
|
|
786
|
+
return /id="1-name"[^>]*>\s*([^<\s]+)\s*</.exec(await res.text())?.[1] ?? '';
|
|
787
|
+
}
|
|
788
|
+
export function cookieRefresh(b, refreshCsrf, refreshToken) {
|
|
789
|
+
const form = [
|
|
790
|
+
['csrf', b.csrf],
|
|
791
|
+
['refresh_csrf', refreshCsrf],
|
|
792
|
+
['source', 'main_web'],
|
|
793
|
+
['refresh_token', refreshToken],
|
|
794
|
+
];
|
|
795
|
+
return b.json({ method: 'POST', url: `${PASSPORT}/x/passport-login/web/cookie/refresh`, headers: headers('FORM').get(), form });
|
|
796
|
+
}
|
|
797
|
+
export function confirmRefresh(b, oldRefreshToken) {
|
|
798
|
+
const form = [
|
|
799
|
+
['csrf', b.csrf],
|
|
800
|
+
['refresh_token', oldRefreshToken],
|
|
801
|
+
];
|
|
802
|
+
return b.json({ method: 'POST', url: `${PASSPORT}/x/passport-login/web/confirm/refresh`, headers: headers('FORM').get(), form });
|
|
803
|
+
}
|
|
804
|
+
export function logout(b) {
|
|
805
|
+
return b.json({ method: 'POST', url: `${PASSPORT}/login/exit/v2`, headers: headers('FORM', { origin: PASSPORT }).get(), form: [['biliCSRF', b.csrf]] });
|
|
806
|
+
}
|