This commit is contained in:
2022-07-18 02:50:52 +00:00
parent befd344ab0
commit 06181b34d6
8569 changed files with 818704 additions and 352705 deletions
+168 -17
View File
@@ -2,8 +2,7 @@ import { Readable } from "stream";
import HTTPClient from "./http";
import * as Types from "./types";
import { AxiosResponse, AxiosRequestConfig } from "axios";
import { ensureJSON, toArray } from "./utils";
import { createMultipartFormData, ensureJSON, toArray } from "./utils";
type ChatType = "group" | "room";
type RequestOption = {
@@ -13,6 +12,7 @@ import {
MESSAGING_API_PREFIX,
DATA_API_PREFIX,
OAUTH_BASE_PREFIX,
OAUTH_BASE_PREFIX_V2_1,
} from "./endpoints";
export default class Client {
@@ -110,8 +110,8 @@ export default class Client {
messages: Types.Message | Types.Message[],
recipient?: Types.ReceieptObject,
filter?: { demographic: Types.DemographicFilterObject },
limit?: { max: number },
notificationDisabled: boolean = false,
limit?: { max?: number; upToRemainingQuota?: boolean },
notificationDisabled?: boolean,
): Promise<Types.MessageAPIResponseBase> {
return this.http.post(
`${MESSAGING_API_PREFIX}/message/narrowcast`,
@@ -200,6 +200,23 @@ export default class Client {
return this.getChatMemberIds("room", roomId);
}
public async getBotFollowersIds(): Promise<string[]> {
let userIds: string[] = [];
let start: string;
do {
const res = await this.http.get<{ userIds: string[]; next?: string }>(
`${MESSAGING_API_PREFIX}/followers/ids`,
start ? { start, limit: 1000 } : { limit: 1000 },
);
ensureJSON(res);
userIds = userIds.concat(res.userIds);
start = res.next;
} while (start);
return userIds;
}
public async getGroupMembersCount(
groupId: string,
): Promise<Types.MembersCountResponse> {
@@ -268,6 +285,56 @@ export default class Client {
return this.http.delete(`${MESSAGING_API_PREFIX}/richmenu/${richMenuId}`);
}
public async getRichMenuAliasList(): Promise<Types.GetRichMenuAliasListResponse> {
const res = await this.http.get<Types.GetRichMenuAliasListResponse>(
`${MESSAGING_API_PREFIX}/richmenu/alias/list`,
);
return ensureJSON(res);
}
public async getRichMenuAlias(
richMenuAliasId: string,
): Promise<Types.GetRichMenuAliasResponse> {
const res = await this.http.get<Types.GetRichMenuAliasResponse>(
`${MESSAGING_API_PREFIX}/richmenu/alias/${richMenuAliasId}`,
);
return ensureJSON(res);
}
public async createRichMenuAlias(
richMenuId: string,
richMenuAliasId: string,
): Promise<{}> {
const res = await this.http.post<{}>(
`${MESSAGING_API_PREFIX}/richmenu/alias`,
{
richMenuId,
richMenuAliasId,
},
);
return ensureJSON(res);
}
public async deleteRichMenuAlias(richMenuAliasId: string): Promise<{}> {
const res = this.http.delete<{}>(
`${MESSAGING_API_PREFIX}/richmenu/alias/${richMenuAliasId}`,
);
return ensureJSON(res);
}
public async updateRichMenuAlias(
richMenuAliasId: string,
richMenuId: string,
): Promise<{}> {
const res = await this.http.post<{}>(
`${MESSAGING_API_PREFIX}/richmenu/alias/${richMenuAliasId}`,
{
richMenuId,
},
);
return ensureJSON(res);
}
public async getRichMenuIdOfUser(userId: string): Promise<string> {
const res = await this.http.get<any>(
`${MESSAGING_API_PREFIX}/user/${userId}/richmenu`,
@@ -391,18 +458,14 @@ export default class Client {
return ensureJSON(res);
}
public async getTargetLimitForAdditionalMessages(): Promise<
Types.TargetLimitForAdditionalMessages
> {
public async getTargetLimitForAdditionalMessages(): Promise<Types.TargetLimitForAdditionalMessages> {
const res = await this.http.get<Types.TargetLimitForAdditionalMessages>(
`${MESSAGING_API_PREFIX}/message/quota`,
);
return ensureJSON(res);
}
public async getNumberOfMessagesSentThisMonth(): Promise<
Types.NumberOfMessagesSentThisMonth
> {
public async getNumberOfMessagesSentThisMonth(): Promise<Types.NumberOfMessagesSentThisMonth> {
const res = await this.http.get<Types.NumberOfMessagesSentThisMonth>(
`${MESSAGING_API_PREFIX}/message/quota/consumption`,
);
@@ -454,8 +517,8 @@ export default class Client {
public async createUploadAudienceGroup(uploadAudienceGroup: {
description: string;
isIfaAudience: boolean;
audiences: { id: string }[];
isIfaAudience?: boolean;
audiences?: { id: string }[];
uploadDescription?: string;
}) {
const res = await this.http.post<{
@@ -469,6 +532,25 @@ export default class Client {
return ensureJSON(res);
}
public async createUploadAudienceGroupByFile(uploadAudienceGroup: {
description: string;
isIfaAudience?: boolean;
uploadDescription?: string;
file: Buffer | Readable;
}) {
const file = await this.http.toBuffer(uploadAudienceGroup.file);
const body = createMultipartFormData({ ...uploadAudienceGroup, file });
const res = await this.http.post<{
audienceGroupId: number;
type: "UPLOAD";
description: string;
created: number;
}>(`${DATA_API_PREFIX}/audienceGroup/upload/byFile`, body, {
headers: body.getHeaders(),
});
return ensureJSON(res);
}
public async updateUploadAudienceGroup(
uploadAudienceGroup: {
audienceGroupId: number;
@@ -489,6 +571,26 @@ export default class Client {
return ensureJSON(res);
}
public async updateUploadAudienceGroupByFile(
uploadAudienceGroup: {
audienceGroupId: number;
uploadDescription?: string;
file: Buffer | Readable;
},
// for set request timeout
httpConfig?: Partial<AxiosRequestConfig>,
) {
const file = await this.http.toBuffer(uploadAudienceGroup.file);
const body = createMultipartFormData({ ...uploadAudienceGroup, file });
const res = await this.http.put<{}>(
`${DATA_API_PREFIX}/audienceGroup/upload/byFile`,
body,
{ headers: body.getHeaders(), ...httpConfig },
);
return ensureJSON(res);
}
public async createClickAudienceGroup(clickAudienceGroup: {
description: string;
requestId: string;
@@ -591,6 +693,35 @@ export default class Client {
);
return ensureJSON(res);
}
public async getBotInfo(): Promise<Types.BotInfoResponse> {
const res = await this.http.get<Types.BotInfoResponse>(
`${MESSAGING_API_PREFIX}/info`,
);
return ensureJSON(res);
}
public async setWebhookEndpointUrl(endpoint: string) {
return this.http.put<{}>(
`${MESSAGING_API_PREFIX}/channel/webhook/endpoint`,
{ endpoint },
);
}
public async getWebhookEndpointInfo() {
const res = await this.http.get<Types.WebhookEndpointInfoResponse>(
`${MESSAGING_API_PREFIX}/channel/webhook/endpoint`,
);
return ensureJSON(res);
}
public async testWebhookEndpoint(endpoint?: string) {
const res = await this.http.post<Types.TestWebhookEndpointResponse>(
`${MESSAGING_API_PREFIX}/channel/webhook/test`,
{ endpoint },
);
return ensureJSON(res);
}
}
export class OAuth {
@@ -615,10 +746,30 @@ export class OAuth {
return this.http.postForm(`${OAUTH_BASE_PREFIX}/revoke`, { access_token });
}
public verifyAccessToken(
access_token: string,
): Promise<Types.VerifyAccessToken> {
return this.http.get(`${OAUTH_BASE_PREFIX_V2_1}/verify`, { access_token });
}
public verifyIdToken(
id_token: string,
client_id: string,
nonce?: string,
user_id?: string,
): Promise<Types.VerifyIDToken> {
return this.http.postForm(`${OAUTH_BASE_PREFIX}/verify`, {
id_token,
client_id,
nonce,
user_id,
});
}
public issueChannelAccessTokenV2_1(
client_assertion: string,
): Promise<Types.ChannelAccessToken> {
return this.http.postForm(`${OAUTH_BASE_PREFIX}/v2.1/token`, {
return this.http.postForm(`${OAUTH_BASE_PREFIX_V2_1}/token`, {
grant_type: "client_credentials",
client_assertion_type:
"urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
@@ -626,10 +777,10 @@ export class OAuth {
});
}
public getIssuedChannelAccessTokenV2_1(
public getChannelAccessTokenKeyIdsV2_1(
client_assertion: string,
): Promise<{ access_tokens: string[] }> {
return this.http.get(`${OAUTH_BASE_PREFIX}/v2.1/tokens`, {
): Promise<{ key_ids: string[] }> {
return this.http.get(`${OAUTH_BASE_PREFIX_V2_1}/tokens/kid`, {
client_assertion_type:
"urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
client_assertion,
@@ -641,7 +792,7 @@ export class OAuth {
client_secret: string,
access_token: string,
): Promise<{}> {
return this.http.postForm(`${OAUTH_BASE_PREFIX}/v2.1/revoke`, {
return this.http.postForm(`${OAUTH_BASE_PREFIX_V2_1}/revoke`, {
client_id,
client_secret,
access_token,
+1
View File
@@ -1,3 +1,4 @@
export const MESSAGING_API_PREFIX = `https://api.line.me/v2/bot`;
export const DATA_API_PREFIX = `https://api-data.line.me/v2/bot`;
export const OAUTH_BASE_PREFIX = `https://api.line.me/v2/oauth`;
export const OAUTH_BASE_PREFIX_V2_1 = `https://api.line.me/oauth2/v2.1`;
+21 -19
View File
@@ -96,33 +96,35 @@ export default class HTTPClient {
return res.data;
}
public async toBuffer(data: Buffer | Readable) {
if (Buffer.isBuffer(data)) {
return data;
} else if (data instanceof Readable) {
return await new Promise<Buffer>((resolve, reject) => {
const buffers: Buffer[] = [];
let size = 0;
data.on("data", (chunk: Buffer) => {
buffers.push(chunk);
size += chunk.length;
});
data.on("end", () => resolve(Buffer.concat(buffers, size)));
data.on("error", reject);
});
} else {
throw new Error("invalid data type for binary data");
}
}
public async postBinary<T>(
url: string,
data: Buffer | Readable,
contentType?: string,
): Promise<T> {
const buffer = await (async (): Promise<Buffer> => {
if (Buffer.isBuffer(data)) {
return data;
} else if (data instanceof Readable) {
return new Promise<Buffer>((resolve, reject) => {
const buffers: Buffer[] = [];
let size = 0;
data.on("data", (chunk: Buffer) => {
buffers.push(chunk);
size += chunk.length;
});
data.on("end", () => resolve(Buffer.concat(buffers, size)));
data.on("error", reject);
});
} else {
throw new Error("invalid data type for postBinary");
}
})();
const buffer = await this.toBuffer(data);
const res = await this.instance.post(url, buffer, {
headers: {
"Content-Type": contentType || fileType(buffer).mime,
"Content-Type": contentType || (await fileType.fromBuffer(buffer)).mime,
"Content-Length": buffer.length,
},
});
+451 -54
View File
@@ -46,6 +46,7 @@ export type WebhookRequestBody = {
*/
export type WebhookEvent =
| MessageEvent
| UnsendEvent
| FollowEvent
| UnfollowEvent
| JoinEvent
@@ -53,6 +54,7 @@ export type WebhookEvent =
| MemberJoinEvent
| MemberLeaveEvent
| PostbackEvent
| VideoPlayCompleteEvent
| BeaconEvent
| AccountLinkEvent
| DeviceLinkEvent
@@ -123,6 +125,19 @@ export type MessageEvent = {
message: EventMessage;
} & ReplyableEvent;
/**
* Event object for when the user unsends a message in a [group](https://developers.line.biz/en/docs/messaging-api/group-chats/#group)
* or [room](https://developers.line.biz/en/docs/messaging-api/group-chats/#room).
* [Unsend event](https://developers.line.biz/en/reference/messaging-api/#unsend-event)
*/
export type UnsendEvent = {
type: "unsend";
/**
* The message ID of the unsent message
*/
unsend: { messageId: string };
} & EventBase;
/**
* Event object for when your account is added as a friend (or unblocked).
*/
@@ -185,6 +200,18 @@ export type PostbackEvent = {
postback: Postback;
} & ReplyableEvent;
/**
* Event for when a user finishes viewing a video at least once with the specified trackingId sent by the LINE Official Account.
*/
export type VideoPlayCompleteEvent = {
type: "videoPlayComplete";
/**
* ID used to identify a video. Returns the same value as the trackingId assigned to the [video message](https://developers.line.biz/en/reference/messaging-api/#video-message).
* String
*/
videoPlayComplete: { trackingId: string };
} & ReplyableEvent;
/**
* Event object for when a user enters or leaves the range of a
* [LINE Beacon](https://developers.line.biz/en/docs/messaging-api/using-beacons/).
@@ -359,6 +386,28 @@ export type TextEventMessage = {
productId: string;
emojiId: string;
}[];
/**
* Object containing the contents of the mentioned user.
*/
mention?: {
/**
* Mentioned user information.
* Max: 20 mentions
*/
mentionees: {
/**
* Index position of the user mention for a character in `text`,
* with the first character being at position 0.
*/
index: number;
/**
* The length of the text of the mentioned user. For a mention `@example`,
* 8 is the length.
*/
length: number;
userId: string;
}[];
};
} & EventMessageBase;
export type ContentProvider<WithPreview extends boolean = true> =
@@ -394,6 +443,28 @@ export type ContentProvider<WithPreview extends boolean = true> =
export type ImageEventMessage = {
type: "image";
contentProvider: ContentProvider;
/**
* Object containing the number of images sent simultaneously.
*/
imageSet?: {
/**
* Image set ID. Only included when multiple images are sent simultaneously.
*/
id: string;
/**
* An index starting from 1, indicating the image number in a set of images sent simultaneously.
* Only included when multiple images are sent simultaneously.
* However, it won't be included if the sender is using LINE 11.15 or earlier for Android.
*/
index: number;
/**
* The total number of images sent simultaneously.
* If two images are sent simultaneously, the number is 2.
* Only included when multiple images are sent simultaneously.
* However, it won't be included if the sender is using LINE 11.15 or earlier for Android.
*/
total: number;
};
} & EventMessageBase;
/**
@@ -452,33 +523,55 @@ export type StickerEventMessage = {
| "ANIMATION_SOUND"
| "POPUP"
| "POPUP_SOUND"
| "NAME_TEXT";
| "CUSTOM"
| "MESSAGE";
keywords: string[];
/**
* Any text entered by the user. This property is only included for message stickers.
* Max character limit: 100
*/
text?: string;
} & EventMessageBase;
export type Postback = {
data: string;
params?: DateTimePostback | RichMenuSwitchPostback;
};
/**
* Object with the date and time selected by a user through a
* [datetime picker action](https://developers.line.biz/en/reference/messaging-api/#datetime-picker-action).
* Only returned for postback actions via a
* [datetime picker action](https://developers.line.biz/en/reference/messaging-api/#datetime-picker-action).
* The `full-date`, `time-hour`, and `time-minute` formats follow the
* [RFC3339 protocol](https://www.ietf.org/rfc/rfc3339.txt).
*/
type DateTimePostback = {
/**
* Object with the date and time selected by a user through a
* [datetime picker action](https://developers.line.biz/en/reference/messaging-api/#datetime-picker-action).
* Only returned for postback actions via a
* [datetime picker action](https://developers.line.biz/en/reference/messaging-api/#datetime-picker-action).
* The `full-date`, `time-hour`, and `time-minute` formats follow the
* [RFC3339 protocol](https://www.ietf.org/rfc/rfc3339.txt).
* Date selected by user. Only included in the `date` mode.
*/
params?: {
/**
* Date selected by user. Only included in the `date` mode.
*/
date?: string;
/**
* Time selected by the user. Only included in the `time` mode.
*/
time?: string;
/**
* Date and time selected by the user. Only included in the `datetime` mode.
*/
datetime?: string;
};
date?: string;
/**
* Time selected by the user. Only included in the `time` mode.
*/
time?: string;
/**
* Date and time selected by the user. Only included in the `datetime` mode.
*/
datetime?: string;
};
/**
* Object with rich menu alias ID selected by user via rich menu switch action.
* https://developers.line.biz/en/reference/messaging-api/#postback-params-object-for-richmenu-switch-action
*/
type RichMenuSwitchPostback = {
newRichMenuAliasId: string;
status:
| "SUCCESS"
| "RICHMENU_ALIAS_ID_NOTFOUND"
| "RICHMENU_NOTFOUND"
| "FAILED";
};
/**
@@ -526,13 +619,25 @@ export type TextMessage = MessageCommon & {
/**
* Message text. You can include the following emoji:
*
* - LINE emojis. Use a $ character as a placeholder and specify the product ID and emoji ID of the LINE emoji you want to use in the emojis property.
* - Unicode emoji
* - LINE original emoji
* - (Deprecated) LINE original unicode emojis
* ([Unicode codepoint table for LINE original emoji](https://developers.line.biz/media/messaging-api/emoji-list.pdf))
*
* Max: 2000 characters
* Max: 5000 characters
*/
text: string;
/**
* One or more LINE emoji.
*
* Max: 20 LINE emoji
*/
emojis?: {
index: number;
productId: string;
emojiId: string;
}[];
};
/**
@@ -541,7 +646,7 @@ export type TextMessage = MessageCommon & {
export type ImageMessage = MessageCommon & {
type: "image";
/**
* Image URL (Max: 1000 characters)
* Image URL (Max: 2000 characters)
*
* - **HTTPS**
* - JPEG
@@ -550,7 +655,7 @@ export type ImageMessage = MessageCommon & {
*/
originalContentUrl: string;
/**
* Preview image URL (Max: 1000 characters)
* Preview image URL (Max: 2000 characters)
*
* - **HTTPS**
* - JPEG
@@ -566,7 +671,7 @@ export type ImageMessage = MessageCommon & {
export type VideoMessage = MessageCommon & {
type: "video";
/**
* URL of video file (Max: 1000 characters)
* URL of video file (Max: 2000 characters)
*
* - **HTTPS**
* - mp4
@@ -577,7 +682,7 @@ export type VideoMessage = MessageCommon & {
*/
originalContentUrl: string;
/**
* URL of preview image (Max: 1000 characters)
* URL of preview image (Max: 2000 characters)
*
* - **HTTPS**
* - JPEG
@@ -593,7 +698,7 @@ export type VideoMessage = MessageCommon & {
export type AudioMessage = MessageCommon & {
type: "audio";
/**
* URL of audio file (Max: 1000 characters)
* URL of audio file (Max: 2000 characters)
*
* - **HTTPS**
* - m4a
@@ -651,7 +756,7 @@ export type ImageMapMessage = MessageCommon & {
type: "imagemap";
/**
* [Base URL](https://developers.line.biz/en/reference/messaging-api/#base-url) of image
* (Max: 1000 characters, **HTTPS**)
* (Max: 2000 characters, **HTTPS**)
*/
baseUrl: string;
/**
@@ -664,7 +769,7 @@ export type ImageMapMessage = MessageCommon & {
*/
video?: {
/**
* URL of video file (Max: 1000 characters)
* URL of video file (Max: 2000 characters)
*
* - **HTTPS**
* - mp4
@@ -675,7 +780,7 @@ export type ImageMapMessage = MessageCommon & {
*/
originalContentUrl: string;
/**
* URL of preview image (Max: 1000 characters)
* URL of preview image (Max: 2000 characters)
*
* - **HTTPS**
* - JPEG
@@ -826,7 +931,7 @@ export type FlexBubble = {
*/
direction?: "ltr" | "rtl";
header?: FlexBox;
hero?: FlexBox | FlexImage;
hero?: FlexBox | FlexImage | FlexVideo;
body?: FlexBox;
footer?: FlexBox;
styles?: FlexBubbleStyle;
@@ -861,7 +966,7 @@ export type FlexBlockStyle = {
export type FlexCarousel = {
type: "carousel";
/**
* (Max: 10 bubbles)
* (Max: 12 bubbles)
*/
contents: FlexBubble[];
};
@@ -873,6 +978,7 @@ export type FlexCarousel = {
* - [Box](https://developers.line.biz/en/reference/messaging-api/#box)
* - [Button](https://developers.line.biz/en/reference/messaging-api/#button)
* - [Image](https://developers.line.biz/en/reference/messaging-api/#f-image)
* - [Video](https://developers.line.biz/en/reference/messaging-api/#f-video)
* - [Icon](https://developers.line.biz/en/reference/messaging-api/#icon)
* - [Text](https://developers.line.biz/en/reference/messaging-api/#f-text)
* - [Span](https://developers.line.biz/en/reference/messaging-api/#span)
@@ -889,6 +995,7 @@ export type FlexComponent =
| FlexBox
| FlexButton
| FlexImage
| FlexVideo
| FlexIcon
| FlexText
| FlexSpan
@@ -967,10 +1074,18 @@ export type FlexBox = {
* Width of the box. For more information, see [Width of a box](https://developers.line.biz/en/docs/messaging-api/flex-message-layout/#box-width) in the API documentation.
*/
width?: string;
/**
* Max width of the box. For more information, see [Max width of a box](https://developers.line.biz/en/docs/messaging-api/flex-message-layout/#box-max-width) in the API documentation.
*/
maxWidth?: string;
/**
* Height of the box. For more information, see [Height of a box](https://developers.line.biz/en/docs/messaging-api/flex-message-layout/#box-height) in the API documentation.
*/
height?: string;
/**
* Max height of the box. For more information, see [Max height of a box](https://developers.line.biz/en/docs/messaging-api/flex-message-layout/#box-max-height) in the API documentation.
*/
maxHeight?: string;
/**
* The ratio of the width or height of this box within the parent box. The
* default value for the horizontal parent box is `1`, and the default value
@@ -989,7 +1104,7 @@ export type FlexBox = {
* - To override this setting for a specific component, set the `margin`
* property of that component.
*/
spacing?: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
spacing?: string | "none" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
/**
* Minimum space between this box and the previous component in the parent box.
*
@@ -1000,7 +1115,7 @@ export type FlexBox = {
* - If this box is the first component in the parent box, the `margin`
* property will be ignored.
*/
margin?: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
margin?: string | "none" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
/**
* Free space between the borders of this box and the child element.
* For more information, see [Box padding](https://developers.line.biz/en/docs/messaging-api/flex-message-layout/#padding-property) in the API documentation.
@@ -1032,6 +1147,25 @@ export type FlexBox = {
* Specify an [action object](https://developers.line.biz/en/reference/messaging-api/#action-objects).
*/
action?: Action;
/**
* How child elements are aligned along the main axis of the parent element. If the
* parent element is a horizontal box, this only takes effect when its child elements have
* their `flex` property set equal to 0. For more information, see [Arranging a box's child elements and free space](https://developers.line.biz/en/docs/messaging-api/flex-message-layout/#justify-property)
* in the Messaging API documentation.
*/
justifyContent?:
| "flex-start"
| "center"
| "flex-end"
| "space-between"
| "space-around"
| "space-evenly";
/**
* How child elements are aligned along the cross axis of the parent element. For more
* information, see [Arranging a box's child elements and free space](https://developers.line.biz/en/docs/messaging-api/flex-message-layout/#justify-property) in the Messaging API documentation.
*/
alignItems?: "flex-start" | "center" | "flex-end";
background?: Background;
} & Offset;
export type Offset = {
@@ -1066,6 +1200,49 @@ export type Offset = {
offsetEnd?: string;
};
export type Background = {
/**
* The type of background used. Specify these values:
* - `linearGradient`: Linear gradient. For more information, see [Linear gradient backgrounds](https://developers.line.biz/en/docs/messaging-api/flex-message-layout/#linear-gradient-bg) in the Messaging API documentation.
*/
type: "linearGradient";
/**
* The angle at which a linear gradient moves. Specify the angle using an integer value
* like `90deg` (90 degrees) or a decimal number like `23.5deg` (23.5 degrees) in the
* half-open interval [0, 360). The direction of the linear gradient rotates clockwise as the
* angle increases. Given a value of `0deg`, the gradient starts at the bottom and ends at
* the top; given a value of `45deg`, the gradient starts at the bottom-left corner and ends
* at the top-right corner; given a value of 90deg, the gradient starts at the left and ends
* at the right; and given a value of `180deg`, the gradient starts at the top and ends at
* the bottom. For more information, see [Direction (angle) of linear gradient backgrounds](https://developers.line.biz/en/docs/messaging-api/flex-message-layout/#linear-gradient-bg-angle) in the Messaging API documentation.
*/
angle: string;
/**
* The color at the gradient's starting point. Use a hexadecimal color code in the
* `#RRGGBB` or `#RRGGBBAA` format.
*/
startColor: string;
/**
* The color at the gradient's ending point. Use a hexadecimal color code in the
* `#RRGGBB` or `#RRGGBBAA` format.
*/
endColor: string;
/**
* The color in the middle of the gradient. Use a hexadecimal color code in the `#RRGGBB`
* or `#RRGGBBAA` format. Specify a value for the `background.centerColor` property to
* create a gradient that has three colors. For more information, see [Intermediate color stops for linear gradients](https://developers.line.biz/en/docs/messaging-api/flex-message-layout/#linear-gradient-bg-center-color) in the
* Messaging API documentation.
*/
centerColor?: string;
/**
* The position of the intermediate color stop. Specify an integer or decimal value
* between `0%` (the starting point) and `100%` (the ending point). This is `50%` by
* default. For more information, see [Intermediate color stops for linear gradients](https://developers.line.biz/en/docs/messaging-api/flex-message-layout/#linear-gradient-bg-center-color) in the
* Messaging API documentation.
*/
centerPosition?: string;
};
/**
* This component draws a button.
*
@@ -1099,7 +1276,7 @@ export type FlexButton = {
* - If this box is the first component in the parent box, the `margin`
* property will be ignored.
*/
margin?: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
margin?: string | "none" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
/**
* Height of the button. The default value is `md`.
*/
@@ -1134,6 +1311,18 @@ export type FlexButton = {
* property will be ignored.
*/
gravity?: "top" | "bottom" | "center";
/**
* The method by which to adjust the text font size. Specify this value:
*
* - `shrink-to-fit`: Automatically shrink the font
* size to fit the width of the component. This
* property takes a "best-effort" approach that may
* work differently—or not at all!—on some platforms.
* For more information, see [Automatically shrink fonts to fit](https://developers.line.biz/en/docs/messaging-api/flex-message-layout/#adjusts-fontsize-to-fit)
* in the Messaging API documentation.
* - LINE 10.13.0 or later for iOS and Android
*/
adjustMode?: "shrink-to-fit";
} & Offset;
/**
@@ -1156,7 +1345,7 @@ export type FlexFiller = {
export type FlexIcon = {
type: "icon";
/**
* Image URL
* Image URL (Max character limit: 2000)
*
* Protocol: HTTPS
* Image format: JPEG or PNG
@@ -1175,13 +1364,15 @@ export type FlexIcon = {
* - If this box is the first component in the parent box, the `margin`
* property will be ignored.
*/
margin?: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
margin?: string | "none" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
/**
* Maximum size of the icon width.
* The size increases in the order of listing.
* The default value is `md`.
* For more information, see [Icon, text, and span size](https://developers.line.biz/en/docs/messaging-api/flex-message-layout/#other-component-size) in the Messaging API documentation.
*/
size?:
| string
| "xxs"
| "xs"
| "sm"
@@ -1207,7 +1398,7 @@ export type FlexIcon = {
export type FlexImage = {
type: "image";
/**
* Image URL
* Image URL (Max character limit: 2000)
*
* - Protocol: HTTPS
* - Image format: JPEG or PNG
@@ -1236,7 +1427,7 @@ export type FlexImage = {
* - If this box is the first component in the parent box, the `margin`
* property will be ignored.
*/
margin?: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
margin?: string | "none" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
/**
* Horizontal alignment style. Specify one of the following values:
*
@@ -1263,8 +1454,10 @@ export type FlexImage = {
* Maximum size of the image width.
* The size increases in the order of listing.
* The default value is `md`.
* For more information, see [Image size](https://developers.line.biz/en/docs/messaging-api/flex-message-layout/#image-size) in the Messaging API documentation.
*/
size?:
| string
| "xxs"
| "xs"
| "sm"
@@ -1304,8 +1497,63 @@ export type FlexImage = {
* Specify an [action object](https://developers.line.biz/en/reference/messaging-api/#action-objects).
*/
action?: Action;
/**
* When this is `true`, an animated image (APNG) plays.
* You can specify a value of `true` up to three times in a single message.
* You can't send messages that exceed this limit.
* This is `false` by default.
* Animated images larger than 300 KB aren't played back.
*/
animated?: Boolean;
} & Offset;
/**
* This component draws a video.
*/
export type FlexVideo = {
type: "video";
/**
* Video file URL (Max character limit: 2000)
*
* - Protocol: HTTPS (TLS 1.2 or later)
* - Video format: mp4
* - Maximum data size: 200 MB
*/
url: string;
/**
* Preview image URL (Max character limit: 2000)
*
* - Protocol: HTTPS (TLS 1.2 or later)
* - Image format: JPEG or PNG
* - Maximum data size: 1 MB
*/
previewUrl: string;
/**
* Alternative content.
*
* The alternative content will be displayed on the screen of a user device
* that is using a version of LINE that doesn't support the video component.
* Specify a box or an image.
*
* - Protocol: HTTPS (TLS 1.2 or later)
* - Image format: JPEG or PNG
* - Maximum data size: 1 MB
*/
altContent: FlexBox | FlexImage;
/**
* Aspect ratio of the video. `{width}:{height}` format.
* Specify the value of `{width}` and `{height}` in the range from 1 to 100000. However,
* you cannot set `{height}` to a value that is more than three times the value of `{width}`.
* The default value is `1:1`.
*/
aspectRatio?: string;
/**
* Action performed when this button is tapped.
* Specify an [action object](https://developers.line.biz/en/reference/messaging-api/#action-objects).
*/
action?: Action;
};
/**
* This component draws a separator between components in the parent box.
*/
@@ -1322,7 +1570,7 @@ export type FlexSeparator = {
* - If this box is the first component in the parent box, the `margin`
* property will be ignored.
*/
margin?: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
margin?: string | "none" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
/**
* Color of the separator. Use a hexadecimal color code.
*/
@@ -1332,6 +1580,7 @@ export type FlexSeparator = {
/**
* This is an invisible component that places a fixed-size space at the
* beginning or end of the box.
* @deprecated
*/
export type FlexSpacer = {
type: "spacer";
@@ -1342,14 +1591,20 @@ export type FlexSpacer = {
*/
size?: "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
};
export type FlexText = {
type FlexTextBase = {
type: "text";
text: string;
/**
* Array of spans. Be sure to set either one of the `text` property or `contents` property. If you set the `contents` property, `text` is ignored.
* The method by which to adjust the text font size. Specify this value:
*
* - `shrink-to-fit`: Automatically shrink the font
* size to fit the width of the component. This
* property takes a "best-effort" approach that may
* work differently—or not at all!—on some platforms.
* For more information, see [Automatically shrink fonts to fit](https://developers.line.biz/en/docs/messaging-api/flex-message-layout/#adjusts-fontsize-to-fit)
* in the Messaging API documentation.
* - LINE 10.13.0 or later for iOS and Android
*/
contents?: FlexSpan[];
adjustMode?: "shrink-to-fit";
/**
* The ratio of the width or height of this box within the parent box.
*
@@ -1371,13 +1626,15 @@ export type FlexText = {
* - If this box is the first component in the parent box, the `margin`
* property will be ignored.
*/
margin?: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
margin?: string | "none" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
/**
* Font size.
* The size increases in the order of listing.
* The default value is `md`.
* For more information, see [Icon, text, and span size](https://developers.line.biz/en/docs/messaging-api/flex-message-layout/#other-component-size) in the Messaging API documentation.
*/
size?:
| string
| "xxs"
| "xs"
| "sm"
@@ -1420,6 +1677,14 @@ export type FlexText = {
* line.
*/
wrap?: boolean;
/**
* Line spacing in a wrapping text.
*
* Specify a positive integer or decimal number that ends in px.
* The `lineSpacing` property doesn't apply to the top of the start line and the bottom of the last line.
* For more information, see [Increase the line spacing in a text](https://developers.line.biz/en/docs/messaging-api/flex-message-elements/#text-line-spacing) in the Messaging API documentation.
*/
lineSpacing?: string;
/**
* Max number of lines. If the text does not fit in the specified number of
* lines, an ellipsis (…) is displayed at the end of the last line. If set to
@@ -1458,7 +1723,22 @@ export type FlexText = {
* The default value is `none`.
*/
decoration?: string;
} & Offset;
};
type FlexTextWithText = FlexTextBase & {
text: string;
contents?: never;
};
type FlexTextWithContents = FlexTextBase & {
/**
* Array of spans. Be sure to set either one of the `text` property or `contents` property. If you set the `contents` property, `text` is ignored.
*/
contents: FlexSpan[];
text?: never;
};
export type FlexText = (FlexTextWithText | FlexTextWithContents) & Offset;
/**
* This component renders multiple text strings with different designs in one row. You can specify the color, size, weight, and decoration for the font. Span is set to `contents` property in [Text](https://developers.line.biz/en/reference/messaging-api/#f-text).
@@ -1475,8 +1755,20 @@ export type FlexSpan = {
color?: string;
/**
* Font size. You can specify one of the following values: `xxs`, `xs`, `sm`, `md`, `lg`, `xl`, `xxl`, `3xl`, `4xl`, or `5xl`. The size increases in the order of listing. The default value is `md`.
* For more information, see [Icon, text, and span size](https://developers.line.biz/en/docs/messaging-api/flex-message-layout/#other-component-size) in the Messaging API documentation.
*/
size?: string;
size?:
| string
| "xxs"
| "xs"
| "sm"
| "md"
| "lg"
| "xl"
| "xxl"
| "3xl"
| "4xl"
| "5xl";
/**
* Font weight. You can specify one of the following values: `regular` or `bold`. Specifying `bold` makes the font bold. The default value is `regular`.
*/
@@ -1519,7 +1811,7 @@ export type TemplateContent =
export type TemplateButtons = {
type: "buttons";
/**
* Image URL (Max: 1000 characters)
* Image URL (Max: 2000 characters)
*
* - HTTPS
* - JPEG or PNG
@@ -1633,7 +1925,7 @@ export type TemplateCarousel = {
export type TemplateColumn = {
/**
* Image URL (Max: 1000 characters)
* Image URL (Max: 2000 characters)
*
* - HTTPS
* - JPEG or PNG
@@ -1682,7 +1974,7 @@ export type TemplateImageCarousel = {
export type TemplateImageColumn = {
/**
* Image URL (Max: 1000 characters)
* Image URL (Max: 2000 characters)
*
* - HTTPS
* - JPEG or PNG
@@ -1752,6 +2044,7 @@ export type QuickReplyItem = {
* - [Camera action](https://developers.line.biz/en/reference/messaging-api/#camera-action)
* - [Camera roll action](https://developers.line.biz/en/reference/messaging-api/#camera-roll-action)
* - [Location action](https://developers.line.biz/en/reference/messaging-api/#location-action)
* - [URI action](https://developers.line.biz/en/reference/messaging-api/#uri-action)
*/
action: Action;
};
@@ -1780,6 +2073,7 @@ export type Sender = {
* - [Message action](https://developers.line.biz/en/reference/messaging-api/#message-action)
* - [URI action](https://developers.line.biz/en/reference/messaging-api/#uri-action)
* - [Datetime picker action](https://developers.line.biz/en/reference/messaging-api/#datetime-picker-action)
* - [Rich menu switch action](https://developers.line.biz/en/reference/messaging-api/#richmenu-switch-action)
* - [Camera action](https://developers.line.biz/en/reference/messaging-api/#camera-action)
* - [Camera roll action](https://developers.line.biz/en/reference/messaging-api/#camera-roll-action)
* - [Location action](https://developers.line.biz/en/reference/messaging-api/#location-action)
@@ -1789,6 +2083,7 @@ export type Action<ExtraFields = { label: string }> = (
| MessageAction
| URIAction
| DatetimePickerAction
| RichMenuSwitchAction
| { type: "camera" }
| { type: "cameraRoll" }
| { type: "location" }
@@ -1917,6 +2212,28 @@ export type Size = {
height: number;
};
/**
* When a control associated with this action is tapped, the URI specified in
* the `uri` property is opened.
*/
export type RichMenuSwitchAction = {
type: "richmenuswitch";
/**
* Action label. Optional for rich menus. Read when the user's device accessibility feature is enabled.
* Max character limit: 20. Supported on LINE for iOS 8.2.0 or later.
*/
label?: string;
/**
* Rich menu alias ID to switch to.
*/
richMenuAliasId: string;
/**
* String returned by the postback.data property of the postback event via a webhook
* Max character limit: 300
*/
data: string;
};
/**
* Rich menus consist of either of these objects.
*
@@ -1961,7 +2278,7 @@ export type RichMenu = {
* which define the coordinates and size of tappable areas
* (Max: 20 area objects)
*/
areas: Array<{ bounds: Area; action: Action<{}> }>;
areas: Array<{ bounds: Area; action: Action<{ label?: string }> }>;
};
export type RichMenuResponse = { richMenuId: string } & RichMenu;
@@ -2201,9 +2518,16 @@ type AudienceObject = {
audienceGroupId: number;
};
type RedeliveryObject = {
type: "redelivery";
requestId: string;
};
export type ReceieptObject =
| AudienceObject
| FilterOperatorObject<AudienceObject>;
| RedeliveryObject
| FilterOperatorObject<AudienceObject>
| FilterOperatorObject<RedeliveryObject>;
type DemographicAge =
| "age_15"
@@ -2357,6 +2681,8 @@ export type NarrowcastProgressResponse = (
successCount: number;
failureCount: number;
targetCount: string;
acceptedTime: string;
completedTime: string;
})
) & {
errorCode?: 1 | 2;
@@ -2430,6 +2756,30 @@ export type ChannelAccessToken = {
access_token: string;
expires_in: number;
token_type: "Bearer";
key_id?: string;
};
export type VerifyAccessToken = {
scope: string;
client_id: string;
expires_in: number;
};
export type VerifyIDToken = {
scope: string;
client_id: string;
expires_in: number;
iss: string;
sub: string;
aud: number;
exp: number;
iat: number;
nonce: string;
amr: string[];
name: string;
picture: string;
email: string;
};
/**
@@ -2452,3 +2802,50 @@ export type GroupSummaryResponse = {
export type MembersCountResponse = {
count: number;
};
export type GetRichMenuAliasResponse = {
richMenuAliasId: string;
richMenuId: string;
};
export type GetRichMenuAliasListResponse = {
aliases: GetRichMenuAliasResponse[];
};
/**
* Response body of get bot info.
*
* @see [Get bot info](https://developers.line.biz/en/reference/messaging-api/#get-bot-info)
*/
export type BotInfoResponse = {
userId: string;
basicId: string;
premiumId?: string;
displayName: string;
pictureUrl?: string;
chatMode: "chat" | "bot";
markAsReadMode: "auto" | "manual";
};
/**
* Response body of get webhook endpoint info.
*
* @see [Get get webhook endpoint info](https://developers.line.biz/en/reference/messaging-api/#get-webhook-endpoint-information)
*/
export type WebhookEndpointInfoResponse = {
endpoint: string;
active: boolean;
};
/**
* Response body of test webhook endpoint.
*
* @see [Test webhook endpoint](https://developers.line.biz/en/reference/messaging-api/#test-webhook-endpoint)
*/
export type TestWebhookEndpointResponse = {
success: boolean;
timestamp: string;
statusCode: number;
reason: string;
detail: string;
};
+16
View File
@@ -1,4 +1,5 @@
import { JSONParseError } from "./exceptions";
import * as FormData from "form-data";
export function toArray<T>(maybeArr: T | T[]): T[] {
return Array.isArray(maybeArr) ? maybeArr : [maybeArr];
@@ -11,3 +12,18 @@ export function ensureJSON<T>(raw: T): T {
throw new JSONParseError("Failed to parse response body as JSON", raw);
}
}
export function createMultipartFormData(
this: FormData | void,
formBody: Record<string, any>,
): FormData {
const formData = this instanceof FormData ? this : new FormData();
Object.entries(formBody).forEach(([key, value]) => {
if (Buffer.isBuffer(value) || value instanceof Uint8Array) {
formData.append(key, value);
} else {
formData.append(key, String(value));
}
});
return formData;
}