import { Readable } from "stream" ; import HTTPClient from "./http" ; import * as Types from "./types" ; import { AxiosResponse , AxiosRequestConfig } from "axios" ; import { createMultipartFormData , ensureJSON , toArray } from "./utils" ; type ChatType = "group" | "room" ; type RequestOption = { retryKey : string ; } ; import { MESSAGING_API_PREFIX , DATA_API_PREFIX , OAUTH_BASE_PREFIX , OAUTH_BASE_PREFIX_V2_1 , } from "./endpoints" ; export default class Client { public config : Types . ClientConfig ; private http : HTTPClient ; private requestOption : Partial < RequestOption > = { } ; constructor ( config ) { if ( ! config . channelAccessToken ) { throw new Error ( "no channel access token" ) ; } this . config = config ; this . http = new HTTPClient ( { defaultHeaders : { Authorization : "Bearer " + this . config . channelAccessToken , } , responseParser : this . parseHTTPResponse . bind ( this ) , ... config . httpConfig , } ) ; } public setRequestOptionOnce ( option ) { this . requestOption = option ; } private generateRequestConfig ( ) { const config = { headers : { } } ; if ( this . requestOption . retryKey ) { config . headers [ "X-Line-Retry-Key" ] = this . requestOption . retryKey ; } this . requestOption = { } ; return config ; } private parseHTTPResponse ( response ) { const { LINE_REQUEST_ID_HTTP_HEADER_NAME } = Types ; let resBody = { ... response . data , } ; if ( response . headers [ LINE_REQUEST_ID_HTTP_HEADER_NAME ] ) { resBody [ LINE_REQUEST_ID_HTTP_HEADER_NAME ] = response . headers [ LINE_REQUEST_ID_HTTP_HEADER_NAME ] ; } return resBody ; } public pushMessage ( to , messages , notificationDisabled = false ) { return this . http . post ( `${ MESSAGING_API_PREFIX }/message/push` , { messages : toArray ( messages ) , to , notificationDisabled , } , this . generateRequestConfig ( ) ) ; } public replyMessage ( replyToken , messages , notificationDisabled = false ) { return this . http . post ( `${ MESSAGING_API_PREFIX }/message/reply` , { messages : toArray ( messages ) , replyToken , notificationDisabled , } ) ; } public async multicast ( to , messages , notificationDisabled = false ) { return this . http . post ( `${ MESSAGING_API_PREFIX }/message/multicast` , { messages : toArray ( messages ) , to , notificationDisabled , } , this . generateRequestConfig ( ) ) ; } public async narrowcast ( messages , recipient ? , filter ? , limit ? , notificationDisabled ? ) { return this . http . post ( `${ MESSAGING_API_PREFIX }/message/narrowcast` , { messages : toArray ( messages ) , recipient , filter , limit , notificationDisabled , } , this . generateRequestConfig ( ) ) ; } public async broadcast ( messages , notificationDisabled = false ) { return this . http . post ( `${ MESSAGING_API_PREFIX }/message/broadcast` , { messages : toArray ( messages ) , notificationDisabled , } , this . generateRequestConfig ( ) ) ; } public async getProfile ( userId ) { const profile = await this . http . get < Types . Profile > ( `${ MESSAGING_API_PREFIX }/profile/${ userId }` ) ; return ensureJSON ( profile ) ; } private async getChatMemberProfile ( chatType , chatId , userId ) { const profile = await this . http . get < Types . Profile > ( `${ MESSAGING_API_PREFIX }/${ chatType }/${ chatId }/member/${ userId }` ) ; return ensureJSON ( profile ) ; } public async getGroupMemberProfile ( groupId , userId ) { return this . getChatMemberProfile ( "group" , groupId , userId ) ; } public async getRoomMemberProfile ( roomId , userId ) { return this . getChatMemberProfile ( "room" , roomId , userId ) ; } private async getChatMemberIds ( chatType , chatId ) { let memberIds = [ ] ; let start ; do { const res = await this . http . get < { memberIds : string [ ] ; next ? : string ; } > ( `${ MESSAGING_API_PREFIX }/${ chatType }/${ chatId }/members/ids` , start ? { start } : null ) ; ensureJSON ( res ) ; memberIds = memberIds . concat ( res . memberIds ) ; start = res . next ; } while ( start ) ; return memberIds ; } public async getGroupMemberIds ( groupId ) { return this . getChatMemberIds ( "group" , groupId ) ; } public async getRoomMemberIds ( roomId ) { return this . getChatMemberIds ( "room" , roomId ) ; } public async getBotFollowersIds ( ) { let userIds = [ ] ; let start ; do { const res = await this . http . get < { userIds : string [ ] ; next ? : string ; } > ( `${ MESSAGING_API_PREFIX }/followers/ids` , start ? { start } : null ) ; ensureJSON ( res ) ; userIds = userIds . concat ( res . userIds ) ; start = res . next ; } while ( start ) ; return userIds ; } public async getGroupMembersCount ( groupId ) { const groupMemberCount = await this . http . get < Types . MembersCountResponse > ( `${ MESSAGING_API_PREFIX }/group/${ groupId }/members/count` ) ; return ensureJSON ( groupMemberCount ) ; } public async getRoomMembersCount ( roomId ) { const roomMemberCount = await this . http . get < Types . MembersCountResponse > ( `${ MESSAGING_API_PREFIX }/room/${ roomId }/members/count` ) ; return ensureJSON ( roomMemberCount ) ; } public async getGroupSummary ( groupId ) { const groupSummary = await this . http . get < Types . GroupSummaryResponse > ( `${ MESSAGING_API_PREFIX }/group/${ groupId }/summary` ) ; return ensureJSON ( groupSummary ) ; } public async getMessageContent ( messageId ) { return this . http . getStream ( `${ DATA_API_PREFIX }/message/${ messageId }/content` ) ; } private leaveChat ( chatType , chatId ) { return this . http . post ( `${ MESSAGING_API_PREFIX }/${ chatType }/${ chatId }/leave` ) ; } public async leaveGroup ( groupId ) { return this . leaveChat ( "group" , groupId ) ; } public async leaveRoom ( roomId ) { return this . leaveChat ( "room" , roomId ) ; } public async getRichMenu ( richMenuId ) { const res = await this . http . get < Types . RichMenuResponse > ( `${ MESSAGING_API_PREFIX }/richmenu/${ richMenuId }` ) ; return ensureJSON ( res ) ; } public async createRichMenu ( richMenu ) { const res = await this . http . post < any > ( `${ MESSAGING_API_PREFIX }/richmenu` , richMenu ) ; return ensureJSON ( res ) . richMenuId ; } public async deleteRichMenu ( richMenuId ) { return this . http . delete ( `${ MESSAGING_API_PREFIX }/richmenu/${ richMenuId }` ) ; } public async getRichMenuAliasList ( ) { const res = await this . http . get < Types . GetRichMenuAliasListResponse > ( `${ MESSAGING_API_PREFIX }/richmenu/alias/list` ) ; return ensureJSON ( res ) ; } public async getRichMenuAlias ( richMenuAliasId ) { const res = await this . http . get < Types . GetRichMenuAliasResponse > ( `${ MESSAGING_API_PREFIX }/richmenu/alias/${ richMenuAliasId }` ) ; return ensureJSON ( res ) ; } public async createRichMenuAlias ( richMenuId , richMenuAliasId ) { const res = await this . http . post < { } > ( `${ MESSAGING_API_PREFIX }/richmenu/alias` , { richMenuId , richMenuAliasId , } ) ; return ensureJSON ( res ) ; } public async deleteRichMenuAlias ( richMenuAliasId ) { const res = this . http . delete < { } > ( `${ MESSAGING_API_PREFIX }/richmenu/alias/${ richMenuAliasId }` ) ; return ensureJSON ( res ) ; } public async updateRichMenuAlias ( richMenuAliasId , richMenuId ) { const res = await this . http . post < { } > ( `${ MESSAGING_API_PREFIX }/richmenu/alias/${ richMenuAliasId }` , { richMenuId , } ) ; return ensureJSON ( res ) ; } public async getRichMenuIdOfUser ( userId ) { const res = await this . http . get < any > ( `${ MESSAGING_API_PREFIX }/user/${ userId }/richmenu` ) ; return ensureJSON ( res ) . richMenuId ; } public async linkRichMenuToUser ( userId , richMenuId ) { return this . http . post ( `${ MESSAGING_API_PREFIX }/user/${ userId }/richmenu/${ richMenuId }` ) ; } public async unlinkRichMenuFromUser ( userId ) { return this . http . delete ( `${ MESSAGING_API_PREFIX }/user/${ userId }/richmenu` ) ; } public async linkRichMenuToMultipleUsers ( richMenuId , userIds ) { return this . http . post ( `${ MESSAGING_API_PREFIX }/richmenu/bulk/link` , { richMenuId , userIds , } ) ; } public async unlinkRichMenusFromMultipleUsers ( userIds ) { return this . http . post ( `${ MESSAGING_API_PREFIX }/richmenu/bulk/unlink` , { userIds , } ) ; } public async getRichMenuImage ( richMenuId ) { return this . http . getStream ( `${ DATA_API_PREFIX }/richmenu/${ richMenuId }/content` ) ; } public async setRichMenuImage ( richMenuId , data , contentType ? ) { return this . http . postBinary ( `${ DATA_API_PREFIX }/richmenu/${ richMenuId }/content` , data , contentType ) ; } public async getRichMenuList ( ) { const res = await this . http . get < any > ( `${ MESSAGING_API_PREFIX }/richmenu/list` ) ; return ensureJSON ( res ) . richmenus ; } public async setDefaultRichMenu ( richMenuId ) { return this . http . post ( `${ MESSAGING_API_PREFIX }/user/all/richmenu/${ richMenuId }` ) ; } public async getDefaultRichMenuId ( ) { const res = await this . http . get < any > ( `${ MESSAGING_API_PREFIX }/user/all/richmenu` ) ; return ensureJSON ( res ) . richMenuId ; } public async deleteDefaultRichMenu ( ) { return this . http . delete ( `${ MESSAGING_API_PREFIX }/user/all/richmenu` ) ; } public async getLinkToken ( userId ) { const res = await this . http . post < any > ( `${ MESSAGING_API_PREFIX }/user/${ userId }/linkToken` ) ; return ensureJSON ( res ) . linkToken ; } public async getNumberOfSentReplyMessages ( date ) { const res = await this . http . get < Types . NumberOfMessagesSentResponse > ( `${ MESSAGING_API_PREFIX }/message/delivery/reply?date=${ date }` ) ; return ensureJSON ( res ) ; } public async getNumberOfSentPushMessages ( date ) { const res = await this . http . get < Types . NumberOfMessagesSentResponse > ( `${ MESSAGING_API_PREFIX }/message/delivery/push?date=${ date }` ) ; return ensureJSON ( res ) ; } public async getNumberOfSentMulticastMessages ( date ) { const res = await this . http . get < Types . NumberOfMessagesSentResponse > ( `${ MESSAGING_API_PREFIX }/message/delivery/multicast?date=${ date }` ) ; return ensureJSON ( res ) ; } public async getNarrowcastProgress ( requestId ) { const res = await this . http . get < Types . NarrowcastProgressResponse > ( `${ MESSAGING_API_PREFIX }/message/progress/narrowcast?requestId=${ requestId }` ) ; return ensureJSON ( res ) ; } public async getTargetLimitForAdditionalMessages ( ) { const res = await this . http . get < Types . TargetLimitForAdditionalMessages > ( `${ MESSAGING_API_PREFIX }/message/quota` ) ; return ensureJSON ( res ) ; } public async getNumberOfMessagesSentThisMonth ( ) { const res = await this . http . get < Types . NumberOfMessagesSentThisMonth > ( `${ MESSAGING_API_PREFIX }/message/quota/consumption` ) ; return ensureJSON ( res ) ; } public async getNumberOfSentBroadcastMessages ( date ) { const res = await this . http . get < Types . NumberOfMessagesSentResponse > ( `${ MESSAGING_API_PREFIX }/message/delivery/broadcast?date=${ date }` ) ; return ensureJSON ( res ) ; } public async getNumberOfMessageDeliveries ( date ) { const res = await this . http . get < Types . NumberOfMessageDeliveriesResponse > ( `${ MESSAGING_API_PREFIX }/insight/message/delivery?date=${ date }` ) ; return ensureJSON ( res ) ; } public async getNumberOfFollowers ( date ) { const res = await this . http . get < Types . NumberOfFollowersResponse > ( `${ MESSAGING_API_PREFIX }/insight/followers?date=${ date }` ) ; return ensureJSON ( res ) ; } public async getFriendDemographics ( ) { const res = await this . http . get < Types . FriendDemographics > ( `${ MESSAGING_API_PREFIX }/insight/demographic` ) ; return ensureJSON ( res ) ; } public async getUserInteractionStatistics ( requestId ) { const res = await this . http . get < Types . UserInteractionStatistics > ( `${ MESSAGING_API_PREFIX }/insight/message/event?requestId=${ requestId }` ) ; return ensureJSON ( res ) ; } public async createUploadAudienceGroup ( uploadAudienceGroup ) { const res = await this . http . post < { audienceGroupId : number ; type : string ; description : string ; created : number ; } > ( `${ MESSAGING_API_PREFIX }/audienceGroup/upload` , { ... uploadAudienceGroup , } ) ; return ensureJSON ( res ) ; } public async createUploadAudienceGroupByFile ( uploadAudienceGroup ) { 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 , httpConfig ? ) { const res = await this . http . put < { } > ( `${ MESSAGING_API_PREFIX }/audienceGroup/upload` , { ... uploadAudienceGroup , } , httpConfig ) ; return ensureJSON ( res ) ; } public async updateUploadAudienceGroupByFile ( uploadAudienceGroup , httpConfig ? ) { 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 ) { const res = await this . http . post < { audienceGroupId : number ; type : string ; created : number ; } & typeof clickAudienceGroup > ( `${ MESSAGING_API_PREFIX }/audienceGroup/click` , { ... clickAudienceGroup , } ) ; return ensureJSON ( res ) ; } public async createImpAudienceGroup ( impAudienceGroup ) { const res = await this . http . post < { audienceGroupId : number ; type : string ; created : number ; } & typeof impAudienceGroup > ( `${ MESSAGING_API_PREFIX }/audienceGroup/imp` , { ... impAudienceGroup , } ) ; return ensureJSON ( res ) ; } public async setDescriptionAudienceGroup ( description , audienceGroupId ) { const res = await this . http . put < { } > ( `${ MESSAGING_API_PREFIX }/audienceGroup/${ audienceGroupId }/updateDescription` , { description , } ) ; return ensureJSON ( res ) ; } public async deleteAudienceGroup ( audienceGroupId ) { const res = await this . http . delete < { } > ( `${ MESSAGING_API_PREFIX }/audienceGroup/${ audienceGroupId }` ) ; return ensureJSON ( res ) ; } public async getAudienceGroup ( audienceGroupId ) { const res = await this . http . get < Types . AudienceGroup > ( `${ MESSAGING_API_PREFIX }/audienceGroup/${ audienceGroupId }` ) ; return ensureJSON ( res ) ; } public async getAudienceGroups ( page , description ? , status ? , size ? , createRoute ? , includesExternalPublicGroups ? ) { const res = await this . http . get < { audienceGroups : Types . AudienceGroups ; hasNextPage : boolean ; totalCount : number ; readWriteAudienceGroupTotalCount : number ; page : number ; size : number ; } > ( `${ MESSAGING_API_PREFIX }/audienceGroup/list` , { page , description , status , size , createRoute , includesExternalPublicGroups , } ) ; return ensureJSON ( res ) ; } public async getAudienceGroupAuthorityLevel ( ) { const res = await this . http . get < { authorityLevel : Types . AudienceGroupAuthorityLevel ; } > ( `${ MESSAGING_API_PREFIX }/audienceGroup/authorityLevel` ) ; return ensureJSON ( res ) ; } public async changeAudienceGroupAuthorityLevel ( authorityLevel ) { const res = await this . http . put < { } > ( `${ MESSAGING_API_PREFIX }/audienceGroup/authorityLevel` , { authorityLevel } ) ; return ensureJSON ( res ) ; } public async getBotInfo ( ) { const res = await this . http . get < Types . BotInfoResponse > ( `${ MESSAGING_API_PREFIX }/info` ) ; return ensureJSON ( res ) ; } public async setWebhookEndpointUrl ( endpoint ) { 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 ? ) { const res = await this . http . post < Types . TestWebhookEndpointResponse > ( `${ MESSAGING_API_PREFIX }/channel/webhook/test` , { endpoint } ) ; return ensureJSON ( res ) ; } } export class OAuth { private http : HTTPClient ; constructor ( ) { this . http = new HTTPClient ( ) ; } public issueAccessToken ( client_id , client_secret ) { return this . http . postForm ( `${ OAUTH_BASE_PREFIX }/accessToken` , { grant_type : "client_credentials" , client_id , client_secret , } ) ; } public revokeAccessToken ( access_token ) { return this . http . postForm ( `${ OAUTH_BASE_PREFIX }/revoke` , { access_token } ) ; } public verifyAccessToken ( access_token ) { return this . http . get ( `${ OAUTH_BASE_PREFIX_V2_1 }/verify` , { access_token } ) ; } public verifyIdToken ( id_token , client_id , nonce ? , user_id ? ) { return this . http . postForm ( `${ OAUTH_BASE_PREFIX }/verify` , { id_token , client_id , nonce , user_id , } ) ; } public issueChannelAccessTokenV2_1 ( client_assertion ) { 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" , client_assertion , } ) ; } public getChannelAccessTokenKeyIdsV2_1 ( client_assertion ) { 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 , } ) ; } public revokeChannelAccessTokenV2_1 ( client_id , client_secret , access_token ) { return this . http . postForm ( `${ OAUTH_BASE_PREFIX_V2_1 }/revoke` , { client_id , client_secret , access_token , } ) ; } }