@ikenxuan/amagi 1.5.7 → 1.5.9
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/README.md +5 -6
- package/lib/business/bilibili/API.d.ts +1 -1
- package/lib/business/bilibili/API.js +2 -2
- package/lib/business/bilibili/getdata.js +3 -3
- package/lib/business/bilibili/index.d.ts +2 -2
- package/lib/business/bilibili/index.js +2 -2
- package/lib/business/bilibili/qtparam.js +1 -1
- package/lib/business/bilibili/result.d.ts +1 -1
- package/lib/business/bilibili/sign/wbi.js +3 -3
- package/lib/business/douyin/API.js +1 -1
- package/lib/business/douyin/getdata.js +2 -2
- package/lib/business/douyin/index.d.ts +2 -2
- package/lib/business/douyin/index.js +2 -2
- package/lib/business/douyin/result.d.ts +1 -1
- package/lib/business/douyin/sign/index.js +1 -1
- package/lib/business/index.d.ts +1 -1
- package/lib/business/index.js +1 -1
- package/lib/index.d.ts +3 -4
- package/lib/index.js +3 -4
- package/lib/model/dir.d.ts +1 -1
- package/lib/model/dir.js +1 -1
- package/lib/model/index.d.ts +1 -2
- package/lib/model/index.js +1 -2
- package/lib/model/networks.d.ts +8 -10
- package/lib/model/networks.js +67 -97
- package/lib/server/client.js +21 -3
- package/lib/server/listen.js +2 -3
- package/lib/types/NetworksConfigType.d.ts +1 -1
- package/lib/types/Request.d.ts +1 -1
- package/lib/types/index.d.ts +7 -7
- package/lib/types/index.js +1 -1
- package/package.json +4 -5
- package/lib/model/logger.d.ts +0 -3
- package/lib/model/logger.js +0 -28
package/README.md
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-

