1 | import { Readable } from "node:stream";
|
2 | import HTTPClient from "./http-axios.js";
|
3 | import * as Types from "./types.js";
|
4 | import { AxiosRequestConfig, AxiosResponse } from "axios";
|
5 | import { createMultipartFormData, ensureJSON, toArray } from "./utils.js";
|
6 | import {
|
7 | DATA_API_PREFIX,
|
8 | MESSAGING_API_PREFIX,
|
9 | OAUTH_BASE_PREFIX,
|
10 | OAUTH_BASE_PREFIX_V2_1,
|
11 | } from "./endpoints.js";
|
12 |
|
13 | type ChatType = "group" | "room";
|
14 | type RequestOption = {
|
15 | retryKey: string;
|
16 | };
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | export default class Client {
|
22 | public config: Types.ClientConfig;
|
23 | private http: HTTPClient;
|
24 |
|
25 | private requestOption: Partial<RequestOption> = {};
|
26 |
|
27 | constructor(config: Types.ClientConfig) {
|
28 | if (!config.channelAccessToken) {
|
29 | throw new Error("no channel access token");
|
30 | }
|
31 |
|
32 | this.config = config;
|
33 | this.http = new HTTPClient({
|
34 | defaultHeaders: {
|
35 | Authorization: "Bearer " + this.config.channelAccessToken,
|
36 | },
|
37 | responseParser: this.parseHTTPResponse.bind(this),
|
38 | ...config.httpConfig,
|
39 | });
|
40 | }
|
41 |
|
42 | public setRequestOptionOnce(option: Partial<RequestOption>) {
|
43 | this.requestOption = option;
|
44 | }
|
45 |
|
46 | private generateRequestConfig(): Partial<AxiosRequestConfig> {
|
47 | const config: Partial<AxiosRequestConfig> = { headers: {} };
|
48 | if (this.requestOption.retryKey) {
|
49 | config.headers["X-Line-Retry-Key"] = this.requestOption.retryKey;
|
50 | }
|
51 |
|
52 |
|
53 | this.requestOption = {};
|
54 | return config;
|
55 | }
|
56 |
|
57 | private parseHTTPResponse(response: AxiosResponse) {
|
58 | const { LINE_REQUEST_ID_HTTP_HEADER_NAME } = Types;
|
59 | let resBody = {
|
60 | ...response.data,
|
61 | };
|
62 | if (response.headers[LINE_REQUEST_ID_HTTP_HEADER_NAME]) {
|
63 | resBody[LINE_REQUEST_ID_HTTP_HEADER_NAME] =
|
64 | response.headers[LINE_REQUEST_ID_HTTP_HEADER_NAME];
|
65 | }
|
66 | return resBody;
|
67 | }
|
68 |
|
69 | public pushMessage(
|
70 | to: string,
|
71 | messages: Types.Message | Types.Message[],
|
72 | notificationDisabled: boolean = false,
|
73 | customAggregationUnits?: string[],
|
74 | ): Promise<Types.MessageAPIResponseBase> {
|
75 | return this.http.post(
|
76 | `${MESSAGING_API_PREFIX}/message/push`,
|
77 | {
|
78 | messages: toArray(messages),
|
79 | to,
|
80 | notificationDisabled,
|
81 | customAggregationUnits,
|
82 | },
|
83 | this.generateRequestConfig(),
|
84 | );
|
85 | }
|
86 |
|
87 | public replyMessage(
|
88 | replyToken: string,
|
89 | messages: Types.Message | Types.Message[],
|
90 | notificationDisabled: boolean = false,
|
91 | ): Promise<Types.MessageAPIResponseBase> {
|
92 | return this.http.post(`${MESSAGING_API_PREFIX}/message/reply`, {
|
93 | messages: toArray(messages),
|
94 | replyToken,
|
95 | notificationDisabled,
|
96 | });
|
97 | }
|
98 |
|
99 | public async multicast(
|
100 | to: string[],
|
101 | messages: Types.Message | Types.Message[],
|
102 | notificationDisabled: boolean = false,
|
103 | customAggregationUnits?: string[],
|
104 | ): Promise<Types.MessageAPIResponseBase> {
|
105 | return this.http.post(
|
106 | `${MESSAGING_API_PREFIX}/message/multicast`,
|
107 | {
|
108 | messages: toArray(messages),
|
109 | to,
|
110 | notificationDisabled,
|
111 | customAggregationUnits,
|
112 | },
|
113 | this.generateRequestConfig(),
|
114 | );
|
115 | }
|
116 |
|
117 | public async narrowcast(
|
118 | messages: Types.Message | Types.Message[],
|
119 | recipient?: Types.ReceieptObject,
|
120 | filter?: { demographic: Types.DemographicFilterObject },
|
121 | limit?: { max?: number; upToRemainingQuota?: boolean },
|
122 | notificationDisabled?: boolean,
|
123 | ): Promise<Types.MessageAPIResponseBase> {
|
124 | return this.http.post(
|
125 | `${MESSAGING_API_PREFIX}/message/narrowcast`,
|
126 | {
|
127 | messages: toArray(messages),
|
128 | recipient,
|
129 | filter,
|
130 | limit,
|
131 | notificationDisabled,
|
132 | },
|
133 | this.generateRequestConfig(),
|
134 | );
|
135 | }
|
136 |
|
137 | public async broadcast(
|
138 | messages: Types.Message | Types.Message[],
|
139 | notificationDisabled: boolean = false,
|
140 | ): Promise<Types.MessageAPIResponseBase> {
|
141 | return this.http.post(
|
142 | `${MESSAGING_API_PREFIX}/message/broadcast`,
|
143 | {
|
144 | messages: toArray(messages),
|
145 | notificationDisabled,
|
146 | },
|
147 | this.generateRequestConfig(),
|
148 | );
|
149 | }
|
150 |
|
151 | public validatePushMessageObjects(
|
152 | messages: Types.Message | Types.Message[],
|
153 | ): Promise<Types.MessageAPIResponseBase> {
|
154 | return this.http.post(
|
155 | `${MESSAGING_API_PREFIX}/message/validate/push`,
|
156 | {
|
157 | messages: toArray(messages),
|
158 | },
|
159 | this.generateRequestConfig(),
|
160 | );
|
161 | }
|
162 |
|
163 | public validateReplyMessageObjects(
|
164 | messages: Types.Message | Types.Message[],
|
165 | ): Promise<Types.MessageAPIResponseBase> {
|
166 | return this.http.post(`${MESSAGING_API_PREFIX}/message/validate/reply`, {
|
167 | messages: toArray(messages),
|
168 | });
|
169 | }
|
170 |
|
171 | public async validateMulticastMessageObjects(
|
172 | messages: Types.Message | Types.Message[],
|
173 | ): Promise<Types.MessageAPIResponseBase> {
|
174 | return this.http.post(
|
175 | `${MESSAGING_API_PREFIX}/message/validate/multicast`,
|
176 | {
|
177 | messages: toArray(messages),
|
178 | },
|
179 | this.generateRequestConfig(),
|
180 | );
|
181 | }
|
182 |
|
183 | public async validateNarrowcastMessageObjects(
|
184 | messages: Types.Message | Types.Message[],
|
185 | ): Promise<Types.MessageAPIResponseBase> {
|
186 | return this.http.post(
|
187 | `${MESSAGING_API_PREFIX}/message/validate/narrowcast`,
|
188 | {
|
189 | messages: toArray(messages),
|
190 | },
|
191 | this.generateRequestConfig(),
|
192 | );
|
193 | }
|
194 |
|
195 | public async validateBroadcastMessageObjects(
|
196 | messages: Types.Message | Types.Message[],
|
197 | ): Promise<Types.MessageAPIResponseBase> {
|
198 | return this.http.post(
|
199 | `${MESSAGING_API_PREFIX}/message/validate/broadcast`,
|
200 | {
|
201 | messages: toArray(messages),
|
202 | },
|
203 | this.generateRequestConfig(),
|
204 | );
|
205 | }
|
206 |
|
207 | public validateCustomAggregationUnits(units: string[]): {
|
208 | messages: string[];
|
209 | valid: boolean;
|
210 | } {
|
211 | const messages: string[] = [];
|
212 | if (units.length > 1) {
|
213 | messages.push("customAggregationUnits can only contain one unit");
|
214 | }
|
215 | units.forEach((unit, index) => {
|
216 | if (unit.length > 30) {
|
217 | messages.push(
|
218 | `customAggregationUnits[${index}] must be less than or equal to 30 characters`,
|
219 | );
|
220 | }
|
221 | if (!/^[a-zA-Z0-9_]+$/.test(unit)) {
|
222 | messages.push(
|
223 | `customAggregationUnits[${index}] must be alphanumeric characters or underscores`,
|
224 | );
|
225 | }
|
226 | });
|
227 |
|
228 | return {
|
229 | messages,
|
230 | valid: messages.length === 0,
|
231 | };
|
232 | }
|
233 |
|
234 | public async getProfile(userId: string): Promise<Types.Profile> {
|
235 | const profile = await this.http.get<Types.Profile>(
|
236 | `${MESSAGING_API_PREFIX}/profile/${userId}`,
|
237 | );
|
238 | return ensureJSON(profile);
|
239 | }
|
240 |
|
241 | private async getChatMemberProfile(
|
242 | chatType: ChatType,
|
243 | chatId: string,
|
244 | userId: string,
|
245 | ): Promise<Types.Profile> {
|
246 | const profile = await this.http.get<Types.Profile>(
|
247 | `${MESSAGING_API_PREFIX}/${chatType}/${chatId}/member/${userId}`,
|
248 | );
|
249 | return ensureJSON(profile);
|
250 | }
|
251 |
|
252 | public async getGroupMemberProfile(
|
253 | groupId: string,
|
254 | userId: string,
|
255 | ): Promise<Types.Profile> {
|
256 | return this.getChatMemberProfile("group", groupId, userId);
|
257 | }
|
258 |
|
259 | public async getRoomMemberProfile(
|
260 | roomId: string,
|
261 | userId: string,
|
262 | ): Promise<Types.Profile> {
|
263 | return this.getChatMemberProfile("room", roomId, userId);
|
264 | }
|
265 |
|
266 | private async getChatMemberIds(
|
267 | chatType: ChatType,
|
268 | chatId: string,
|
269 | ): Promise<string[]> {
|
270 | let memberIds: string[] = [];
|
271 |
|
272 | let start: string;
|
273 | do {
|
274 | const res = await this.http.get<{ memberIds: string[]; next?: string }>(
|
275 | `${MESSAGING_API_PREFIX}/${chatType}/${chatId}/members/ids`,
|
276 | start ? { start } : null,
|
277 | );
|
278 | ensureJSON(res);
|
279 | memberIds = memberIds.concat(res.memberIds);
|
280 | start = res.next;
|
281 | } while (start);
|
282 |
|
283 | return memberIds;
|
284 | }
|
285 |
|
286 | public async getGroupMemberIds(groupId: string): Promise<string[]> {
|
287 | return this.getChatMemberIds("group", groupId);
|
288 | }
|
289 |
|
290 | public async getRoomMemberIds(roomId: string): Promise<string[]> {
|
291 | return this.getChatMemberIds("room", roomId);
|
292 | }
|
293 |
|
294 | public async getBotFollowersIds(): Promise<string[]> {
|
295 | let userIds: string[] = [];
|
296 |
|
297 | let start: string;
|
298 | do {
|
299 | const res = await this.http.get<{ userIds: string[]; next?: string }>(
|
300 | `${MESSAGING_API_PREFIX}/followers/ids`,
|
301 | start ? { start, limit: 1000 } : { limit: 1000 },
|
302 | );
|
303 | ensureJSON(res);
|
304 | userIds = userIds.concat(res.userIds);
|
305 | start = res.next;
|
306 | } while (start);
|
307 |
|
308 | return userIds;
|
309 | }
|
310 |
|
311 | public async getGroupMembersCount(
|
312 | groupId: string,
|
313 | ): Promise<Types.MembersCountResponse> {
|
314 | const groupMemberCount = await this.http.get<Types.MembersCountResponse>(
|
315 | `${MESSAGING_API_PREFIX}/group/${groupId}/members/count`,
|
316 | );
|
317 | return ensureJSON(groupMemberCount);
|
318 | }
|
319 |
|
320 | public async getRoomMembersCount(
|
321 | roomId: string,
|
322 | ): Promise<Types.MembersCountResponse> {
|
323 | const roomMemberCount = await this.http.get<Types.MembersCountResponse>(
|
324 | `${MESSAGING_API_PREFIX}/room/${roomId}/members/count`,
|
325 | );
|
326 | return ensureJSON(roomMemberCount);
|
327 | }
|
328 |
|
329 | public async getGroupSummary(
|
330 | groupId: string,
|
331 | ): Promise<Types.GroupSummaryResponse> {
|
332 | const groupSummary = await this.http.get<Types.GroupSummaryResponse>(
|
333 | `${MESSAGING_API_PREFIX}/group/${groupId}/summary`,
|
334 | );
|
335 | return ensureJSON(groupSummary);
|
336 | }
|
337 |
|
338 | public async getMessageContent(messageId: string): Promise<Readable> {
|
339 | return this.http.getStream(
|
340 | `${DATA_API_PREFIX}/message/${messageId}/content`,
|
341 | );
|
342 | }
|
343 |
|
344 | private leaveChat(chatType: ChatType, chatId: string): Promise<any> {
|
345 | return this.http.post(
|
346 | `${MESSAGING_API_PREFIX}/${chatType}/${chatId}/leave`,
|
347 | );
|
348 | }
|
349 |
|
350 | public async leaveGroup(groupId: string): Promise<any> {
|
351 | return this.leaveChat("group", groupId);
|
352 | }
|
353 |
|
354 | public async leaveRoom(roomId: string): Promise<any> {
|
355 | return this.leaveChat("room", roomId);
|
356 | }
|
357 |
|
358 | public async getRichMenu(
|
359 | richMenuId: string,
|
360 | ): Promise<Types.RichMenuResponse> {
|
361 | const res = await this.http.get<Types.RichMenuResponse>(
|
362 | `${MESSAGING_API_PREFIX}/richmenu/${richMenuId}`,
|
363 | );
|
364 | return ensureJSON(res);
|
365 | }
|
366 |
|
367 | public async createRichMenu(richMenu: Types.RichMenu): Promise<string> {
|
368 | const res = await this.http.post<any>(
|
369 | `${MESSAGING_API_PREFIX}/richmenu`,
|
370 | richMenu,
|
371 | );
|
372 | return ensureJSON(res).richMenuId;
|
373 | }
|
374 |
|
375 | public async deleteRichMenu(richMenuId: string): Promise<any> {
|
376 | return this.http.delete(`${MESSAGING_API_PREFIX}/richmenu/${richMenuId}`);
|
377 | }
|
378 |
|
379 | public async getRichMenuAliasList(): Promise<Types.GetRichMenuAliasListResponse> {
|
380 | const res = await this.http.get<Types.GetRichMenuAliasListResponse>(
|
381 | `${MESSAGING_API_PREFIX}/richmenu/alias/list`,
|
382 | );
|
383 | return ensureJSON(res);
|
384 | }
|
385 |
|
386 | public async getRichMenuAlias(
|
387 | richMenuAliasId: string,
|
388 | ): Promise<Types.GetRichMenuAliasResponse> {
|
389 | const res = await this.http.get<Types.GetRichMenuAliasResponse>(
|
390 | `${MESSAGING_API_PREFIX}/richmenu/alias/${richMenuAliasId}`,
|
391 | );
|
392 | return ensureJSON(res);
|
393 | }
|
394 |
|
395 | public async createRichMenuAlias(
|
396 | richMenuId: string,
|
397 | richMenuAliasId: string,
|
398 | ): Promise<{}> {
|
399 | const res = await this.http.post<{}>(
|
400 | `${MESSAGING_API_PREFIX}/richmenu/alias`,
|
401 | {
|
402 | richMenuId,
|
403 | richMenuAliasId,
|
404 | },
|
405 | );
|
406 | return ensureJSON(res);
|
407 | }
|
408 |
|
409 | public async deleteRichMenuAlias(richMenuAliasId: string): Promise<{}> {
|
410 | const res = this.http.delete<{}>(
|
411 | `${MESSAGING_API_PREFIX}/richmenu/alias/${richMenuAliasId}`,
|
412 | );
|
413 | return ensureJSON(res);
|
414 | }
|
415 |
|
416 | public async updateRichMenuAlias(
|
417 | richMenuAliasId: string,
|
418 | richMenuId: string,
|
419 | ): Promise<{}> {
|
420 | const res = await this.http.post<{}>(
|
421 | `${MESSAGING_API_PREFIX}/richmenu/alias/${richMenuAliasId}`,
|
422 | {
|
423 | richMenuId,
|
424 | },
|
425 | );
|
426 | return ensureJSON(res);
|
427 | }
|
428 |
|
429 | public async getRichMenuIdOfUser(userId: string): Promise<string> {
|
430 | const res = await this.http.get<any>(
|
431 | `${MESSAGING_API_PREFIX}/user/${userId}/richmenu`,
|
432 | );
|
433 | return ensureJSON(res).richMenuId;
|
434 | }
|
435 |
|
436 | public async linkRichMenuToUser(
|
437 | userId: string,
|
438 | richMenuId: string,
|
439 | ): Promise<any> {
|
440 | return this.http.post(
|
441 | `${MESSAGING_API_PREFIX}/user/${userId}/richmenu/${richMenuId}`,
|
442 | );
|
443 | }
|
444 |
|
445 | public async unlinkRichMenuFromUser(userId: string): Promise<any> {
|
446 | return this.http.delete(`${MESSAGING_API_PREFIX}/user/${userId}/richmenu`);
|
447 | }
|
448 |
|
449 | public async linkRichMenuToMultipleUsers(
|
450 | richMenuId: string,
|
451 | userIds: string[],
|
452 | ): Promise<any> {
|
453 | return this.http.post(`${MESSAGING_API_PREFIX}/richmenu/bulk/link`, {
|
454 | richMenuId,
|
455 | userIds,
|
456 | });
|
457 | }
|
458 |
|
459 | public async unlinkRichMenusFromMultipleUsers(
|
460 | userIds: string[],
|
461 | ): Promise<any> {
|
462 | return this.http.post(`${MESSAGING_API_PREFIX}/richmenu/bulk/unlink`, {
|
463 | userIds,
|
464 | });
|
465 | }
|
466 |
|
467 | public async getRichMenuImage(richMenuId: string): Promise<Readable> {
|
468 | return this.http.getStream(
|
469 | `${DATA_API_PREFIX}/richmenu/${richMenuId}/content`,
|
470 | );
|
471 | }
|
472 |
|
473 | public async setRichMenuImage(
|
474 | richMenuId: string,
|
475 | data: Buffer | Readable,
|
476 | contentType?: string,
|
477 | ): Promise<any> {
|
478 | return this.http.postBinary(
|
479 | `${DATA_API_PREFIX}/richmenu/${richMenuId}/content`,
|
480 | data,
|
481 | contentType,
|
482 | );
|
483 | }
|
484 |
|
485 | public async getRichMenuList(): Promise<Array<Types.RichMenuResponse>> {
|
486 | const res = await this.http.get<any>(
|
487 | `${MESSAGING_API_PREFIX}/richmenu/list`,
|
488 | );
|
489 | return ensureJSON(res).richmenus;
|
490 | }
|
491 |
|
492 | public async setDefaultRichMenu(richMenuId: string): Promise<{}> {
|
493 | return this.http.post(
|
494 | `${MESSAGING_API_PREFIX}/user/all/richmenu/${richMenuId}`,
|
495 | );
|
496 | }
|
497 |
|
498 | public async getDefaultRichMenuId(): Promise<string> {
|
499 | const res = await this.http.get<any>(
|
500 | `${MESSAGING_API_PREFIX}/user/all/richmenu`,
|
501 | );
|
502 | return ensureJSON(res).richMenuId;
|
503 | }
|
504 |
|
505 | public async deleteDefaultRichMenu(): Promise<{}> {
|
506 | return this.http.delete(`${MESSAGING_API_PREFIX}/user/all/richmenu`);
|
507 | }
|
508 |
|
509 | public async getLinkToken(userId: string): Promise<string> {
|
510 | const res = await this.http.post<any>(
|
511 | `${MESSAGING_API_PREFIX}/user/${userId}/linkToken`,
|
512 | );
|
513 | return ensureJSON(res).linkToken;
|
514 | }
|
515 |
|
516 | public async getNumberOfSentReplyMessages(
|
517 | date: string,
|
518 | ): Promise<Types.NumberOfMessagesSentResponse> {
|
519 | const res = await this.http.get<Types.NumberOfMessagesSentResponse>(
|
520 | `${MESSAGING_API_PREFIX}/message/delivery/reply?date=${date}`,
|
521 | );
|
522 | return ensureJSON(res);
|
523 | }
|
524 |
|
525 | public async getNumberOfSentPushMessages(
|
526 | date: string,
|
527 | ): Promise<Types.NumberOfMessagesSentResponse> {
|
528 | const res = await this.http.get<Types.NumberOfMessagesSentResponse>(
|
529 | `${MESSAGING_API_PREFIX}/message/delivery/push?date=${date}`,
|
530 | );
|
531 | return ensureJSON(res);
|
532 | }
|
533 |
|
534 | public async getNumberOfSentMulticastMessages(
|
535 | date: string,
|
536 | ): Promise<Types.NumberOfMessagesSentResponse> {
|
537 | const res = await this.http.get<Types.NumberOfMessagesSentResponse>(
|
538 | `${MESSAGING_API_PREFIX}/message/delivery/multicast?date=${date}`,
|
539 | );
|
540 | return ensureJSON(res);
|
541 | }
|
542 |
|
543 | public async getNarrowcastProgress(
|
544 | requestId: string,
|
545 | ): Promise<Types.NarrowcastProgressResponse> {
|
546 | const res = await this.http.get<Types.NarrowcastProgressResponse>(
|
547 | `${MESSAGING_API_PREFIX}/message/progress/narrowcast?requestId=${requestId}`,
|
548 | );
|
549 | return ensureJSON(res);
|
550 | }
|
551 |
|
552 | public async getTargetLimitForAdditionalMessages(): Promise<Types.TargetLimitForAdditionalMessages> {
|
553 | const res = await this.http.get<Types.TargetLimitForAdditionalMessages>(
|
554 | `${MESSAGING_API_PREFIX}/message/quota`,
|
555 | );
|
556 | return ensureJSON(res);
|
557 | }
|
558 |
|
559 | public async getNumberOfMessagesSentThisMonth(): Promise<Types.NumberOfMessagesSentThisMonth> {
|
560 | const res = await this.http.get<Types.NumberOfMessagesSentThisMonth>(
|
561 | `${MESSAGING_API_PREFIX}/message/quota/consumption`,
|
562 | );
|
563 | return ensureJSON(res);
|
564 | }
|
565 |
|
566 | public async getNumberOfSentBroadcastMessages(
|
567 | date: string,
|
568 | ): Promise<Types.NumberOfMessagesSentResponse> {
|
569 | const res = await this.http.get<Types.NumberOfMessagesSentResponse>(
|
570 | `${MESSAGING_API_PREFIX}/message/delivery/broadcast?date=${date}`,
|
571 | );
|
572 | return ensureJSON(res);
|
573 | }
|
574 |
|
575 | public async getNumberOfMessageDeliveries(
|
576 | date: string,
|
577 | ): Promise<Types.NumberOfMessageDeliveriesResponse> {
|
578 | const res = await this.http.get<Types.NumberOfMessageDeliveriesResponse>(
|
579 | `${MESSAGING_API_PREFIX}/insight/message/delivery?date=${date}`,
|
580 | );
|
581 | return ensureJSON(res);
|
582 | }
|
583 |
|
584 | public async getNumberOfFollowers(
|
585 | date: string,
|
586 | ): Promise<Types.NumberOfFollowersResponse> {
|
587 | const res = await this.http.get<Types.NumberOfFollowersResponse>(
|
588 | `${MESSAGING_API_PREFIX}/insight/followers?date=${date}`,
|
589 | );
|
590 | return ensureJSON(res);
|
591 | }
|
592 |
|
593 | public async getFriendDemographics(): Promise<Types.FriendDemographics> {
|
594 | const res = await this.http.get<Types.FriendDemographics>(
|
595 | `${MESSAGING_API_PREFIX}/insight/demographic`,
|
596 | );
|
597 | return ensureJSON(res);
|
598 | }
|
599 |
|
600 | public async getUserInteractionStatistics(
|
601 | requestId: string,
|
602 | ): Promise<Types.UserInteractionStatistics> {
|
603 | const res = await this.http.get<Types.UserInteractionStatistics>(
|
604 | `${MESSAGING_API_PREFIX}/insight/message/event?requestId=${requestId}`,
|
605 | );
|
606 | return ensureJSON(res);
|
607 | }
|
608 |
|
609 | public async getStatisticsPerUnit(
|
610 | customAggregationUnit: string,
|
611 | from: string,
|
612 | to: string,
|
613 | ): Promise<Types.StatisticsPerUnit> {
|
614 | const res = await this.http.get<Types.StatisticsPerUnit>(
|
615 | `${MESSAGING_API_PREFIX}/insight/message/event/aggregation?customAggregationUnit=${customAggregationUnit}&from=${from}&to=${to}`,
|
616 | );
|
617 | return ensureJSON(res);
|
618 | }
|
619 |
|
620 | public async createUploadAudienceGroup(uploadAudienceGroup: {
|
621 | description: string;
|
622 | isIfaAudience?: boolean;
|
623 | audiences?: { id: string }[];
|
624 | uploadDescription?: string;
|
625 | }) {
|
626 | const res = await this.http.post<{
|
627 | audienceGroupId: number;
|
628 | type: string;
|
629 | description: string;
|
630 | created: number;
|
631 | }>(`${MESSAGING_API_PREFIX}/audienceGroup/upload`, {
|
632 | ...uploadAudienceGroup,
|
633 | });
|
634 | return ensureJSON(res);
|
635 | }
|
636 |
|
637 | public async createUploadAudienceGroupByFile(uploadAudienceGroup: {
|
638 | description: string;
|
639 | isIfaAudience?: boolean;
|
640 | uploadDescription?: string;
|
641 | file: Buffer | Readable;
|
642 | }) {
|
643 | const file = await this.http.toBuffer(uploadAudienceGroup.file);
|
644 | const body = createMultipartFormData({ ...uploadAudienceGroup, file });
|
645 | const res = await this.http.postFormMultipart<{
|
646 | audienceGroupId: number;
|
647 | type: "UPLOAD";
|
648 | description: string;
|
649 | created: number;
|
650 | }>(`${DATA_API_PREFIX}/audienceGroup/upload/byFile`, body);
|
651 | return ensureJSON(res);
|
652 | }
|
653 |
|
654 | public async updateUploadAudienceGroup(
|
655 | uploadAudienceGroup: {
|
656 | audienceGroupId: number;
|
657 | description?: string;
|
658 | uploadDescription?: string;
|
659 | audiences: { id: string }[];
|
660 | },
|
661 |
|
662 | httpConfig?: Partial<AxiosRequestConfig>,
|
663 | ) {
|
664 | const res = await this.http.put<{}>(
|
665 | `${MESSAGING_API_PREFIX}/audienceGroup/upload`,
|
666 | {
|
667 | ...uploadAudienceGroup,
|
668 | },
|
669 | httpConfig,
|
670 | );
|
671 | return ensureJSON(res);
|
672 | }
|
673 |
|
674 | public async updateUploadAudienceGroupByFile(
|
675 | uploadAudienceGroup: {
|
676 | audienceGroupId: number;
|
677 | uploadDescription?: string;
|
678 | file: Buffer | Readable;
|
679 | },
|
680 |
|
681 | httpConfig?: Partial<AxiosRequestConfig>,
|
682 | ) {
|
683 | const file = await this.http.toBuffer(uploadAudienceGroup.file);
|
684 | const body = createMultipartFormData({ ...uploadAudienceGroup, file });
|
685 |
|
686 | const res = await this.http.putFormMultipart<{}>(
|
687 | `${DATA_API_PREFIX}/audienceGroup/upload/byFile`,
|
688 | body,
|
689 | httpConfig,
|
690 | );
|
691 | return ensureJSON(res);
|
692 | }
|
693 |
|
694 | public async createClickAudienceGroup(clickAudienceGroup: {
|
695 | description: string;
|
696 | requestId: string;
|
697 | clickUrl?: string;
|
698 | }) {
|
699 | const res = await this.http.post<
|
700 | {
|
701 | audienceGroupId: number;
|
702 | type: string;
|
703 | created: number;
|
704 | } & typeof clickAudienceGroup
|
705 | >(`${MESSAGING_API_PREFIX}/audienceGroup/click`, {
|
706 | ...clickAudienceGroup,
|
707 | });
|
708 | return ensureJSON(res);
|
709 | }
|
710 |
|
711 | public async createImpAudienceGroup(impAudienceGroup: {
|
712 | requestId: string;
|
713 | description: string;
|
714 | }) {
|
715 | const res = await this.http.post<
|
716 | {
|
717 | audienceGroupId: number;
|
718 | type: string;
|
719 | created: number;
|
720 | } & typeof impAudienceGroup
|
721 | >(`${MESSAGING_API_PREFIX}/audienceGroup/imp`, {
|
722 | ...impAudienceGroup,
|
723 | });
|
724 | return ensureJSON(res);
|
725 | }
|
726 |
|
727 | public async setDescriptionAudienceGroup(
|
728 | description: string,
|
729 | audienceGroupId: string,
|
730 | ) {
|
731 | const res = await this.http.put<{}>(
|
732 | `${MESSAGING_API_PREFIX}/audienceGroup/${audienceGroupId}/updateDescription`,
|
733 | {
|
734 | description,
|
735 | },
|
736 | );
|
737 | return ensureJSON(res);
|
738 | }
|
739 |
|
740 | public async deleteAudienceGroup(audienceGroupId: string) {
|
741 | const res = await this.http.delete<{}>(
|
742 | `${MESSAGING_API_PREFIX}/audienceGroup/${audienceGroupId}`,
|
743 | );
|
744 | return ensureJSON(res);
|
745 | }
|
746 |
|
747 | public async getAudienceGroup(audienceGroupId: string) {
|
748 | const res = await this.http.get<Types.AudienceGroup>(
|
749 | `${MESSAGING_API_PREFIX}/audienceGroup/${audienceGroupId}`,
|
750 | );
|
751 | return ensureJSON(res);
|
752 | }
|
753 |
|
754 | public async getAudienceGroups(
|
755 | page: number,
|
756 | description?: string,
|
757 | status?: Types.AudienceGroupStatus,
|
758 | size?: number,
|
759 | createRoute?: Types.AudienceGroupCreateRoute,
|
760 | includesExternalPublicGroups?: boolean,
|
761 | ) {
|
762 | const res = await this.http.get<{
|
763 | audienceGroups: Types.AudienceGroups;
|
764 | hasNextPage: boolean;
|
765 | totalCount: number;
|
766 | readWriteAudienceGroupTotalCount: number;
|
767 | page: number;
|
768 | size: number;
|
769 | }>(`${MESSAGING_API_PREFIX}/audienceGroup/list`, {
|
770 | page,
|
771 | description,
|
772 | status,
|
773 | size,
|
774 | createRoute,
|
775 | includesExternalPublicGroups,
|
776 | });
|
777 | return ensureJSON(res);
|
778 | }
|
779 |
|
780 | public async getAudienceGroupAuthorityLevel() {
|
781 | const res = await this.http.get<{
|
782 | authorityLevel: Types.AudienceGroupAuthorityLevel;
|
783 | }>(`${MESSAGING_API_PREFIX}/audienceGroup/authorityLevel`);
|
784 | return ensureJSON(res);
|
785 | }
|
786 |
|
787 | public async changeAudienceGroupAuthorityLevel(
|
788 | authorityLevel: Types.AudienceGroupAuthorityLevel,
|
789 | ) {
|
790 | const res = await this.http.put<{}>(
|
791 | `${MESSAGING_API_PREFIX}/audienceGroup/authorityLevel`,
|
792 | { authorityLevel },
|
793 | );
|
794 | return ensureJSON(res);
|
795 | }
|
796 |
|
797 | public async getBotInfo(): Promise<Types.BotInfoResponse> {
|
798 | const res = await this.http.get<Types.BotInfoResponse>(
|
799 | `${MESSAGING_API_PREFIX}/info`,
|
800 | );
|
801 | return ensureJSON(res);
|
802 | }
|
803 |
|
804 | public async setWebhookEndpointUrl(endpoint: string) {
|
805 | return this.http.put<{}>(
|
806 | `${MESSAGING_API_PREFIX}/channel/webhook/endpoint`,
|
807 | { endpoint },
|
808 | );
|
809 | }
|
810 |
|
811 | public async getWebhookEndpointInfo() {
|
812 | const res = await this.http.get<Types.WebhookEndpointInfoResponse>(
|
813 | `${MESSAGING_API_PREFIX}/channel/webhook/endpoint`,
|
814 | );
|
815 | return ensureJSON(res);
|
816 | }
|
817 |
|
818 | public async testWebhookEndpoint(endpoint?: string) {
|
819 | const res = await this.http.post<Types.TestWebhookEndpointResponse>(
|
820 | `${MESSAGING_API_PREFIX}/channel/webhook/test`,
|
821 | { endpoint },
|
822 | );
|
823 | return ensureJSON(res);
|
824 | }
|
825 |
|
826 | public async validateRichMenu(richMenu: Types.RichMenu): Promise<{}> {
|
827 | return await this.http.post<{}>(
|
828 | `${MESSAGING_API_PREFIX}/richmenu/validate`,
|
829 | richMenu,
|
830 | );
|
831 | }
|
832 | }
|
833 |
|
834 | export class OAuth {
|
835 | private http: HTTPClient;
|
836 |
|
837 | constructor() {
|
838 | this.http = new HTTPClient();
|
839 | }
|
840 |
|
841 | public issueAccessToken(
|
842 | client_id: string,
|
843 | client_secret: string,
|
844 | ): Promise<Types.ChannelAccessToken> {
|
845 | return this.http.postForm(`${OAUTH_BASE_PREFIX}/accessToken`, {
|
846 | grant_type: "client_credentials",
|
847 | client_id,
|
848 | client_secret,
|
849 | });
|
850 | }
|
851 |
|
852 | public revokeAccessToken(access_token: string): Promise<{}> {
|
853 | return this.http.postForm(`${OAUTH_BASE_PREFIX}/revoke`, { access_token });
|
854 | }
|
855 |
|
856 | public verifyAccessToken(
|
857 | access_token: string,
|
858 | ): Promise<Types.VerifyAccessToken> {
|
859 | return this.http.get(`${OAUTH_BASE_PREFIX_V2_1}/verify`, { access_token });
|
860 | }
|
861 |
|
862 | public verifyIdToken(
|
863 | id_token: string,
|
864 | client_id: string,
|
865 | nonce?: string,
|
866 | user_id?: string,
|
867 | ): Promise<Types.VerifyIDToken> {
|
868 | const body: { [key: string]: string } = {
|
869 | id_token,
|
870 | client_id,
|
871 | };
|
872 |
|
873 | if (nonce) {
|
874 | body.nonce = nonce;
|
875 | }
|
876 |
|
877 | if (user_id) {
|
878 | body.user_id = user_id;
|
879 | }
|
880 | return this.http.postForm(`${OAUTH_BASE_PREFIX_V2_1}/verify`, body);
|
881 | }
|
882 |
|
883 | public issueChannelAccessTokenV2_1(
|
884 | client_assertion: string,
|
885 | ): Promise<Types.ChannelAccessToken> {
|
886 | return this.http.postForm(`${OAUTH_BASE_PREFIX_V2_1}/token`, {
|
887 | grant_type: "client_credentials",
|
888 | client_assertion_type:
|
889 | "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
|
890 | client_assertion,
|
891 | });
|
892 | }
|
893 |
|
894 | public getChannelAccessTokenKeyIdsV2_1(
|
895 | client_assertion: string,
|
896 | ): Promise<{ key_ids: string[] }> {
|
897 | return this.http.get(`${OAUTH_BASE_PREFIX_V2_1}/tokens/kid`, {
|
898 | client_assertion_type:
|
899 | "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
|
900 | client_assertion,
|
901 | });
|
902 | }
|
903 |
|
904 | public revokeChannelAccessTokenV2_1(
|
905 | client_id: string,
|
906 | client_secret: string,
|
907 | access_token: string,
|
908 | ): Promise<{}> {
|
909 | return this.http.postForm(`${OAUTH_BASE_PREFIX_V2_1}/revoke`, {
|
910 | client_id,
|
911 | client_secret,
|
912 | access_token,
|
913 | });
|
914 | }
|
915 | }
|