@book000/pixivts 0.48.58 → 0.48.59
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/dist/checks.d.ts +19 -0
- package/dist/checks.d.ts.map +1 -0
- package/dist/checks.js +85 -0
- package/dist/checks.js.map +1 -0
- package/dist/checks.test.d.ts +2 -0
- package/dist/checks.test.d.ts.map +1 -0
- package/dist/checks.test.js +306 -0
- package/dist/checks.test.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/options.d.ts +248 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +154 -0
- package/dist/options.js.map +1 -0
- package/dist/options.test.d.ts +2 -0
- package/dist/options.test.d.ts.map +1 -0
- package/dist/options.test.js +117 -0
- package/dist/options.test.js.map +1 -0
- package/dist/pixiv.d.ts +292 -0
- package/dist/pixiv.d.ts.map +1 -0
- package/dist/pixiv.js +759 -0
- package/dist/pixiv.js.map +1 -0
- package/dist/pixiv.test.d.ts +2 -0
- package/dist/pixiv.test.d.ts.map +1 -0
- package/dist/pixiv.test.js +705 -0
- package/dist/pixiv.test.js.map +1 -0
- package/dist/saving-responses/index.d.ts +119 -0
- package/dist/saving-responses/index.d.ts.map +1 -0
- package/dist/saving-responses/index.js +263 -0
- package/dist/saving-responses/index.js.map +1 -0
- package/dist/saving-responses/index.test.d.ts +2 -0
- package/dist/saving-responses/index.test.d.ts.map +1 -0
- package/dist/saving-responses/index.test.js +469 -0
- package/dist/saving-responses/index.test.js.map +1 -0
- package/dist/saving-responses/response-entity.d.ts +16 -0
- package/dist/saving-responses/response-entity.d.ts.map +1 -0
- package/dist/saving-responses/response-entity.js +101 -0
- package/dist/saving-responses/response-entity.js.map +1 -0
- package/dist/types/endpoints/v1/illust/bookmark/delete.d.ts +14 -0
- package/dist/types/endpoints/v1/illust/bookmark/delete.d.ts.map +1 -0
- package/dist/types/endpoints/v1/illust/bookmark/delete.js +3 -0
- package/dist/types/endpoints/v1/illust/bookmark/delete.js.map +1 -0
- package/dist/types/endpoints/v1/illust/detail.d.ts +25 -0
- package/dist/types/endpoints/v1/illust/detail.d.ts.map +1 -0
- package/dist/types/endpoints/v1/illust/detail.js +20 -0
- package/dist/types/endpoints/v1/illust/detail.js.map +1 -0
- package/dist/types/endpoints/v1/illust/ranking.d.ts +51 -0
- package/dist/types/endpoints/v1/illust/ranking.d.ts.map +1 -0
- package/dist/types/endpoints/v1/illust/ranking.js +40 -0
- package/dist/types/endpoints/v1/illust/ranking.js.map +1 -0
- package/dist/types/endpoints/v1/illust/recommended.d.ts +85 -0
- package/dist/types/endpoints/v1/illust/recommended.d.ts.map +1 -0
- package/dist/types/endpoints/v1/illust/recommended.js +37 -0
- package/dist/types/endpoints/v1/illust/recommended.js.map +1 -0
- package/dist/types/endpoints/v1/illust/series.d.ts +45 -0
- package/dist/types/endpoints/v1/illust/series.d.ts.map +1 -0
- package/dist/types/endpoints/v1/illust/series.js +31 -0
- package/dist/types/endpoints/v1/illust/series.js.map +1 -0
- package/dist/types/endpoints/v1/illust/ugoira/metadata.d.ts +25 -0
- package/dist/types/endpoints/v1/illust/ugoira/metadata.d.ts.map +1 -0
- package/dist/types/endpoints/v1/illust/ugoira/metadata.js +20 -0
- package/dist/types/endpoints/v1/illust/ugoira/metadata.js.map +1 -0
- package/dist/types/endpoints/v1/manga/recommended.d.ts +72 -0
- package/dist/types/endpoints/v1/manga/recommended.d.ts.map +1 -0
- package/dist/types/endpoints/v1/manga/recommended.js +33 -0
- package/dist/types/endpoints/v1/manga/recommended.js.map +1 -0
- package/dist/types/endpoints/v1/novel/bookmark/delete.d.ts +14 -0
- package/dist/types/endpoints/v1/novel/bookmark/delete.d.ts.map +1 -0
- package/dist/types/endpoints/v1/novel/bookmark/delete.js +3 -0
- package/dist/types/endpoints/v1/novel/bookmark/delete.js.map +1 -0
- package/dist/types/endpoints/v1/novel/ranking.d.ts +47 -0
- package/dist/types/endpoints/v1/novel/ranking.d.ts.map +1 -0
- package/dist/types/endpoints/v1/novel/ranking.js +39 -0
- package/dist/types/endpoints/v1/novel/ranking.js.map +1 -0
- package/dist/types/endpoints/v1/novel/recommended.d.ts +72 -0
- package/dist/types/endpoints/v1/novel/recommended.d.ts.map +1 -0
- package/dist/types/endpoints/v1/novel/recommended.js +32 -0
- package/dist/types/endpoints/v1/novel/recommended.js.map +1 -0
- package/dist/types/endpoints/v1/novel/related.d.ts +37 -0
- package/dist/types/endpoints/v1/novel/related.d.ts.map +1 -0
- package/dist/types/endpoints/v1/novel/related.js +24 -0
- package/dist/types/endpoints/v1/novel/related.js.map +1 -0
- package/dist/types/endpoints/v1/search/illust.d.ts +90 -0
- package/dist/types/endpoints/v1/search/illust.d.ts.map +1 -0
- package/dist/types/endpoints/v1/search/illust.js +35 -0
- package/dist/types/endpoints/v1/search/illust.js.map +1 -0
- package/dist/types/endpoints/v1/search/novel.d.ts +90 -0
- package/dist/types/endpoints/v1/search/novel.d.ts.map +1 -0
- package/dist/types/endpoints/v1/search/novel.js +35 -0
- package/dist/types/endpoints/v1/search/novel.js.map +1 -0
- package/dist/types/endpoints/v1/user/bookmarks/illust.d.ts +48 -0
- package/dist/types/endpoints/v1/user/bookmarks/illust.d.ts.map +1 -0
- package/dist/types/endpoints/v1/user/bookmarks/illust.js +31 -0
- package/dist/types/endpoints/v1/user/bookmarks/illust.js.map +1 -0
- package/dist/types/endpoints/v1/user/bookmarks/novel.d.ts +44 -0
- package/dist/types/endpoints/v1/user/bookmarks/novel.d.ts.map +1 -0
- package/dist/types/endpoints/v1/user/bookmarks/novel.js +28 -0
- package/dist/types/endpoints/v1/user/bookmarks/novel.js.map +1 -0
- package/dist/types/endpoints/v1/user/detail.d.ts +44 -0
- package/dist/types/endpoints/v1/user/detail.d.ts.map +1 -0
- package/dist/types/endpoints/v1/user/detail.js +26 -0
- package/dist/types/endpoints/v1/user/detail.js.map +1 -0
- package/dist/types/endpoints/v2/illust/bookmark/add.d.ts +28 -0
- package/dist/types/endpoints/v2/illust/bookmark/add.d.ts.map +1 -0
- package/dist/types/endpoints/v2/illust/bookmark/add.js +3 -0
- package/dist/types/endpoints/v2/illust/bookmark/add.js.map +1 -0
- package/dist/types/endpoints/v2/illust/related.d.ts +41 -0
- package/dist/types/endpoints/v2/illust/related.d.ts.map +1 -0
- package/dist/types/endpoints/v2/illust/related.js +29 -0
- package/dist/types/endpoints/v2/illust/related.js.map +1 -0
- package/dist/types/endpoints/v2/novel/bookmark/add.d.ts +27 -0
- package/dist/types/endpoints/v2/novel/bookmark/add.d.ts.map +1 -0
- package/dist/types/endpoints/v2/novel/bookmark/add.js +3 -0
- package/dist/types/endpoints/v2/novel/bookmark/add.js.map +1 -0
- package/dist/types/endpoints/v2/novel/detail.d.ts +25 -0
- package/dist/types/endpoints/v2/novel/detail.d.ts.map +1 -0
- package/dist/types/endpoints/v2/novel/detail.js +20 -0
- package/dist/types/endpoints/v2/novel/detail.js.map +1 -0
- package/dist/types/endpoints/v2/novel/series.d.ts +49 -0
- package/dist/types/endpoints/v2/novel/series.d.ts.map +1 -0
- package/dist/types/endpoints/v2/novel/series.js +31 -0
- package/dist/types/endpoints/v2/novel/series.js.map +1 -0
- package/dist/types/endpoints/webview/v2/novel.d.ts +21 -0
- package/dist/types/endpoints/webview/v2/novel.d.ts.map +1 -0
- package/dist/types/endpoints/webview/v2/novel.js +18 -0
- package/dist/types/endpoints/webview/v2/novel.js.map +1 -0
- package/dist/types/error-response.d.ts +29 -0
- package/dist/types/error-response.d.ts.map +1 -0
- package/dist/types/error-response.js +3 -0
- package/dist/types/error-response.js.map +1 -0
- package/dist/types/pixiv-common.d.ts +96 -0
- package/dist/types/pixiv-common.d.ts.map +1 -0
- package/dist/types/pixiv-common.js +66 -0
- package/dist/types/pixiv-common.js.map +1 -0
- package/dist/types/pixiv-illust-series.d.ts +56 -0
- package/dist/types/pixiv-illust-series.d.ts.map +1 -0
- package/dist/types/pixiv-illust-series.js +26 -0
- package/dist/types/pixiv-illust-series.js.map +1 -0
- package/dist/types/pixiv-illust.d.ts +167 -0
- package/dist/types/pixiv-illust.d.ts.map +1 -0
- package/dist/types/pixiv-illust.js +53 -0
- package/dist/types/pixiv-illust.js.map +1 -0
- package/dist/types/pixiv-novel-series.d.ts +84 -0
- package/dist/types/pixiv-novel-series.d.ts.map +1 -0
- package/dist/types/pixiv-novel-series.js +43 -0
- package/dist/types/pixiv-novel-series.js.map +1 -0
- package/dist/types/pixiv-novel.d.ts +122 -0
- package/dist/types/pixiv-novel.d.ts.map +1 -0
- package/dist/types/pixiv-novel.js +42 -0
- package/dist/types/pixiv-novel.js.map +1 -0
- package/dist/types/pixiv-ugoira.d.ts +50 -0
- package/dist/types/pixiv-ugoira.d.ts.map +1 -0
- package/dist/types/pixiv-ugoira.js +34 -0
- package/dist/types/pixiv-ugoira.js.map +1 -0
- package/dist/types/pixiv-user.d.ts +184 -0
- package/dist/types/pixiv-user.d.ts.map +1 -0
- package/dist/types/pixiv-user.js +97 -0
- package/dist/types/pixiv-user.js.map +1 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +15 -0
- package/dist/utils.js.map +1 -0
- package/dist/utils.test.d.ts +2 -0
- package/dist/utils.test.d.ts.map +1 -0
- package/dist/utils.test.js +15 -0
- package/dist/utils.test.js.map +1 -0
- package/package.json +2 -2
package/dist/pixiv.js
ADDED
|
@@ -0,0 +1,759 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PixivHttpClient = void 0;
|
|
7
|
+
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
8
|
+
const qs_1 = __importDefault(require("qs"));
|
|
9
|
+
const options_1 = require("./options");
|
|
10
|
+
const saving_responses_1 = require("./saving-responses");
|
|
11
|
+
function headersToRecord(headers) {
|
|
12
|
+
const result = {};
|
|
13
|
+
for (const [key, value] of headers) {
|
|
14
|
+
result[key] = value;
|
|
15
|
+
}
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
class PixivHttpClient {
|
|
19
|
+
constructor(baseURL, headers) {
|
|
20
|
+
this.baseURL = baseURL;
|
|
21
|
+
this.defaultHeaders = headers;
|
|
22
|
+
}
|
|
23
|
+
async get(path, options = {}) {
|
|
24
|
+
let url = `${this.baseURL}${path}`;
|
|
25
|
+
if (options.params) {
|
|
26
|
+
const queryString = qs_1.default.stringify(options.params);
|
|
27
|
+
if (queryString)
|
|
28
|
+
url += `?${queryString}`;
|
|
29
|
+
}
|
|
30
|
+
const response = await fetch(url, {
|
|
31
|
+
headers: this.defaultHeaders,
|
|
32
|
+
});
|
|
33
|
+
const contentType = response.headers.get('content-type') ?? '';
|
|
34
|
+
const text = await response.text();
|
|
35
|
+
const data = (contentType.includes('application/json') ? JSON.parse(text) : text);
|
|
36
|
+
return {
|
|
37
|
+
data,
|
|
38
|
+
status: response.status,
|
|
39
|
+
headers: headersToRecord(response.headers),
|
|
40
|
+
requestHeaders: this.defaultHeaders,
|
|
41
|
+
requestBody: null,
|
|
42
|
+
responseUrl: response.url || undefined,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
async post(path, body, options = {}) {
|
|
46
|
+
const url = `${this.baseURL}${path}`;
|
|
47
|
+
const headers = { ...this.defaultHeaders, ...options.headers };
|
|
48
|
+
const response = await fetch(url, {
|
|
49
|
+
method: 'POST',
|
|
50
|
+
headers,
|
|
51
|
+
body,
|
|
52
|
+
});
|
|
53
|
+
const contentType = response.headers.get('content-type') ?? '';
|
|
54
|
+
const text = await response.text();
|
|
55
|
+
const data = (contentType.includes('application/json') ? JSON.parse(text) : text);
|
|
56
|
+
return {
|
|
57
|
+
data,
|
|
58
|
+
status: response.status,
|
|
59
|
+
headers: headersToRecord(response.headers),
|
|
60
|
+
requestHeaders: headers,
|
|
61
|
+
requestBody: body,
|
|
62
|
+
responseUrl: response.url || undefined,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.PixivHttpClient = PixivHttpClient;
|
|
67
|
+
/**
|
|
68
|
+
* pixiv API
|
|
69
|
+
*/
|
|
70
|
+
class Pixiv {
|
|
71
|
+
/**
|
|
72
|
+
* コンストラクタ。外部からインスタンス化できないので、of メソッドを使うこと。
|
|
73
|
+
*
|
|
74
|
+
* @param userId ユーザー ID
|
|
75
|
+
* @param accessToken アクセストークン
|
|
76
|
+
* @param refreshToken リフレッシュトークン
|
|
77
|
+
* @param pixivTsOptions Pixivts オプション
|
|
78
|
+
*/
|
|
79
|
+
constructor(userId, accessToken, refreshToken, responseDatabase) {
|
|
80
|
+
this.hosts = 'https://app-api.pixiv.net';
|
|
81
|
+
this.userId = userId;
|
|
82
|
+
this.accessToken = accessToken;
|
|
83
|
+
this.refreshToken = refreshToken;
|
|
84
|
+
this.responseDatabase = responseDatabase ?? null;
|
|
85
|
+
this.http = new PixivHttpClient(this.hosts, {
|
|
86
|
+
Host: 'app-api.pixiv.net',
|
|
87
|
+
'App-OS': 'ios',
|
|
88
|
+
'App-OS-Version': '14.6',
|
|
89
|
+
'User-Agent': 'PixivIOSApp/7.13.3 (iOS 14.6; iPhone13,2)',
|
|
90
|
+
'Accept-Language': 'ja',
|
|
91
|
+
Authorization: `Bearer ${this.accessToken}`,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* リフレッシュトークンからインスタンスを生成する。
|
|
96
|
+
*
|
|
97
|
+
* @param refreshToken リフレッシュトークン
|
|
98
|
+
* @returns Pixiv インスタンス
|
|
99
|
+
*/
|
|
100
|
+
static async of(refreshToken, pixivTsOptions) {
|
|
101
|
+
// @see https://github.com/upbit/pixivpy/blob/master/pixivpy3/api.py#L120
|
|
102
|
+
// UTCで YYYY-MM-DDTHH:mm:ss+00:00 の形式で現在時刻を取得
|
|
103
|
+
const localTime = new Date().toISOString().replace(/Z$/, '+00:00');
|
|
104
|
+
const headers = {
|
|
105
|
+
'x-client-time': localTime,
|
|
106
|
+
'x-client-hash': this.hash(localTime),
|
|
107
|
+
'app-os': 'ios',
|
|
108
|
+
'app-os-version': '16.4.1',
|
|
109
|
+
'user-agent': ' PixivIOSApp/7.16.9 (iOS 16.4.1; iPad13,4)',
|
|
110
|
+
header: 'application/x-www-form-urlencoded',
|
|
111
|
+
};
|
|
112
|
+
const authUrl = 'https://oauth.secure.pixiv.net/auth/token';
|
|
113
|
+
const data = qs_1.default.stringify({
|
|
114
|
+
client_id: this.clientId,
|
|
115
|
+
client_secret: this.clientSecret,
|
|
116
|
+
get_secure_url: 1,
|
|
117
|
+
grant_type: 'refresh_token',
|
|
118
|
+
refresh_token: refreshToken,
|
|
119
|
+
});
|
|
120
|
+
const response = await fetch(authUrl, {
|
|
121
|
+
method: 'POST',
|
|
122
|
+
headers: {
|
|
123
|
+
...headers,
|
|
124
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
125
|
+
},
|
|
126
|
+
body: data,
|
|
127
|
+
});
|
|
128
|
+
if (response.status !== 200) {
|
|
129
|
+
throw new Error('Failed to refresh token');
|
|
130
|
+
}
|
|
131
|
+
const responseData = (await response.json());
|
|
132
|
+
const options = {
|
|
133
|
+
userId: responseData.user.id,
|
|
134
|
+
accessToken: responseData.response.access_token,
|
|
135
|
+
refreshToken: responseData.response.refresh_token,
|
|
136
|
+
};
|
|
137
|
+
const responseDatabase = pixivTsOptions?.debugOptions?.outputResponse
|
|
138
|
+
?.enable
|
|
139
|
+
? new saving_responses_1.ResponseDatabase(pixivTsOptions.debugOptions.outputResponse.db)
|
|
140
|
+
: null;
|
|
141
|
+
if (responseDatabase) {
|
|
142
|
+
await responseDatabase.init();
|
|
143
|
+
await responseDatabase.migrate();
|
|
144
|
+
await responseDatabase.sync();
|
|
145
|
+
}
|
|
146
|
+
return new Pixiv(options.userId, options.accessToken, options.refreshToken, responseDatabase);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* 画像取得用の `Response` を返す。
|
|
150
|
+
*
|
|
151
|
+
* 戻り値はストリームそのものではなく `Response` オブジェクトであり、
|
|
152
|
+
* ストリームとして読み取る場合は `response.body` を参照する。
|
|
153
|
+
* 必要に応じて `arrayBuffer()` などの `Response` の API も利用できる。
|
|
154
|
+
*
|
|
155
|
+
* @param url 画像 URL
|
|
156
|
+
* @returns 画像取得結果の `Response`
|
|
157
|
+
*/
|
|
158
|
+
static async getImageStream(url) {
|
|
159
|
+
return fetch(url, {
|
|
160
|
+
headers: {
|
|
161
|
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36',
|
|
162
|
+
Referer: 'https://www.pixiv.net/',
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
// ---------- イラスト ---------- //
|
|
167
|
+
/**
|
|
168
|
+
* イラストの詳細情報を取得する。
|
|
169
|
+
*
|
|
170
|
+
* @param options オプション
|
|
171
|
+
* @returns レスポンス
|
|
172
|
+
*/
|
|
173
|
+
async illustDetail(options) {
|
|
174
|
+
const parameters = {
|
|
175
|
+
...this.convertCamelToSnake(options),
|
|
176
|
+
illust_id: options.illustId,
|
|
177
|
+
};
|
|
178
|
+
return this.request({
|
|
179
|
+
method: 'GET',
|
|
180
|
+
path: '/v1/illust/detail',
|
|
181
|
+
params: parameters,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* イラストの関連イラストを取得する。
|
|
186
|
+
*
|
|
187
|
+
* @param options オプション
|
|
188
|
+
* @returns レスポンス
|
|
189
|
+
*/
|
|
190
|
+
async illustRelated(options) {
|
|
191
|
+
this.checkRequiredOptions(options, ['illustId']);
|
|
192
|
+
const parameters = {
|
|
193
|
+
...this.convertCamelToSnake(options),
|
|
194
|
+
illust_id: options.illustId,
|
|
195
|
+
seed_illust_ids: options.seedIllustIds,
|
|
196
|
+
viewed: options.viewed,
|
|
197
|
+
offset: options.offset,
|
|
198
|
+
};
|
|
199
|
+
return this.request({
|
|
200
|
+
method: 'GET',
|
|
201
|
+
path: '/v2/illust/related',
|
|
202
|
+
params: parameters,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* イラストを検索する。
|
|
207
|
+
*
|
|
208
|
+
* @param options オプション
|
|
209
|
+
* @returns レスポンス
|
|
210
|
+
*/
|
|
211
|
+
async searchIllust(options) {
|
|
212
|
+
this.checkRequiredOptions(options, ['word']);
|
|
213
|
+
const parameters = {
|
|
214
|
+
...this.convertCamelToSnake(options),
|
|
215
|
+
word: options.word, // required
|
|
216
|
+
search_target: options.searchTarget ?? options_1.SearchTarget.PARTIAL_MATCH_FOR_TAGS,
|
|
217
|
+
sort: options.sort ?? options_1.SearchSort.DATE_DESC,
|
|
218
|
+
start_date: options.startDate,
|
|
219
|
+
end_date: options.endDate,
|
|
220
|
+
filter: options.filter ?? options_1.OSFilter.FOR_IOS,
|
|
221
|
+
offset: options.offset,
|
|
222
|
+
merge_plain_keyword_results: options.mergePlainKeywordResults ?? true,
|
|
223
|
+
include_translated_tag_results: options.includeTranslatedTagResults ?? true,
|
|
224
|
+
};
|
|
225
|
+
return this.request({
|
|
226
|
+
method: 'GET',
|
|
227
|
+
path: '/v1/search/illust',
|
|
228
|
+
params: parameters,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* イラストランキングを取得する。
|
|
233
|
+
*
|
|
234
|
+
* @param options オプション
|
|
235
|
+
* @returns レスポンス
|
|
236
|
+
*/
|
|
237
|
+
async illustRanking(options = {}) {
|
|
238
|
+
const parameters = {
|
|
239
|
+
...this.convertCamelToSnake(options),
|
|
240
|
+
mode: options.mode ?? options_1.RankingMode.DAY,
|
|
241
|
+
filter: options.filter ?? options_1.OSFilter.FOR_IOS,
|
|
242
|
+
date: options.date ?? undefined,
|
|
243
|
+
offset: options.offset ?? undefined,
|
|
244
|
+
};
|
|
245
|
+
return this.request({
|
|
246
|
+
method: 'GET',
|
|
247
|
+
path: '/v1/illust/ranking',
|
|
248
|
+
params: parameters,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* おすすめイラストを取得する。
|
|
253
|
+
*
|
|
254
|
+
* @param options オプション
|
|
255
|
+
* @returns レスポンス
|
|
256
|
+
*/
|
|
257
|
+
async illustRecommended(options = {}) {
|
|
258
|
+
const parameters = {
|
|
259
|
+
...this.convertCamelToSnake(options),
|
|
260
|
+
filter: options.filter ?? options_1.OSFilter.FOR_IOS,
|
|
261
|
+
include_ranking_illusts: options.includeRankingIllusts ?? true,
|
|
262
|
+
min_bookmark_id_for_recent_illust: options.minBookmarkIdForRecentIllust ?? undefined,
|
|
263
|
+
max_bookmark_id_for_recommend: options.maxBookmarkIdForRecommend ?? undefined,
|
|
264
|
+
offset: options.offset ?? undefined,
|
|
265
|
+
include_privacy_policy: options.includePrivacyPolicy ?? true,
|
|
266
|
+
};
|
|
267
|
+
return this.request({
|
|
268
|
+
method: 'GET',
|
|
269
|
+
path: '/v1/illust/recommended',
|
|
270
|
+
params: parameters,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* イラストシリーズの詳細情報を取得する。
|
|
275
|
+
*
|
|
276
|
+
* @param options オプション
|
|
277
|
+
* @returns レスポンス
|
|
278
|
+
*/
|
|
279
|
+
async illustSeries(options) {
|
|
280
|
+
this.checkRequiredOptions(options, ['illustSeriesId']);
|
|
281
|
+
const parameters = {
|
|
282
|
+
...this.convertCamelToSnake(options),
|
|
283
|
+
illust_series_id: options.illustSeriesId,
|
|
284
|
+
filter: options.filter ?? options_1.OSFilter.FOR_IOS,
|
|
285
|
+
// offset: options.offset,
|
|
286
|
+
};
|
|
287
|
+
return this.request({
|
|
288
|
+
method: 'GET',
|
|
289
|
+
path: '/v1/illust/series',
|
|
290
|
+
params: parameters,
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* イラストをブックマークする。
|
|
295
|
+
*
|
|
296
|
+
* @param options オプション
|
|
297
|
+
* @returns レスポンス
|
|
298
|
+
*/
|
|
299
|
+
async illustBookmarkAdd(options) {
|
|
300
|
+
this.checkRequiredOptions(options, ['illustId']);
|
|
301
|
+
const data = {
|
|
302
|
+
...this.convertCamelToSnake(options),
|
|
303
|
+
illust_id: options.illustId,
|
|
304
|
+
restrict: options.restrict ?? options_1.BookmarkRestrict.PUBLIC,
|
|
305
|
+
tags: options.tags ?? [],
|
|
306
|
+
};
|
|
307
|
+
return this.request({
|
|
308
|
+
method: 'POST',
|
|
309
|
+
path: '/v2/illust/bookmark/add',
|
|
310
|
+
data,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* イラストのブックマークを削除する。
|
|
315
|
+
*
|
|
316
|
+
* @param options オプション
|
|
317
|
+
* @returns レスポンス
|
|
318
|
+
*/
|
|
319
|
+
async illustBookmarkDelete(options) {
|
|
320
|
+
this.checkRequiredOptions(options, ['illustId']);
|
|
321
|
+
const data = {
|
|
322
|
+
...this.convertCamelToSnake(options),
|
|
323
|
+
illust_id: options.illustId,
|
|
324
|
+
};
|
|
325
|
+
return this.request({
|
|
326
|
+
method: 'POST',
|
|
327
|
+
path: '/v1/illust/bookmark/delete',
|
|
328
|
+
data,
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
// ---------- マンガ ---------- //
|
|
332
|
+
async mangaRecommended(options = {}) {
|
|
333
|
+
const parameters = {
|
|
334
|
+
...this.convertCamelToSnake(options),
|
|
335
|
+
filter: options.filter ?? options_1.OSFilter.FOR_IOS,
|
|
336
|
+
include_ranking_illusts: options.includeRankingIllusts ?? true,
|
|
337
|
+
max_bookmark_id: options.maxBookmarkId ?? undefined,
|
|
338
|
+
offset: options.offset ?? undefined,
|
|
339
|
+
include_privacy_policy: options.includePrivacyPolicy ?? true,
|
|
340
|
+
};
|
|
341
|
+
return this.request({
|
|
342
|
+
method: 'GET',
|
|
343
|
+
path: '/v1/manga/recommended',
|
|
344
|
+
params: parameters,
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
// ---------- うごイラ ---------- //
|
|
348
|
+
/**
|
|
349
|
+
* うごイラの詳細情報を取得する。
|
|
350
|
+
*
|
|
351
|
+
* @param options オプション
|
|
352
|
+
* @returns レスポンス
|
|
353
|
+
*/
|
|
354
|
+
async ugoiraMetadata(options) {
|
|
355
|
+
const parameters = {
|
|
356
|
+
...this.convertCamelToSnake(options),
|
|
357
|
+
illust_id: options.illustId,
|
|
358
|
+
};
|
|
359
|
+
return this.request({
|
|
360
|
+
method: 'GET',
|
|
361
|
+
path: '/v1/ugoira/metadata',
|
|
362
|
+
params: parameters,
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
// ---------- 小説 ---------- //
|
|
366
|
+
/**
|
|
367
|
+
* 小説の詳細情報を取得する。
|
|
368
|
+
*
|
|
369
|
+
* @param options オプション
|
|
370
|
+
* @returns レスポンス
|
|
371
|
+
*/
|
|
372
|
+
async novelDetail(options) {
|
|
373
|
+
this.checkRequiredOptions(options, ['novelId']);
|
|
374
|
+
const parameters = {
|
|
375
|
+
...this.convertCamelToSnake(options),
|
|
376
|
+
novel_id: options.novelId,
|
|
377
|
+
};
|
|
378
|
+
return this.request({
|
|
379
|
+
method: 'GET',
|
|
380
|
+
path: '/v2/novel/detail',
|
|
381
|
+
params: parameters,
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* 小説の本文を取得する。
|
|
386
|
+
*
|
|
387
|
+
* @param options オプション
|
|
388
|
+
* @returns レスポンス
|
|
389
|
+
*/
|
|
390
|
+
async novelText(options) {
|
|
391
|
+
this.checkRequiredOptions(options, ['id']);
|
|
392
|
+
const parameters = {
|
|
393
|
+
...this.convertCamelToSnake(options),
|
|
394
|
+
id: options.id,
|
|
395
|
+
};
|
|
396
|
+
return await this.request({
|
|
397
|
+
method: 'GET',
|
|
398
|
+
path: '/webview/v2/novel',
|
|
399
|
+
params: parameters,
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* 小説の関連小説を取得する。
|
|
404
|
+
*
|
|
405
|
+
* @param options オプション
|
|
406
|
+
* @returns レスポンス
|
|
407
|
+
*/
|
|
408
|
+
async novelRelated(options) {
|
|
409
|
+
this.checkRequiredOptions(options, ['novelId']);
|
|
410
|
+
const parameters = {
|
|
411
|
+
...this.convertCamelToSnake(options),
|
|
412
|
+
novel_id: options.novelId,
|
|
413
|
+
seed_novel_ids: options.seedNovelIds,
|
|
414
|
+
viewed: options.viewed,
|
|
415
|
+
};
|
|
416
|
+
return this.request({
|
|
417
|
+
method: 'GET',
|
|
418
|
+
path: '/v1/novel/related',
|
|
419
|
+
params: parameters,
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* 小説を検索する。
|
|
424
|
+
*
|
|
425
|
+
* @param options オプション
|
|
426
|
+
* @returns レスポンス
|
|
427
|
+
*/
|
|
428
|
+
async searchNovel(options) {
|
|
429
|
+
this.checkRequiredOptions(options, ['word']);
|
|
430
|
+
const parameters = {
|
|
431
|
+
...this.convertCamelToSnake(options),
|
|
432
|
+
word: options.word, // required
|
|
433
|
+
search_target: options.searchTarget ?? options_1.SearchTarget.PARTIAL_MATCH_FOR_TAGS,
|
|
434
|
+
sort: options.sort ?? options_1.SearchSort.DATE_DESC,
|
|
435
|
+
startDate: options.startDate,
|
|
436
|
+
endDate: options.endDate,
|
|
437
|
+
filter: options.filter ?? options_1.OSFilter.FOR_IOS,
|
|
438
|
+
offset: options.offset,
|
|
439
|
+
merge_plain_keyword_results: options.mergePlainKeywordResults ?? true,
|
|
440
|
+
include_translated_tag_results: options.includeTranslatedTagResults ?? true,
|
|
441
|
+
};
|
|
442
|
+
return this.request({
|
|
443
|
+
method: 'GET',
|
|
444
|
+
path: '/v1/search/novel',
|
|
445
|
+
params: parameters,
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* 小説ランキングを取得する。
|
|
450
|
+
*/
|
|
451
|
+
async novelRanking(options = {}) {
|
|
452
|
+
const parameters = {
|
|
453
|
+
...this.convertCamelToSnake(options),
|
|
454
|
+
mode: options.mode ?? options_1.RankingMode.DAY,
|
|
455
|
+
date: options.date ?? undefined,
|
|
456
|
+
offset: options.offset ?? undefined,
|
|
457
|
+
};
|
|
458
|
+
return this.request({
|
|
459
|
+
method: 'GET',
|
|
460
|
+
path: '/v1/novel/ranking',
|
|
461
|
+
params: parameters,
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* おすすめ小説を取得する。
|
|
466
|
+
*
|
|
467
|
+
* @param options オプション
|
|
468
|
+
* @returns レスポンス
|
|
469
|
+
*/
|
|
470
|
+
async novelRecommended(options = {}) {
|
|
471
|
+
const parameters = {
|
|
472
|
+
...this.convertCamelToSnake(options),
|
|
473
|
+
// filter: options.filter ?? 'for_ios',
|
|
474
|
+
include_ranking_novels: options.includeRankingNovels ?? true,
|
|
475
|
+
already_recommended: options.alreadyRecommended
|
|
476
|
+
? options.alreadyRecommended.join(',')
|
|
477
|
+
: undefined,
|
|
478
|
+
max_bookmark_id_for_recommend: options.maxBookmarkIdForRecommend ?? undefined,
|
|
479
|
+
offset: options.offset ?? undefined,
|
|
480
|
+
include_privacy_policy: options.includePrivacyPolicy ?? true,
|
|
481
|
+
};
|
|
482
|
+
return this.request({
|
|
483
|
+
method: 'GET',
|
|
484
|
+
path: '/v1/novel/recommended',
|
|
485
|
+
params: parameters,
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* 小説シリーズの詳細情報を取得する。
|
|
490
|
+
*
|
|
491
|
+
* @param options オプション
|
|
492
|
+
* @returns レスポンス
|
|
493
|
+
*/
|
|
494
|
+
async novelSeries(options) {
|
|
495
|
+
this.checkRequiredOptions(options, ['seriesId']);
|
|
496
|
+
const parameters = {
|
|
497
|
+
...this.convertCamelToSnake(options),
|
|
498
|
+
series_id: options.seriesId,
|
|
499
|
+
// filter: options.filter ?? 'for_ios',
|
|
500
|
+
last_order: options.lastOrder ?? undefined,
|
|
501
|
+
};
|
|
502
|
+
return this.request({
|
|
503
|
+
method: 'GET',
|
|
504
|
+
path: '/v2/novel/series',
|
|
505
|
+
params: parameters,
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* 小説をブックマークする。
|
|
510
|
+
*
|
|
511
|
+
* @param options オプション
|
|
512
|
+
* @returns レスポンス
|
|
513
|
+
*/
|
|
514
|
+
async novelBookmarkAdd(options) {
|
|
515
|
+
this.checkRequiredOptions(options, ['novelId']);
|
|
516
|
+
const data = {
|
|
517
|
+
...this.convertCamelToSnake(options),
|
|
518
|
+
novel_id: options.novelId,
|
|
519
|
+
restrict: options.restrict ?? options_1.BookmarkRestrict.PUBLIC,
|
|
520
|
+
tags: options.tags ?? [],
|
|
521
|
+
};
|
|
522
|
+
return this.request({
|
|
523
|
+
method: 'POST',
|
|
524
|
+
path: '/v2/novel/bookmark/add',
|
|
525
|
+
data,
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* 小説のブックマークを削除する。
|
|
530
|
+
*
|
|
531
|
+
* @param options オプション
|
|
532
|
+
* @returns レスポンス
|
|
533
|
+
*/
|
|
534
|
+
async novelBookmarkDelete(options) {
|
|
535
|
+
this.checkRequiredOptions(options, ['novelId']);
|
|
536
|
+
const data = {
|
|
537
|
+
...this.convertCamelToSnake(options),
|
|
538
|
+
novel_id: options.novelId,
|
|
539
|
+
};
|
|
540
|
+
return this.request({
|
|
541
|
+
method: 'POST',
|
|
542
|
+
path: '/v1/novel/bookmark/delete',
|
|
543
|
+
data,
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
// ---------- ユーザ ---------- //
|
|
547
|
+
/**
|
|
548
|
+
* ユーザの詳細情報を取得する。
|
|
549
|
+
*
|
|
550
|
+
* @param options オプション
|
|
551
|
+
* @returns レスポンス
|
|
552
|
+
*/
|
|
553
|
+
async userDetail(options) {
|
|
554
|
+
this.checkRequiredOptions(options, ['userId']);
|
|
555
|
+
const parameters = {
|
|
556
|
+
...this.convertCamelToSnake(options),
|
|
557
|
+
user_id: options.userId,
|
|
558
|
+
filter: options.filter ?? options_1.OSFilter.FOR_IOS,
|
|
559
|
+
};
|
|
560
|
+
return this.request({
|
|
561
|
+
method: 'GET',
|
|
562
|
+
path: '/v1/user/detail',
|
|
563
|
+
params: parameters,
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* ユーザのイラストブックマークを取得する。
|
|
568
|
+
*
|
|
569
|
+
* @param options オプション
|
|
570
|
+
* @returns レスポンス
|
|
571
|
+
*/
|
|
572
|
+
async userBookmarksIllust(options) {
|
|
573
|
+
this.checkRequiredOptions(options, ['userId']);
|
|
574
|
+
const parameters = {
|
|
575
|
+
...this.convertCamelToSnake(options),
|
|
576
|
+
user_id: options.userId,
|
|
577
|
+
restrict: options.restrict ?? options_1.BookmarkRestrict.PUBLIC,
|
|
578
|
+
filter: options.filter ?? options_1.OSFilter.FOR_IOS,
|
|
579
|
+
max_bookmark_id: options.maxBookmarkId ?? undefined,
|
|
580
|
+
tag: options.tag ?? undefined,
|
|
581
|
+
};
|
|
582
|
+
return this.request({
|
|
583
|
+
method: 'GET',
|
|
584
|
+
path: '/v1/user/bookmarks/illust',
|
|
585
|
+
params: parameters,
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* ユーザの小説ブックマークを取得する。
|
|
590
|
+
*
|
|
591
|
+
* @param options オプション
|
|
592
|
+
* @returns レスポンス
|
|
593
|
+
*/
|
|
594
|
+
async userBookmarksNovel(options) {
|
|
595
|
+
this.checkRequiredOptions(options, ['userId']);
|
|
596
|
+
const parameters = {
|
|
597
|
+
...this.convertCamelToSnake(options),
|
|
598
|
+
user_id: options.userId,
|
|
599
|
+
restrict: options.restrict ?? options_1.BookmarkRestrict.PUBLIC,
|
|
600
|
+
max_bookmark_id: options.maxBookmarkId ?? undefined,
|
|
601
|
+
tag: options.tag ?? undefined,
|
|
602
|
+
};
|
|
603
|
+
return this.request({
|
|
604
|
+
method: 'GET',
|
|
605
|
+
path: '/v1/user/bookmarks/novel',
|
|
606
|
+
params: parameters,
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
// ---------- その他 ---------- //
|
|
610
|
+
/**
|
|
611
|
+
* 接続を閉じる。
|
|
612
|
+
*/
|
|
613
|
+
async close() {
|
|
614
|
+
if (this.responseDatabase) {
|
|
615
|
+
await this.responseDatabase.close();
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
// ---------- ユーティリティ ---------- //
|
|
619
|
+
/**
|
|
620
|
+
* クエリストリングをパースする。
|
|
621
|
+
*
|
|
622
|
+
* @param url URL
|
|
623
|
+
* @returns パースしたクエリストリングオブジェクト
|
|
624
|
+
*/
|
|
625
|
+
static parseQueryString(url) {
|
|
626
|
+
let query = url;
|
|
627
|
+
if (url.includes('?')) {
|
|
628
|
+
query = url.split('?')[1];
|
|
629
|
+
}
|
|
630
|
+
return qs_1.default.parse(query);
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* レスポンスがエラーかどうかを判定する。
|
|
634
|
+
*
|
|
635
|
+
* @param response Axios レスポンス
|
|
636
|
+
* @returns エラーかどうか
|
|
637
|
+
*/
|
|
638
|
+
static isError(response) {
|
|
639
|
+
return (
|
|
640
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
641
|
+
response.error !== undefined &&
|
|
642
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
643
|
+
response.error.user_message !== undefined &&
|
|
644
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
645
|
+
response.error.message !== undefined &&
|
|
646
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
647
|
+
response.error.reason !== undefined);
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* MD5ハッシュを生成する。
|
|
651
|
+
*
|
|
652
|
+
* @param str 文字列
|
|
653
|
+
* @returns ハッシュ
|
|
654
|
+
*/
|
|
655
|
+
static hash(string) {
|
|
656
|
+
const hash = node_crypto_1.default.createHash('md5');
|
|
657
|
+
return hash.update(string + this.hashSecret).digest('hex');
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* リクエストを送信する。
|
|
661
|
+
*
|
|
662
|
+
* ジェネリクスの順番は、T: リクエスト、U: レスポンス。
|
|
663
|
+
*
|
|
664
|
+
* @param options オプション
|
|
665
|
+
* @returns レスポンス
|
|
666
|
+
*/
|
|
667
|
+
async request(options) {
|
|
668
|
+
if (options.method === 'GET') {
|
|
669
|
+
return await this.saveResponse(options, await this.http.get(options.path, {
|
|
670
|
+
params: options.params,
|
|
671
|
+
}));
|
|
672
|
+
}
|
|
673
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
674
|
+
if (options.method === 'POST') {
|
|
675
|
+
return await this.saveResponse(options, await this.http.post(options.path, qs_1.default.stringify(options.data), {
|
|
676
|
+
headers: {
|
|
677
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
678
|
+
},
|
|
679
|
+
}));
|
|
680
|
+
}
|
|
681
|
+
throw new Error('Invalid method');
|
|
682
|
+
}
|
|
683
|
+
async saveResponse(request, response) {
|
|
684
|
+
if (this.responseDatabase === null) {
|
|
685
|
+
return response;
|
|
686
|
+
}
|
|
687
|
+
const method = request.method;
|
|
688
|
+
const path = request.path;
|
|
689
|
+
const rawUrl = [
|
|
690
|
+
this.hosts,
|
|
691
|
+
path,
|
|
692
|
+
method === 'GET'
|
|
693
|
+
? qs_1.default.stringify(request.params, { addQueryPrefix: true })
|
|
694
|
+
: '',
|
|
695
|
+
].join('');
|
|
696
|
+
const url = response.responseUrl ?? rawUrl;
|
|
697
|
+
const responseType = this.isJSON(response.data) ? 'JSON' : 'TEXT';
|
|
698
|
+
const responseBody = responseType === 'JSON'
|
|
699
|
+
? JSON.stringify(response.data)
|
|
700
|
+
: response.data;
|
|
701
|
+
await this.responseDatabase.addResponse({
|
|
702
|
+
method,
|
|
703
|
+
endpoint: path,
|
|
704
|
+
url,
|
|
705
|
+
requestHeaders: JSON.stringify(response.requestHeaders),
|
|
706
|
+
requestBody: response.requestBody,
|
|
707
|
+
responseType,
|
|
708
|
+
statusCode: response.status,
|
|
709
|
+
responseHeaders: JSON.stringify(response.headers),
|
|
710
|
+
responseBody,
|
|
711
|
+
});
|
|
712
|
+
return response;
|
|
713
|
+
}
|
|
714
|
+
isJSON(value) {
|
|
715
|
+
if (typeof value === 'object') {
|
|
716
|
+
return true;
|
|
717
|
+
}
|
|
718
|
+
try {
|
|
719
|
+
JSON.parse(value);
|
|
720
|
+
return true;
|
|
721
|
+
}
|
|
722
|
+
catch {
|
|
723
|
+
return false;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* 必須のオプションが含まれているかどうかをチェックする。
|
|
728
|
+
*
|
|
729
|
+
* @param options オプション
|
|
730
|
+
* @param required 必須のオプションキー
|
|
731
|
+
* @throws 必須のオプションが含まれていない場合
|
|
732
|
+
*/
|
|
733
|
+
checkRequiredOptions(options, required) {
|
|
734
|
+
for (const key of required) {
|
|
735
|
+
if (options[key] === undefined) {
|
|
736
|
+
throw new Error(`Missing required option: ${key}`);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* キャメルケースのオブジェクトキーをスネークケースなオブジェクトキーに変換する。
|
|
742
|
+
*
|
|
743
|
+
* @param object オブジェクト
|
|
744
|
+
* @returns 変換後のオブジェクト
|
|
745
|
+
*/
|
|
746
|
+
convertCamelToSnake(object) {
|
|
747
|
+
const result = {};
|
|
748
|
+
for (const key of Object.keys(object)) {
|
|
749
|
+
const snakeKey = key.replaceAll(/([A-Z])/g, (m) => `_${m[0].toLowerCase()}`);
|
|
750
|
+
result[snakeKey] = object[key];
|
|
751
|
+
}
|
|
752
|
+
return result;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
Pixiv.clientId = 'MOBrBDS8blbauoSck0ZfDbtuzpyT';
|
|
756
|
+
Pixiv.clientSecret = 'lsACyCD94FhDUtGTXi3QzcFE2uU1hqtDaKeqrdwj';
|
|
757
|
+
Pixiv.hashSecret = '28c1fdd170a5204386cb1313c7077b34f83e4aaf4aa829ce78c231e05b0bae2c';
|
|
758
|
+
exports.default = Pixiv;
|
|
759
|
+
//# sourceMappingURL=pixiv.js.map
|