|
|
2
|
-
|
|
3
1
|
# amagi(泥干嘛哈哈
|
|
2
|
+
|
|
4
3
|
* 热门平台视频解析 API 基于 Node.js 的实现,支持最低node版本为 v16
|
|
5
4
|
* 抖音、B站
|
|
6
5
|
|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
7
10
|
## 使用
|
|
8
11
|
```
|
|
9
12
|
pnpm add @ikenxuan/amagi
|
|
@@ -24,10 +27,6 @@ await StartClient(client, { port: 4567 })
|
|
|
24
27
|
## 开发构建
|
|
25
28
|
> Node.js版本 <= v18.20.4
|
|
26
29
|
|
|
27
|
-
* 克隆仓库
|
|
28
|
-
```
|
|
29
|
-
git clone git@github.com:ikenxuan/amagi.git
|
|
30
|
-
```
|
|
31
30
|
* 安装依赖
|
|
32
31
|
```
|
|
33
32
|
pnpm install
|
|
@@ -4,7 +4,7 @@ declare class BiLiBiLiAPI {
|
|
|
4
4
|
视频详细信息(data: BilibiliAPIParams['VideoInfoParams']): string;
|
|
5
5
|
视频流信息(data: BilibiliAPIParams['VideoStreamParams']): string;
|
|
6
6
|
/** type参数详见https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/comment/readme.md#评论区类型代码 */
|
|
7
|
-
评论区明细(data
|
|
7
|
+
评论区明细(data: BilibiliAPIParams['CommentParams']): string;
|
|
8
8
|
表情列表(): string;
|
|
9
9
|
番剧明细(data: BilibiliAPIParams['BangumiInfoParams']): string;
|
|
10
10
|
番剧视频流信息(data: BilibiliAPIParams['BangumiStreamParams']): string;
|
|
@@ -9,8 +9,8 @@ class BiLiBiLiAPI {
|
|
|
9
9
|
return `https://api.bilibili.com/x/player/playurl?avid=${data.avid}&cid=${data.cid}`;
|
|
10
10
|
}
|
|
11
11
|
/** type参数详见https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/comment/readme.md#评论区类型代码 */
|
|
12
|
-
评论区明细(data
|
|
13
|
-
return `https://api.bilibili.com/x/v2/reply?sort=1&ps=${data.number}&type=${data.type}&oid=${data.oid}`;
|
|
12
|
+
评论区明细(data) {
|
|
13
|
+
return `https://api.bilibili.com/x/v2/reply?sort=1&ps=${data.number || 20}&type=${data.type}&oid=${data.oid}`;
|
|
14
14
|
}
|
|
15
15
|
表情列表() {
|
|
16
16
|
return 'https://api.bilibili.com/x/emote/user/panel/web?business=reply&web_location=0.0';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BiLiBiLiAPI, qtparam, wbi_sign } from '../../business/bilibili/index.js';
|
|
2
|
-
import { Networks
|
|
2
|
+
import { Networks } from '../../model/index.js';
|
|
3
3
|
export default class BilibiliData {
|
|
4
4
|
type;
|
|
5
5
|
headers;
|
|
@@ -8,7 +8,7 @@ export default class BilibiliData {
|
|
|
8
8
|
this.type = type;
|
|
9
9
|
this.headers = {};
|
|
10
10
|
this.headers.Referer = 'https://api.bilibili.com/';
|
|
11
|
-
this.headers.Cookie = cookie;
|
|
11
|
+
this.headers.Cookie = cookie.replace(/\s+/g, '');
|
|
12
12
|
this.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0';
|
|
13
13
|
}
|
|
14
14
|
async GetData(data = {}) {
|
|
@@ -102,7 +102,7 @@ export default class BilibiliData {
|
|
|
102
102
|
const result = await new Networks(options).getData();
|
|
103
103
|
if (result && result.code !== 0) {
|
|
104
104
|
const errorMessage = errorMap[result.code] || '未知错误';
|
|
105
|
-
|
|
105
|
+
console.error(`响应数据失败!\n请求接口类型:${this.type}\n请求URL:${options.url}\n错误代码:${result.code},\n含义:${errorMessage}`);
|
|
106
106
|
return null;
|
|
107
107
|
}
|
|
108
108
|
else {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import BiLiBiLiAPI from './API.js';
|
|
2
2
|
import BilibiliData from './getdata.js';
|
|
3
3
|
import GetBilibiliID from './getid.js';
|
|
4
|
-
import wbi_sign from './sign/wbi.js';
|
|
5
4
|
import qtparam from './qtparam.js';
|
|
6
5
|
import BilibiliResult from './result.js';
|
|
7
|
-
|
|
6
|
+
import wbi_sign from './sign/wbi.js';
|
|
7
|
+
export { BiLiBiLiAPI, BilibiliData, BilibiliResult, GetBilibiliID, qtparam, wbi_sign };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import BiLiBiLiAPI from './API.js';
|
|
2
2
|
import BilibiliData from './getdata.js';
|
|
3
3
|
import GetBilibiliID from './getid.js';
|
|
4
|
-
import wbi_sign from './sign/wbi.js';
|
|
5
4
|
import qtparam from './qtparam.js';
|
|
6
5
|
import BilibiliResult from './result.js';
|
|
7
|
-
|
|
6
|
+
import wbi_sign from './sign/wbi.js';
|
|
7
|
+
export { BiLiBiLiAPI, BilibiliData, BilibiliResult, GetBilibiliID, qtparam, wbi_sign };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Networks } from '../../model/index.js';
|
|
2
1
|
import { BiLiBiLiAPI, wbi_sign } from '../../business/bilibili/index.js';
|
|
2
|
+
import { Networks } from '../../model/index.js';
|
|
3
3
|
export default async function qtparam(BASEURL, cookie) {
|
|
4
4
|
if (cookie == '')
|
|
5
5
|
return { QUERY: '&platform=html5', STATUS: '!isLogin' };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BilibiliDataType,
|
|
1
|
+
import { BilibiliDataType, BilibiliOptionsType, GetDataResponseType } from '../../types/index.js';
|
|
2
2
|
export default class BilibiliResult {
|
|
3
3
|
type: BilibiliDataType;
|
|
4
4
|
cookie: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import md5 from 'md5';
|
|
2
|
-
import
|
|
2
|
+
import axios from 'axios';
|
|
3
3
|
const mixinKeyEncTab = [
|
|
4
4
|
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,
|
|
5
5
|
17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11, 36, 20, 34, 44, 52
|
|
@@ -29,12 +29,12 @@ function encWbi(params, img_key, sub_key) {
|
|
|
29
29
|
}
|
|
30
30
|
// 获取最新的 img_key 和 sub_key
|
|
31
31
|
async function getWbiKeys(cookie) {
|
|
32
|
-
const res = await
|
|
32
|
+
const res = await axios('https://api.bilibili.com/x/web-interface/nav', {
|
|
33
33
|
headers: {
|
|
34
34
|
Cookie: cookie
|
|
35
35
|
}
|
|
36
36
|
});
|
|
37
|
-
const responseJson =
|
|
37
|
+
const responseJson = res.data;
|
|
38
38
|
const response = responseJson; // 类型断言
|
|
39
39
|
// 确保response是ResponseData类型后再解构
|
|
40
40
|
const { data: { wbi_img: { img_url, sub_url } } } = response;
|
|
@@ -23,7 +23,7 @@ class DouyinAPI {
|
|
|
23
23
|
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=${data.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=${Sign.Mstoken(116)}&verifyFp=${fp}&fp=${fp}`;
|
|
24
24
|
}
|
|
25
25
|
热点词(data) {
|
|
26
|
-
return `https://www.douyin.com/aweme/v1/web/api/suggest_words/?device_platform=webapp&aid=6383&channel=channel_pc_web&query=${
|
|
26
|
+
return `https://www.douyin.com/aweme/v1/web/api/suggest_words/?device_platform=webapp&aid=6383&channel=channel_pc_web&query=${data.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=${Sign.Mstoken(116)}&verifyFp=${fp}&fp=${fp}`;
|
|
27
27
|
}
|
|
28
28
|
搜索(data) {
|
|
29
29
|
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=${data.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=${Sign.Mstoken(116)}&verifyFp=${fp}&fp=${fp}`;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DouyinAPI, Sign } from '../../business/douyin/index.js';
|
|
2
2
|
import { Networks } from '../../model/index.js';
|
|
3
3
|
export default class DouyinData {
|
|
4
4
|
type;
|
|
@@ -8,7 +8,7 @@ export default class DouyinData {
|
|
|
8
8
|
this.type = type;
|
|
9
9
|
this.headers = {
|
|
10
10
|
Referer: 'https://www.douyin.com/',
|
|
11
|
-
Cookie: cookie,
|
|
11
|
+
Cookie: cookie.replace(/\s+/g, ''),
|
|
12
12
|
Accept: '*/*',
|
|
13
13
|
'Content-Type': 'application/json',
|
|
14
14
|
'Accpet-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import DouyinData from './getdata.js';
|
|
2
1
|
import DouyinAPI from './API.js';
|
|
2
|
+
import DouyinData from './getdata.js';
|
|
3
3
|
import GetDouyinID from './getid.js';
|
|
4
4
|
import DouyinResult from './result.js';
|
|
5
5
|
import Sign from './sign/index.js';
|
|
6
|
-
export { DouyinAPI, DouyinData,
|
|
6
|
+
export { DouyinAPI, DouyinData, DouyinResult, GetDouyinID, Sign };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import DouyinData from './getdata.js';
|
|
2
1
|
import DouyinAPI from './API.js';
|
|
2
|
+
import DouyinData from './getdata.js';
|
|
3
3
|
import GetDouyinID from './getid.js';
|
|
4
4
|
import DouyinResult from './result.js';
|
|
5
5
|
import Sign from './sign/index.js';
|
|
6
|
-
export { DouyinAPI, DouyinData,
|
|
6
|
+
export { DouyinAPI, DouyinData, DouyinResult, GetDouyinID, Sign };
|
package/lib/business/index.d.ts
CHANGED
package/lib/business/index.js
CHANGED
package/lib/index.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
export * from "./model/index.js";
|
|
2
1
|
export * from "./business/index.js";
|
|
3
|
-
export * from "./
|
|
2
|
+
export * from "./model/index.js";
|
|
4
3
|
export * from "./server/index.js";
|
|
4
|
+
export * from "./types/index.js";
|
|
5
|
+
export { amagi as Amagi, amagi as default };
|
|
5
6
|
import { client } from "./server/index.js";
|
|
6
7
|
declare const amagi: typeof client;
|
|
7
|
-
export { amagi as default };
|
|
8
|
-
export { amagi as Amagi };
|
package/lib/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
export * from "./model/index.js";
|
|
2
1
|
export * from "./business/index.js";
|
|
3
|
-
export * from "./
|
|
2
|
+
export * from "./model/index.js";
|
|
4
3
|
export * from "./server/index.js";
|
|
4
|
+
export * from "./types/index.js";
|
|
5
|
+
export { amagi as Amagi, amagi as default };
|
|
5
6
|
import { client } from "./server/index.js";
|
|
6
7
|
const amagi = client;
|
|
7
|
-
export { amagi as default };
|
|
8
|
-
export { amagi as Amagi };
|
package/lib/model/dir.d.ts
CHANGED
package/lib/model/dir.js
CHANGED
package/lib/model/index.d.ts
CHANGED
package/lib/model/index.js
CHANGED
package/lib/model/networks.d.ts
CHANGED
|
@@ -1,24 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AxiosRequestConfig, AxiosResponse } from 'axios';
|
|
2
2
|
import { NetworksConfigType } from '../types/index.js';
|
|
3
3
|
interface HeadersObject {
|
|
4
4
|
[key: string]: string;
|
|
5
5
|
}
|
|
6
6
|
export default class Networks {
|
|
7
|
-
url: string
|
|
7
|
+
url: string;
|
|
8
8
|
method: string;
|
|
9
|
-
|
|
9
|
+
headers: HeadersObject;
|
|
10
10
|
type: string;
|
|
11
|
-
body?:
|
|
12
|
-
|
|
11
|
+
body?: any;
|
|
12
|
+
axiosInstance: any;
|
|
13
13
|
isGetResult: boolean;
|
|
14
14
|
timeout: number;
|
|
15
15
|
timer: NodeJS.Timeout | undefined;
|
|
16
16
|
data: {};
|
|
17
|
-
redirect: string;
|
|
18
17
|
constructor(data: NetworksConfigType);
|
|
19
|
-
get config():
|
|
20
|
-
getfetch(): Promise<
|
|
21
|
-
returnResult(): Promise<
|
|
18
|
+
get config(): AxiosRequestConfig;
|
|
19
|
+
getfetch(): Promise<AxiosResponse | boolean>;
|
|
20
|
+
returnResult(): Promise<AxiosResponse>;
|
|
22
21
|
/** 最终地址(跟随重定向) */
|
|
23
22
|
getLongLink(): Promise<string>;
|
|
24
23
|
/** 获取首个302 */
|
|
@@ -33,6 +32,5 @@ export default class Networks {
|
|
|
33
32
|
ToText(): Promise<void>;
|
|
34
33
|
ToArrayBuffer(): Promise<void>;
|
|
35
34
|
ToBlob(): Promise<void>;
|
|
36
|
-
timeoutPromise(timeout: number): Promise<Response>;
|
|
37
35
|
}
|
|
38
36
|
export {};
|
package/lib/model/networks.js
CHANGED
|
@@ -1,48 +1,43 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { logger } from '../model/index.js';
|
|
3
|
-
const controller = new AbortController();
|
|
1
|
+
import axios from 'axios';
|
|
4
2
|
export default class Networks {
|
|
5
3
|
url;
|
|
6
4
|
method;
|
|
7
|
-
|
|
5
|
+
headers;
|
|
8
6
|
type;
|
|
9
7
|
body;
|
|
10
|
-
|
|
8
|
+
axiosInstance;
|
|
11
9
|
isGetResult;
|
|
12
10
|
timeout;
|
|
13
11
|
timer;
|
|
14
12
|
data;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
this.Headers = new Headers();
|
|
18
|
-
if (data.headers && Object.keys(data.headers).length > 0) {
|
|
19
|
-
for (const [key, value] of Object.entries(data.headers)) {
|
|
20
|
-
this.Headers.append(key, value);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
else
|
|
24
|
-
this.Headers = {};
|
|
13
|
+
constructor (data) {
|
|
14
|
+
this.headers = data.headers || {};
|
|
25
15
|
this.url = data.url || '';
|
|
26
16
|
this.type = data.type || 'json';
|
|
27
17
|
this.method = data.method || 'GET';
|
|
28
|
-
this.body = data.body ||
|
|
18
|
+
this.body = data.body || null;
|
|
29
19
|
this.data = {};
|
|
30
|
-
this.timeout = data.timeout ||
|
|
20
|
+
this.timeout = data.timeout || 5000;
|
|
31
21
|
this.isGetResult = false;
|
|
32
22
|
this.timer = undefined;
|
|
33
|
-
|
|
23
|
+
// 创建axios实例
|
|
24
|
+
this.axiosInstance = axios.create({
|
|
25
|
+
timeout: this.timeout,
|
|
26
|
+
headers: this.headers
|
|
27
|
+
});
|
|
34
28
|
}
|
|
35
|
-
get config() {
|
|
36
|
-
let
|
|
37
|
-
|
|
38
|
-
method: this.method
|
|
29
|
+
get config () {
|
|
30
|
+
let config = {
|
|
31
|
+
url: this.url,
|
|
32
|
+
method: this.method,
|
|
33
|
+
headers: this.headers
|
|
39
34
|
};
|
|
40
|
-
if (this.method === 'POST') {
|
|
41
|
-
data =
|
|
35
|
+
if (this.method === 'POST' && this.body) {
|
|
36
|
+
config.data = this.body;
|
|
42
37
|
}
|
|
43
|
-
return
|
|
38
|
+
return config;
|
|
44
39
|
}
|
|
45
|
-
async getfetch() {
|
|
40
|
+
async getfetch () {
|
|
46
41
|
try {
|
|
47
42
|
const result = await this.returnResult();
|
|
48
43
|
if (result.status === 504) {
|
|
@@ -52,41 +47,42 @@ export default class Networks {
|
|
|
52
47
|
return result;
|
|
53
48
|
}
|
|
54
49
|
catch (error) {
|
|
55
|
-
|
|
50
|
+
console.info(error);
|
|
56
51
|
return false;
|
|
57
52
|
}
|
|
58
53
|
}
|
|
59
|
-
async returnResult() {
|
|
60
|
-
return await
|
|
54
|
+
async returnResult () {
|
|
55
|
+
return await this.axiosInstance(this.config);
|
|
61
56
|
}
|
|
62
57
|
/** 最终地址(跟随重定向) */
|
|
63
|
-
async getLongLink() {
|
|
58
|
+
async getLongLink () {
|
|
64
59
|
try {
|
|
65
60
|
const result = await this.returnResult();
|
|
66
|
-
return result.
|
|
61
|
+
return result.request.res.responseUrl; // axios中获取最终的请求URL
|
|
67
62
|
}
|
|
68
63
|
catch (error) {
|
|
69
|
-
|
|
64
|
+
console.error(error);
|
|
70
65
|
return '';
|
|
71
66
|
}
|
|
72
67
|
}
|
|
73
68
|
/** 获取首个302 */
|
|
74
|
-
async getLocation() {
|
|
69
|
+
async getLocation () {
|
|
75
70
|
try {
|
|
76
|
-
const response = await
|
|
71
|
+
const response = await this.axiosInstance({
|
|
77
72
|
method: 'GET',
|
|
78
|
-
|
|
73
|
+
url: this.url,
|
|
74
|
+
maxRedirects: 0, // 禁止跟随重定向
|
|
75
|
+
validateStatus: (status) => status >= 300 && status < 400 // 仅处理3xx响应
|
|
79
76
|
});
|
|
80
|
-
|
|
81
|
-
return response.headers.get('location');
|
|
77
|
+
return response.headers['location'];
|
|
82
78
|
}
|
|
83
79
|
catch (error) {
|
|
84
|
-
|
|
80
|
+
console.error(error);
|
|
85
81
|
return '';
|
|
86
82
|
}
|
|
87
83
|
}
|
|
88
84
|
/** 获取数据并处理数据的格式化,默认json */
|
|
89
|
-
async getData(new_fetch = '') {
|
|
85
|
+
async getData (new_fetch = '') {
|
|
90
86
|
try {
|
|
91
87
|
if (!new_fetch) {
|
|
92
88
|
const result = await this.returnResult();
|
|
@@ -94,14 +90,14 @@ export default class Networks {
|
|
|
94
90
|
return result;
|
|
95
91
|
}
|
|
96
92
|
if (result.status === 429) {
|
|
97
|
-
|
|
93
|
+
console.warn('HTTP 响应状态码: 429');
|
|
98
94
|
throw new Error('ratelimit triggered, 触发 https://www.douyin.com/ 的速率限制!!!');
|
|
99
95
|
}
|
|
100
|
-
this.
|
|
96
|
+
this.axiosInstance = result;
|
|
101
97
|
this.isGetResult = true;
|
|
102
98
|
}
|
|
103
99
|
else {
|
|
104
|
-
this.
|
|
100
|
+
this.axiosInstance = new_fetch;
|
|
105
101
|
}
|
|
106
102
|
switch (this.type) {
|
|
107
103
|
case 'json':
|
|
@@ -118,68 +114,50 @@ export default class Networks {
|
|
|
118
114
|
break;
|
|
119
115
|
default:
|
|
120
116
|
}
|
|
121
|
-
return this.
|
|
117
|
+
return this.axiosInstance;
|
|
122
118
|
}
|
|
123
119
|
catch (error) {
|
|
124
|
-
|
|
120
|
+
console.error(error);
|
|
125
121
|
return false;
|
|
126
122
|
}
|
|
127
123
|
}
|
|
128
124
|
/** 获取响应头 */
|
|
129
|
-
async getHeaders() {
|
|
125
|
+
async getHeaders () {
|
|
130
126
|
try {
|
|
131
|
-
this.
|
|
132
|
-
if (this.
|
|
133
|
-
if (this.
|
|
134
|
-
|
|
135
|
-
const headersObject = {};
|
|
136
|
-
for (const [key, value] of headers.entries()) {
|
|
137
|
-
headersObject[key] = value;
|
|
138
|
-
}
|
|
139
|
-
return headersObject;
|
|
127
|
+
this.axiosInstance = await this.returnResult();
|
|
128
|
+
if (this.axiosInstance) {
|
|
129
|
+
if (this.axiosInstance.headers) {
|
|
130
|
+
return this.axiosInstance.headers;
|
|
140
131
|
}
|
|
141
132
|
else {
|
|
142
|
-
|
|
133
|
+
console.error('未获取到响应头');
|
|
143
134
|
return null;
|
|
144
135
|
}
|
|
145
136
|
}
|
|
146
137
|
else {
|
|
147
|
-
|
|
138
|
+
console.error('未获取到响应对象');
|
|
148
139
|
return null;
|
|
149
140
|
}
|
|
150
141
|
}
|
|
151
142
|
catch (error) {
|
|
152
|
-
|
|
143
|
+
console.error('获取响应头失败:', error);
|
|
153
144
|
return null;
|
|
154
145
|
}
|
|
155
146
|
}
|
|
156
147
|
/** 一次性获取响应头和响应体 */
|
|
157
|
-
async getHeadersAndData() {
|
|
148
|
+
async getHeadersAndData () {
|
|
158
149
|
try {
|
|
159
|
-
|
|
160
|
-
this.fetch = await this.returnResult();
|
|
161
|
-
// 初始化响应头和响应数据
|
|
150
|
+
this.axiosInstance = await this.returnResult();
|
|
162
151
|
let headers = null;
|
|
163
152
|
let data = null;
|
|
164
|
-
if (this.
|
|
165
|
-
|
|
166
|
-
if (this.fetch.headers) {
|
|
167
|
-
headers = {};
|
|
168
|
-
const fetchHeaders = this.fetch.headers;
|
|
169
|
-
for (const [key, value] of fetchHeaders.entries()) {
|
|
170
|
-
headers[key] = value;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
else {
|
|
174
|
-
logger.error('未获取到响应头');
|
|
175
|
-
}
|
|
176
|
-
// 获取响应数据
|
|
153
|
+
if (this.axiosInstance) {
|
|
154
|
+
headers = this.axiosInstance.headers;
|
|
177
155
|
switch (this.type) {
|
|
178
156
|
case 'json':
|
|
179
|
-
data =
|
|
157
|
+
data = this.axiosInstance.data;
|
|
180
158
|
break;
|
|
181
159
|
case 'text':
|
|
182
|
-
data =
|
|
160
|
+
data = this.axiosInstance.data;
|
|
183
161
|
break;
|
|
184
162
|
case 'arrayBuffer':
|
|
185
163
|
data = await this.ToArrayBuffer();
|
|
@@ -191,40 +169,32 @@ export default class Networks {
|
|
|
191
169
|
}
|
|
192
170
|
}
|
|
193
171
|
else {
|
|
194
|
-
|
|
172
|
+
console.error('未获取到响应对象');
|
|
195
173
|
}
|
|
196
174
|
return { headers, data };
|
|
197
175
|
}
|
|
198
176
|
catch (error) {
|
|
199
|
-
|
|
177
|
+
console.error('获取响应头和数据失败:', error);
|
|
200
178
|
return { headers: null, data: null };
|
|
201
179
|
}
|
|
202
180
|
}
|
|
203
|
-
async Tojson() {
|
|
204
|
-
if (this.
|
|
205
|
-
this.
|
|
181
|
+
async Tojson () {
|
|
182
|
+
if (this.axiosInstance.headers['content-type'].includes('json')) {
|
|
183
|
+
this.axiosInstance = this.axiosInstance.data;
|
|
206
184
|
}
|
|
207
185
|
else {
|
|
208
|
-
this.
|
|
186
|
+
this.axiosInstance = this.axiosInstance.data;
|
|
209
187
|
this.type = 'text';
|
|
210
188
|
}
|
|
211
189
|
}
|
|
212
|
-
async ToText() {
|
|
213
|
-
this.
|
|
190
|
+
async ToText () {
|
|
191
|
+
this.axiosInstance = this.axiosInstance.data;
|
|
214
192
|
}
|
|
215
|
-
async ToArrayBuffer() {
|
|
216
|
-
this.
|
|
193
|
+
async ToArrayBuffer () {
|
|
194
|
+
this.axiosInstance = this.axiosInstance.data;
|
|
217
195
|
}
|
|
218
|
-
async ToBlob() {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
timeoutPromise(timeout) {
|
|
222
|
-
return new Promise((resolve, reject) => {
|
|
223
|
-
this.timer = setTimeout(() => {
|
|
224
|
-
logger.info('执行力');
|
|
225
|
-
controller.abort();
|
|
226
|
-
resolve(new Response('timeout', { status: 504, statusText: 'timeout' }));
|
|
227
|
-
}, timeout);
|
|
228
|
-
});
|
|
196
|
+
async ToBlob () {
|
|
197
|
+
// axios 没有直接支持blob, 需要使用arraybuffer然后转换
|
|
198
|
+
this.axiosInstance = new Blob([new Uint8Array(this.axiosInstance.data)]);
|
|
229
199
|
}
|
|
230
200
|
}
|
package/lib/server/client.js
CHANGED
|
@@ -8,7 +8,7 @@ export class client {
|
|
|
8
8
|
*
|
|
9
9
|
* @param cookies 包含抖音和B站cookie的参数对象
|
|
10
10
|
*/
|
|
11
|
-
constructor(cookies) {
|
|
11
|
+
constructor (cookies) {
|
|
12
12
|
/** 抖音ck */
|
|
13
13
|
this.douyin = cookies.douyin;
|
|
14
14
|
/** B站ck */
|
|
@@ -19,8 +19,26 @@ export class client {
|
|
|
19
19
|
* @param log 是否启用日志
|
|
20
20
|
* @returns fastify 实例
|
|
21
21
|
*/
|
|
22
|
-
async initServer(log = false) {
|
|
23
|
-
const client = fastify({
|
|
22
|
+
async initServer (log = false) {
|
|
23
|
+
const client = fastify({
|
|
24
|
+
logger: log && {
|
|
25
|
+
transport: {
|
|
26
|
+
target: 'pino-pretty',
|
|
27
|
+
options: {
|
|
28
|
+
colorize: true,
|
|
29
|
+
translateTime: 'yyyy-MM-dd HH:mm:ss',
|
|
30
|
+
ignore: 'pid,hostname,reqId,res,responseTime,req.hostname,req.method,req.remotePort',
|
|
31
|
+
messageFormat: '{msg}'
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
client.get('/', async (_request, reply) => {
|
|
37
|
+
reply.redirect('https://amagi.apifox.cn', 301);
|
|
38
|
+
});
|
|
39
|
+
client.get('/docs', async (_request, reply) => {
|
|
40
|
+
reply.redirect('https://amagi.apifox.cn', 301);
|
|
41
|
+
});
|
|
24
42
|
client.get('/api/douyin/aweme', async (request, reply) => {
|
|
25
43
|
const url = request.query.url;
|
|
26
44
|
reply.type('application/json').send(await new DouyinResult("VideoData" /* DouyinDataType['单个视频作品数据'] */, this.douyin).result({ url }));
|
package/lib/server/listen.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { logger } from '../model/index.js';
|
|
2
1
|
/**
|
|
3
2
|
* 启动 fastify 实例
|
|
4
3
|
* @param client fastify 实例
|
|
@@ -8,7 +7,7 @@ import { logger } from '../model/index.js';
|
|
|
8
7
|
export const StartClient = async (client, options) => {
|
|
9
8
|
return client.listen({ port: options.port, host: '::' }, (_err, _address) => {
|
|
10
9
|
if (_err)
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
client.log.error(_err);
|
|
11
|
+
console.log(`amagi server listening on ${options.port} port. API docs: https://amagi.apifox.cn`);
|
|
13
12
|
});
|
|
14
13
|
};
|
package/lib/types/Request.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FastifyRequest } from 'fastify';
|
|
2
|
-
import {
|
|
2
|
+
import { BilibiliOptionsType, DouyinOptionsType } from './OptionsType.js';
|
|
3
3
|
export interface DouyinRequest extends FastifyRequest {
|
|
4
4
|
Querystring: DouyinOptionsType;
|
|
5
5
|
}
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type DouyinOptionsType, type BilibiliOptionsType } from './OptionsType.js';
|
|
3
|
-
import { type GetDataResponseType } from './GetDataResponseType.js';
|
|
1
|
+
import { type BilibiliAPIParams } from './BilibiliAPIParams.js';
|
|
4
2
|
import { type ConfigType } from './ConfigType.js';
|
|
5
|
-
import {
|
|
6
|
-
import { DouyinRequest, BilibiliRequest } from './Request.js';
|
|
3
|
+
import { BilibiliDataType, DouyinDataType } from './DataType.js';
|
|
7
4
|
import { type DouyinAPIParams } from './DouyinAPIParams.js';
|
|
8
|
-
import { type
|
|
9
|
-
|
|
5
|
+
import { type GetDataResponseType } from './GetDataResponseType.js';
|
|
6
|
+
import { type NetworksConfigType } from './NetworksConfigType.js';
|
|
7
|
+
import { type BilibiliOptionsType, type DouyinOptionsType } from './OptionsType.js';
|
|
8
|
+
export * from './Request.js';
|
|
9
|
+
export { BilibiliAPIParams, BilibiliDataType, BilibiliOptionsType, ConfigType, DouyinAPIParams, DouyinDataType, DouyinOptionsType, GetDataResponseType, NetworksConfigType };
|
package/lib/types/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export * from './Request.js';
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ikenxuan/amagi",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
7
7
|
"homepage": "https://github.com/ikenxuan/amagi",
|
|
8
8
|
"scripts": {
|
|
9
|
-
"dev": "tsx
|
|
9
|
+
"dev": "tsx watch src/dev.ts",
|
|
10
10
|
"fix": "eslint lib/**/*.js --fix && eslint lib/**/*.d.ts --fix",
|
|
11
11
|
"build": "tsc --project tsconfig.json && tsc-alias -p tsconfig.json && npm run fix"
|
|
12
12
|
},
|
|
@@ -29,14 +29,13 @@
|
|
|
29
29
|
"registry": "https://registry.npmjs.org"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
+
"axios": "^1.7.3",
|
|
32
33
|
"chalk": "^5.3.0",
|
|
33
34
|
"chokidar": "^3.6.0",
|
|
34
35
|
"fastify": "^4.28.1",
|
|
35
36
|
"lodash": "4.17.21",
|
|
36
|
-
"loglevel": "^1.9.1",
|
|
37
|
-
"loglevel-plugin-prefix": "^0.8.4",
|
|
38
37
|
"md5": "^2.3.0",
|
|
39
|
-
"
|
|
38
|
+
"pino-pretty": "^11.2.2"
|
|
40
39
|
},
|
|
41
40
|
"devDependencies": {
|
|
42
41
|
"@types/lodash": "latest",
|
package/lib/model/logger.d.ts
DELETED
package/lib/model/logger.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import log from 'loglevel';
|
|
2
|
-
import prefix from 'loglevel-plugin-prefix';
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
const colors = {
|
|
5
|
-
TRACE: chalk.magenta,
|
|
6
|
-
DEBUG: chalk.cyan,
|
|
7
|
-
INFO: chalk.blue,
|
|
8
|
-
WARN: chalk.yellow,
|
|
9
|
-
ERROR: chalk.red
|
|
10
|
-
};
|
|
11
|
-
prefix.reg(log);
|
|
12
|
-
log.enableAll();
|
|
13
|
-
prefix.apply(log, {
|
|
14
|
-
format(level, name, timestamp) {
|
|
15
|
-
const levelKey = level.toUpperCase();
|
|
16
|
-
if (!(levelKey in colors)) {
|
|
17
|
-
throw new Error(`Invalid log level: ${levelKey}`);
|
|
18
|
-
}
|
|
19
|
-
return `${chalk.gray(`[${timestamp}]`)} ${colors[levelKey](level)} ${chalk.green(`${name}:`)}`;
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
prefix.apply(log.getLogger('critical'), {
|
|
23
|
-
format(level, name, timestamp) {
|
|
24
|
-
return chalk.red.bold(`[${timestamp}] ${level} ${name}:`);
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
const logger = log;
|
|
28
|
-
export default logger;
|