messaging-api-slack
Advanced tools
Comparing version 1.0.0-alpha.2 to 1.0.0-alpha.4
import { AxiosInstance } from 'axios'; | ||
import { SlackAttachment, SlackAvailableMethod, SlackChannel, SlackOAuthAPIResponse, SlackUser } from './SlackTypes'; | ||
import { Attachment, AvailableMethod, Block, Channel, OAuthAPIResponse, User } from './SlackTypes'; | ||
declare type CommonOptions = { | ||
@@ -8,19 +8,28 @@ token?: string; | ||
declare type PostEphemeralOptions = CommonOptions & { | ||
as_user?: boolean; | ||
attachments?: string | SlackAttachment[]; | ||
link_names?: boolean; | ||
asUser?: boolean; | ||
attachments?: string | Attachment[]; | ||
linkNames?: boolean; | ||
parse?: 'none' | 'full'; | ||
}; | ||
declare type GetInfoOptions = CommonOptions & { | ||
include_locale?: boolean; | ||
includeLocale?: boolean; | ||
}; | ||
declare type WithCursorOptions = CommonOptions & { | ||
declare type UserInfoOptions = CommonOptions & { | ||
includeLocale?: boolean; | ||
}; | ||
declare type ConversationMembersOptions = CommonOptions & { | ||
cursor?: string; | ||
limit?: number; | ||
}; | ||
declare type ConversationListOptions = CommonOptions & { | ||
cursor?: string; | ||
exclude_archived?: boolean; | ||
excludeArchived?: boolean; | ||
limit?: number; | ||
types?: string; | ||
}; | ||
declare type UserListOptions = CommonOptions & { | ||
cursor?: string; | ||
includeLocale?: boolean; | ||
limit?: number; | ||
}; | ||
declare type ClientConfig = { | ||
@@ -32,12 +41,12 @@ accessToken: string; | ||
interface PostMessageOptions extends CommonOptions { | ||
as_user?: boolean; | ||
attachments?: string | SlackAttachment[]; | ||
icon_emoji?: string; | ||
icon_url?: string; | ||
link_names?: boolean; | ||
asUser?: boolean; | ||
attachments?: string | Attachment[]; | ||
iconEmoji?: string; | ||
iconUrl?: string; | ||
linkNames?: boolean; | ||
parse?: 'none' | 'full'; | ||
reply_broadcast?: boolean; | ||
thread_ts?: string; | ||
unfurl_links?: boolean; | ||
unfurl_media?: boolean; | ||
replyBroadcast?: boolean; | ||
threadTs?: string; | ||
unfurlLinks?: boolean; | ||
unfurlMedia?: boolean; | ||
username?: string; | ||
@@ -53,17 +62,10 @@ } | ||
readonly accessToken: string; | ||
callMethod(method: SlackAvailableMethod, _body?: Record<string, any>): Promise<SlackOAuthAPIResponse>; | ||
callMethod(method: AvailableMethod, inputBody?: Record<string, any>): Promise<OAuthAPIResponse>; | ||
/** | ||
* Gets information about a public channel. | ||
* Gets information about a channel. | ||
* | ||
* https://api.slack.com/methods/channels.info | ||
*/ | ||
getChannelInfo(channelId: string, options?: GetInfoOptions): Promise<SlackChannel>; | ||
getChannelInfo(channelId: string, options?: GetInfoOptions): Promise<Channel>; | ||
/** | ||
* Lists all public channels in a Slack team. | ||
* | ||
* https://api.slack.com/methods/channels.list | ||
* FIXME: [breaking] support cursor, exclude_archived, exclude_members, limit | ||
*/ | ||
getChannelList(options?: CommonOptions): Promise<SlackChannel[]>; | ||
/** | ||
* Retrieve information about a conversation. | ||
@@ -73,3 +75,3 @@ * | ||
*/ | ||
getConversationInfo(channelId: string, options?: GetInfoOptions): Promise<SlackChannel>; | ||
getConversationInfo(channelId: string, options?: GetInfoOptions): Promise<Channel>; | ||
/** | ||
@@ -80,7 +82,7 @@ * Retrieve members of a conversation. | ||
*/ | ||
getConversationMembers(channelId: string, options?: WithCursorOptions): Promise<{ | ||
getConversationMembers(channelId: string, options?: ConversationMembersOptions): Promise<{ | ||
members: string[]; | ||
next?: string; | ||
}>; | ||
getAllConversationMembers(channelId: string, options?: CommonOptions): Promise<string[]>; | ||
getAllConversationMembers(channelId: string, options?: Omit<ConversationMembersOptions, 'cursor'>): Promise<string[]>; | ||
/** | ||
@@ -92,6 +94,6 @@ * Lists all channels in a Slack team. | ||
getConversationList(options?: ConversationListOptions): Promise<{ | ||
channels: SlackChannel[]; | ||
channels: Channel[]; | ||
next?: string; | ||
}>; | ||
getAllConversationList(options?: ConversationListOptions): Promise<SlackChannel[]>; | ||
getAllConversationList(options?: Omit<ConversationListOptions, 'cursor'>): Promise<Channel[]>; | ||
/** | ||
@@ -102,6 +104,7 @@ * Sends a message to a channel. | ||
*/ | ||
postMessage(channel: string, message: { | ||
postMessage(channel: string, inputMessage: { | ||
text?: string; | ||
attachments?: SlackAttachment[] | string; | ||
} | string, options?: PostMessageOptions): Promise<SlackOAuthAPIResponse>; | ||
attachments?: Attachment[] | string; | ||
blocks?: Block[] | string; | ||
} | string, options?: PostMessageOptions): Promise<OAuthAPIResponse>; | ||
/** | ||
@@ -112,6 +115,7 @@ * Sends an ephemeral message to a user in a channel. | ||
*/ | ||
postEphemeral(channel: string, user: string, message: { | ||
postEphemeral(channel: string, user: string, inputMessage: { | ||
text?: string; | ||
attachments?: SlackAttachment[] | string; | ||
} | string, options?: PostEphemeralOptions): Promise<SlackOAuthAPIResponse>; | ||
attachments?: Attachment[] | string; | ||
blocks?: Block[] | string; | ||
}, options?: PostEphemeralOptions): Promise<OAuthAPIResponse>; | ||
/** | ||
@@ -122,3 +126,3 @@ * Gets information about a user. | ||
*/ | ||
getUserInfo(userId: string, options?: GetInfoOptions): Promise<SlackUser>; | ||
getUserInfo(userId: string, options?: UserInfoOptions): Promise<User>; | ||
/** | ||
@@ -128,11 +132,10 @@ * Lists all users in a Slack team. | ||
* https://api.slack.com/methods/users.list | ||
* FIXME: [breaking] support include_locale, limit, presence | ||
*/ | ||
getUserList(cursorOrOptions?: string | WithCursorOptions): Promise<{ | ||
members: SlackUser[]; | ||
getUserList(options?: UserListOptions): Promise<{ | ||
members: User[]; | ||
next?: string; | ||
}>; | ||
getAllUserList(options?: CommonOptions): Promise<SlackUser[]>; | ||
getAllUserList(options?: Omit<UserListOptions, 'cursor'>): Promise<User[]>; | ||
} | ||
export {}; | ||
//# sourceMappingURL=SlackOAuthClient.d.ts.map |
@@ -18,3 +18,5 @@ "use strict"; | ||
const axios_1 = __importDefault(require("axios")); | ||
const camelcase_keys_1 = __importDefault(require("camelcase-keys")); | ||
const lodash_omit_1 = __importDefault(require("lodash.omit")); | ||
const snakecase_keys_1 = __importDefault(require("snakecase-keys")); | ||
const url_join_1 = __importDefault(require("url-join")); | ||
@@ -71,10 +73,12 @@ const messaging_api_common_1 = require("messaging-api-common"); | ||
} | ||
callMethod(method, _body = {}) { | ||
callMethod(method, inputBody = {}) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
try { | ||
const body = lodash_omit_1.default(_body, ['token', 'accessToken']); | ||
body.token = _body.accessToken || _body.token || this._token; | ||
const response = yield this._axios.post(method, querystring_1.default.stringify(body)); | ||
const { data, config, request } = response; | ||
const body = Object.assign(Object.assign({}, lodash_omit_1.default(inputBody, ['token', 'accessToken'])), { token: inputBody.accessToken || inputBody.token || this._token }); | ||
const response = yield this._axios.post(method, querystring_1.default.stringify(snakecase_keys_1.default(body, { deep: true }))); | ||
const data = camelcase_keys_1.default(response.data, { | ||
deep: true, | ||
}); | ||
if (!data.ok) { | ||
const { config, request } = response; | ||
throw new axios_error_1.default(`Slack API - ${data.error}`, { | ||
@@ -94,19 +98,10 @@ config, | ||
/** | ||
* Gets information about a public channel. | ||
* Gets information about a channel. | ||
* | ||
* https://api.slack.com/methods/channels.info | ||
*/ | ||
getChannelInfo(channelId, options = {}) { | ||
getChannelInfo(channelId, options) { | ||
return this.callMethod('channels.info', Object.assign({ channel: channelId }, options)).then(data => data.channel); | ||
} | ||
/** | ||
* Lists all public channels in a Slack team. | ||
* | ||
* https://api.slack.com/methods/channels.list | ||
* FIXME: [breaking] support cursor, exclude_archived, exclude_members, limit | ||
*/ | ||
getChannelList(options = {}) { | ||
return this.callMethod('channels.list', options).then(data => data.channels); | ||
} | ||
/** | ||
* Retrieve information about a conversation. | ||
@@ -116,3 +111,3 @@ * | ||
*/ | ||
getConversationInfo(channelId, options = {}) { | ||
getConversationInfo(channelId, options) { | ||
return this.callMethod('conversations.info', Object.assign({ channel: channelId }, options)).then(data => data.channel); | ||
@@ -125,9 +120,9 @@ } | ||
*/ | ||
getConversationMembers(channelId, options = {}) { | ||
getConversationMembers(channelId, options) { | ||
return this.callMethod('conversations.members', Object.assign({ channel: channelId }, options)).then(data => ({ | ||
members: data.members, | ||
next: data.response_metadata && data.response_metadata.next_cursor, | ||
next: data.responseMetadata && data.responseMetadata.nextCursor, | ||
})); | ||
} | ||
getAllConversationMembers(channelId, options = {}) { | ||
getAllConversationMembers(channelId, options) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
@@ -149,9 +144,9 @@ let allMembers = []; | ||
*/ | ||
getConversationList(options = {}) { | ||
getConversationList(options) { | ||
return this.callMethod('conversations.list', options).then(data => ({ | ||
channels: data.channels, | ||
next: data.response_metadata && data.response_metadata.next_cursor, | ||
next: data.responseMetadata && data.responseMetadata.nextCursor, | ||
})); | ||
} | ||
getAllConversationList(options = {}) { | ||
getAllConversationList(options) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
@@ -161,5 +156,5 @@ let allChannels = []; | ||
do { | ||
const _options = continuationCursor | ||
const nextOptions = continuationCursor | ||
? Object.assign({ cursor: continuationCursor }, options) : options; | ||
const { channels, next, } = yield this.getConversationList(_options); | ||
const { channels, next, } = yield this.getConversationList(nextOptions); | ||
allChannels = allChannels.concat(channels); | ||
@@ -176,17 +171,12 @@ continuationCursor = next; | ||
*/ | ||
postMessage(channel, message, options = {}) { | ||
if (options.attachments && typeof options.attachments !== 'string') { | ||
// A JSON-based array of structured attachments, presented as a URL-encoded string. | ||
postMessage(channel, inputMessage, options = {}) { | ||
const message = typeof inputMessage === 'string' ? { text: inputMessage } : inputMessage; | ||
if (message.attachments && typeof message.attachments !== 'string') { | ||
// eslint-disable-next-line no-param-reassign | ||
options.attachments = JSON.stringify(options.attachments); | ||
message.attachments = JSON.stringify(snakecase_keys_1.default(message.attachments, { deep: true })); | ||
} | ||
else if (typeof message === 'object' && | ||
message.attachments && | ||
typeof message.attachments !== 'string') { | ||
if (message.blocks && typeof message.blocks !== 'string') { | ||
// eslint-disable-next-line no-param-reassign | ||
message.attachments = JSON.stringify(message.attachments); | ||
message.blocks = JSON.stringify(snakecase_keys_1.default(message.blocks, { deep: true })); | ||
} | ||
if (typeof message === 'string') { | ||
return this.callMethod('chat.postMessage', Object.assign({ channel, text: message }, options)); | ||
} | ||
return this.callMethod('chat.postMessage', Object.assign(Object.assign({ channel }, message), options)); | ||
@@ -199,18 +189,12 @@ } | ||
*/ | ||
postEphemeral(channel, user, message, options = {}) { | ||
if (options.attachments && typeof options.attachments !== 'string') { | ||
// A JSON-based array of structured attachments, presented as a URL-encoded string. | ||
postEphemeral(channel, user, inputMessage, options = {}) { | ||
const message = typeof inputMessage === 'string' ? { text: inputMessage } : inputMessage; | ||
if (message.attachments && typeof message.attachments !== 'string') { | ||
// eslint-disable-next-line no-param-reassign | ||
options.attachments = JSON.stringify(options.attachments); | ||
message.attachments = JSON.stringify(snakecase_keys_1.default(message.attachments, { deep: true })); | ||
} | ||
else if (typeof message === 'object' && | ||
message.attachments && | ||
typeof message.attachments !== 'string') { | ||
if (message.blocks && typeof message.blocks !== 'string') { | ||
// eslint-disable-next-line no-param-reassign | ||
message.attachments = JSON.stringify(message.attachments); | ||
message.blocks = JSON.stringify(snakecase_keys_1.default(message.blocks, { deep: true })); | ||
} | ||
if (typeof message === 'string') { | ||
return this.callMethod('chat.postEphemeral', Object.assign({ channel, | ||
user, text: message }, options)); | ||
} | ||
return this.callMethod('chat.postEphemeral', Object.assign(Object.assign({ channel, | ||
@@ -224,3 +208,3 @@ user }, message), options)); | ||
*/ | ||
getUserInfo(userId, options = {}) { | ||
getUserInfo(userId, options) { | ||
return this.callMethod('users.info', Object.assign({ user: userId }, options)).then(data => data.user); | ||
@@ -232,19 +216,10 @@ } | ||
* https://api.slack.com/methods/users.list | ||
* FIXME: [breaking] support include_locale, limit, presence | ||
*/ | ||
getUserList(cursorOrOptions) { | ||
if (typeof cursorOrOptions === 'string') { | ||
// cursorOrOptions is cursor string | ||
return this.callMethod('users.list', { cursor: cursorOrOptions }).then(data => ({ | ||
members: data.members, | ||
next: data.response_metadata && data.response_metadata.next_cursor, | ||
})); | ||
} | ||
// cursorOrOptions is options object | ||
return this.callMethod('users.list', cursorOrOptions).then(data => ({ | ||
getUserList(options) { | ||
return this.callMethod('users.list', options).then(data => ({ | ||
members: data.members, | ||
next: data.response_metadata && data.response_metadata.next_cursor, | ||
next: data.responseMetadata && data.responseMetadata.nextCursor, | ||
})); | ||
} | ||
getAllUserList(options = {}) { | ||
getAllUserList(options) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
@@ -251,0 +226,0 @@ let allUsers = []; |
@@ -1,10 +0,10 @@ | ||
export declare type SlackAttachment = { | ||
export declare type Attachment = { | ||
fallback: string; | ||
pretext?: string; | ||
color?: string; | ||
author_name?: string; | ||
author_link?: string; | ||
author_icon?: string; | ||
authorName?: string; | ||
authorLink?: string; | ||
authorIcon?: string; | ||
title?: string; | ||
title_link?: string; | ||
titleLink?: string; | ||
text?: string; | ||
@@ -16,8 +16,8 @@ fields?: { | ||
}[]; | ||
image_url?: string; | ||
thumb_url?: string; | ||
imageUrl?: string; | ||
thumbUrl?: string; | ||
footer?: string; | ||
footer_icon?: string; | ||
callback_id?: string; | ||
attachment_type?: string; | ||
footerIcon?: string; | ||
callbackId?: string; | ||
attachmentType?: string; | ||
actions: { | ||
@@ -36,4 +36,4 @@ name?: string; | ||
text?: string; | ||
ok_text?: string; | ||
dismiss_text?: string; | ||
okText?: string; | ||
dismissText?: string; | ||
}; | ||
@@ -43,17 +43,212 @@ }[]; | ||
}; | ||
export declare type CompositionObject = TextObject | ConfirmObject | OptionObject; | ||
export declare type TextObject = PlainTextObject | MrkdwnObject; | ||
export declare type PlainTextObject = { | ||
type: 'plain_text'; | ||
text: string; | ||
emoji?: boolean; | ||
}; | ||
export declare type MrkdwnObject = { | ||
type: 'mrkdwn'; | ||
text: string; | ||
verbatim?: boolean; | ||
}; | ||
export declare type ConfirmObject = { | ||
title: PlainTextObject; | ||
text: TextObject; | ||
confirm: PlainTextObject; | ||
deny: PlainTextObject; | ||
}; | ||
export declare type OptionObject = { | ||
text: PlainTextObject; | ||
value: string; | ||
url?: string; | ||
}; | ||
export declare type OptionGroupObject = { | ||
label: PlainTextObject; | ||
options: OptionObject[]; | ||
}; | ||
export declare type BlockElement = ButtonElement | DatepickerElement | ImageElement | MultiSelectElement | OverflowElement | PlainTextInputElement | RadioButtonsElement | SelectElement; | ||
export declare type ButtonElement = { | ||
type: 'button'; | ||
text: PlainTextObject; | ||
actionId: string; | ||
url?: string; | ||
value?: string; | ||
style?: 'primary' | 'danger'; | ||
confirm?: ConfirmObject; | ||
}; | ||
export declare type DatepickerElement = { | ||
type: 'datepicker'; | ||
actionId: string; | ||
placeholder?: PlainTextObject; | ||
initialDate?: string; | ||
confirm?: ConfirmObject; | ||
}; | ||
export declare type ImageElement = { | ||
type: 'image'; | ||
imageUrl: string; | ||
altText: string; | ||
}; | ||
export declare type MultiSelectElement = MultiStaticSelectElement | MultiExternalSelectElement | MultiUsersSelectElement | MultiConversationsSelectElement | MultiChannelsSelectElement; | ||
export declare type MultiStaticSelectElement = { | ||
type: 'multi_static_select'; | ||
placeholder: PlainTextObject; | ||
actionId: string; | ||
options: OptionObject[]; | ||
optionGroups?: OptionGroupObject[]; | ||
initialOptions?: OptionObject[]; | ||
confirm?: ConfirmObject; | ||
}; | ||
export declare type MultiExternalSelectElement = { | ||
type: 'multi_external_select'; | ||
placeholder: PlainTextObject; | ||
actionId: string; | ||
minQueryLength?: number; | ||
initialOptions?: OptionObject[]; | ||
confirm?: ConfirmObject; | ||
}; | ||
export declare type MultiUsersSelectElement = { | ||
type: 'multi_users_select'; | ||
placeholder: PlainTextObject; | ||
actionId: string; | ||
initialUsers?: string[]; | ||
confirm?: ConfirmObject; | ||
}; | ||
export declare type MultiConversationsSelectElement = { | ||
type: 'multi_conversations_select'; | ||
placeholder: PlainTextObject; | ||
actionId: string; | ||
initialConversations?: string[]; | ||
confirm?: ConfirmObject; | ||
}; | ||
export declare type MultiChannelsSelectElement = { | ||
type: 'multi_channels_select'; | ||
placeholder: PlainTextObject; | ||
actionId: string; | ||
initialChannels?: string[]; | ||
confirm?: ConfirmObject; | ||
}; | ||
export declare type OverflowElement = { | ||
type: 'overflow'; | ||
actionId: string; | ||
options: OptionObject[]; | ||
confirm?: ConfirmObject; | ||
}; | ||
export declare type PlainTextInputElement = { | ||
type: 'plain_text_input'; | ||
actionId: string; | ||
placeholder?: PlainTextObject; | ||
initialValue: string; | ||
multiline?: boolean; | ||
minLength?: number; | ||
maxLength?: number; | ||
}; | ||
export declare type RadioButtonsElement = { | ||
type: 'radio_buttons'; | ||
actionId: string; | ||
options: OptionObject[]; | ||
initialOption?: OptionObject; | ||
confirm?: ConfirmObject; | ||
}; | ||
export declare type SelectElement = StaticSelectElement | ExternalSelectElement | UsersSelectElement | ConversationsSelectElement | ChannelsSelectElement; | ||
export declare type StaticSelectElement = { | ||
type: 'static_select'; | ||
placeholder: PlainTextObject; | ||
actionId: string; | ||
options: OptionObject[]; | ||
optionGroups?: OptionGroupObject[]; | ||
initialOption?: OptionObject; | ||
confirm?: ConfirmObject; | ||
}; | ||
export declare type ExternalSelectElement = { | ||
type: 'external_select'; | ||
placeholder: PlainTextObject; | ||
actionId: string; | ||
minQueryLength?: number; | ||
initialOption?: OptionObject; | ||
confirm?: ConfirmObject; | ||
}; | ||
export declare type UsersSelectElement = { | ||
type: 'users_select'; | ||
placeholder: PlainTextObject; | ||
actionId: string; | ||
initialUser?: string; | ||
confirm?: ConfirmObject; | ||
}; | ||
export declare type ConversationsSelectElement = { | ||
type: 'conversations_select'; | ||
placeholder: PlainTextObject; | ||
actionId: string; | ||
initialConversation?: string; | ||
confirm?: ConfirmObject; | ||
}; | ||
export declare type ChannelsSelectElement = { | ||
type: 'channels_select'; | ||
placeholder: PlainTextObject; | ||
actionId: string; | ||
initialChannel?: string; | ||
confirm?: ConfirmObject; | ||
}; | ||
export declare type Block = ActionsBlock | ContextBlock | DividerBlock | FileBlock | ImageBlock | InputBlock | SectionBlock; | ||
export declare type ActionsBlockElement = ButtonElement | SelectElement | OverflowElement | DatepickerElement; | ||
export declare type ActionsBlock = { | ||
type: 'action'; | ||
elements: ActionsBlockElement[]; | ||
blockId?: string; | ||
}; | ||
export declare type ContextBlockElement = TextObject | ImageElement; | ||
export declare type ContextBlock = { | ||
type: 'context'; | ||
elements: ContextBlockElement[]; | ||
blockId?: string; | ||
}; | ||
export declare type DividerBlock = { | ||
type: 'divider'; | ||
blockId?: string; | ||
}; | ||
export declare type FileBlock = { | ||
type: 'file'; | ||
externalId: string; | ||
source: string; | ||
blockId?: string; | ||
}; | ||
export declare type ImageBlock = { | ||
type: 'image'; | ||
imageUrl: string; | ||
altText: string; | ||
title?: PlainTextObject; | ||
blockId?: string; | ||
}; | ||
export declare type InputBlockElement = PlainTextInputElement | SelectElement | MultiSelectElement | DatepickerElement; | ||
export declare type InputBlock = { | ||
type: 'input'; | ||
label: PlainTextObject; | ||
element: InputBlockElement; | ||
blockId?: string; | ||
hint?: PlainTextObject; | ||
optional?: boolean; | ||
}; | ||
export declare type SectionBlock = { | ||
type: 'section'; | ||
text: TextObject; | ||
blockId?: string; | ||
fields?: TextObject[]; | ||
accessory?: BlockElement; | ||
}; | ||
export declare type SendMessageSuccessResponse = 'ok'; | ||
export declare type SlackOAuthAPIResponse = Record<string, any> & { | ||
export declare type OAuthAPIResponse = Record<string, any> & { | ||
ok: boolean; | ||
}; | ||
export declare type SlackAvailableMethod = 'api.test' | 'apps.permissions.info' | 'apps.permissions.request' | 'auth.revoke' | 'auth.test' | 'bots.info' | 'channels.archive' | 'channels.create' | 'channels.history' | 'channels.info' | 'channels.invite' | 'channels.join' | 'channels.kick' | 'channels.leave' | 'channels.list' | 'channels.mark' | 'channels.rename' | 'channels.replies' | 'channels.setPurpose' | 'channels.setTopic' | 'channels.unarchive' | 'chat.delete' | 'chat.meMessage' | 'chat.postEphemeral' | 'chat.postMessage' | 'chat.unfurl' | 'chat.update' | 'conversations.archive' | 'conversations.close' | 'conversations.create' | 'conversations.history' | 'conversations.info' | 'conversations.invite' | 'conversations.join' | 'conversations.kick' | 'conversations.leave' | 'conversations.list' | 'conversations.members' | 'conversations.open' | 'conversations.rename' | 'conversations.replies' | 'conversations.setPurpose' | 'conversations.setTopic' | 'conversations.unarchive' | 'dnd.endDnd' | 'dnd.endSnooze' | 'dnd.info' | 'dnd.setSnooze' | 'dnd.teamInfo' | 'emoji.list' | 'files.comments.add' | 'files.comments.delete' | 'files.comments.edit' | 'files.delete' | 'files.info' | 'files.list' | 'files.revokePublicURL' | 'files.sharedPublicURL' | 'files.upload' | 'groups.archive' | 'groups.create' | 'groups.createChild' | 'groups.history' | 'groups.info' | 'groups.invite' | 'groups.kick' | 'groups.leave' | 'groups.list' | 'groups.mark' | 'groups.open' | 'groups.rename' | 'groups.replies' | 'groups.setPurpose' | 'groups.setTopic' | 'groups.unarchive' | 'im.close' | 'im.history' | 'im.list' | 'im.mark' | 'im.open' | 'im.replies' | 'oauth.access' | 'oauth.token' | 'pins.add' | 'pins.list' | 'pins.remove' | 'reactions.add' | 'reactions.get' | 'reactions.list' | 'reactions.remove' | 'reminders.add' | 'reminders.complete' | 'reminders.delete' | 'reminders.info' | 'reminders.list' | 'rtm.connect' | 'rtm.start' | 'search.all' | 'search.files' | 'search.messages' | 'stars.add' | 'stars.list' | 'stars.remove' | 'team.accessLogs' | 'team.billableInfo' | 'team.info' | 'team.integrationLogs' | 'team.profile.get' | 'usergroups.create' | 'usergroups.disable' | 'usergroups.enable' | 'usergroups.list' | 'usergroups.update' | 'usergroups.users.list' | 'usergroups.users.update' | 'users.deletePhoto' | 'users.getPresence' | 'users.identity' | 'users.info' | 'users.list' | 'users.setActive' | 'users.setPhoto' | 'users.setPresence' | 'users.profile.get' | 'users.profile.set'; | ||
export interface SlackUser { | ||
export declare type AvailableMethod = 'api.test' | 'apps.permissions.info' | 'apps.permissions.request' | 'auth.revoke' | 'auth.test' | 'bots.info' | 'channels.archive' | 'channels.create' | 'channels.history' | 'channels.info' | 'channels.invite' | 'channels.join' | 'channels.kick' | 'channels.leave' | 'channels.list' | 'channels.mark' | 'channels.rename' | 'channels.replies' | 'channels.setPurpose' | 'channels.setTopic' | 'channels.unarchive' | 'chat.delete' | 'chat.meMessage' | 'chat.postEphemeral' | 'chat.postMessage' | 'chat.unfurl' | 'chat.update' | 'conversations.archive' | 'conversations.close' | 'conversations.create' | 'conversations.history' | 'conversations.info' | 'conversations.invite' | 'conversations.join' | 'conversations.kick' | 'conversations.leave' | 'conversations.list' | 'conversations.members' | 'conversations.open' | 'conversations.rename' | 'conversations.replies' | 'conversations.setPurpose' | 'conversations.setTopic' | 'conversations.unarchive' | 'dnd.endDnd' | 'dnd.endSnooze' | 'dnd.info' | 'dnd.setSnooze' | 'dnd.teamInfo' | 'emoji.list' | 'files.comments.add' | 'files.comments.delete' | 'files.comments.edit' | 'files.delete' | 'files.info' | 'files.list' | 'files.revokePublicURL' | 'files.sharedPublicURL' | 'files.upload' | 'groups.archive' | 'groups.create' | 'groups.createChild' | 'groups.history' | 'groups.info' | 'groups.invite' | 'groups.kick' | 'groups.leave' | 'groups.list' | 'groups.mark' | 'groups.open' | 'groups.rename' | 'groups.replies' | 'groups.setPurpose' | 'groups.setTopic' | 'groups.unarchive' | 'im.close' | 'im.history' | 'im.list' | 'im.mark' | 'im.open' | 'im.replies' | 'oauth.access' | 'oauth.token' | 'pins.add' | 'pins.list' | 'pins.remove' | 'reactions.add' | 'reactions.get' | 'reactions.list' | 'reactions.remove' | 'reminders.add' | 'reminders.complete' | 'reminders.delete' | 'reminders.info' | 'reminders.list' | 'rtm.connect' | 'rtm.start' | 'search.all' | 'search.files' | 'search.messages' | 'stars.add' | 'stars.list' | 'stars.remove' | 'team.accessLogs' | 'team.billableInfo' | 'team.info' | 'team.integrationLogs' | 'team.profile.get' | 'usergroups.create' | 'usergroups.disable' | 'usergroups.enable' | 'usergroups.list' | 'usergroups.update' | 'usergroups.users.list' | 'usergroups.users.update' | 'users.deletePhoto' | 'users.getPresence' | 'users.identity' | 'users.info' | 'users.list' | 'users.setActive' | 'users.setPhoto' | 'users.setPresence' | 'users.profile.get' | 'users.profile.set'; | ||
export interface User { | ||
id: string; | ||
name: string; | ||
real_name: string; | ||
realName: string; | ||
} | ||
export declare type SlackChannel = { | ||
export declare type Channel = { | ||
id: string; | ||
name: string; | ||
members?: SlackUser[]; | ||
members?: User[]; | ||
}; | ||
//# sourceMappingURL=SlackTypes.d.ts.map |
import { AxiosInstance } from 'axios'; | ||
import { SendMessageSuccessResponse, SlackAttachment } from './SlackTypes'; | ||
import { Attachment, SendMessageSuccessResponse } from './SlackTypes'; | ||
declare type URL = string; | ||
@@ -21,6 +21,6 @@ interface ClientConfig { | ||
*/ | ||
sendAttachments(attachments: SlackAttachment[]): Promise<SendMessageSuccessResponse>; | ||
sendAttachment(attachment: SlackAttachment): Promise<SendMessageSuccessResponse>; | ||
sendAttachments(attachments: Attachment[]): Promise<SendMessageSuccessResponse>; | ||
sendAttachment(attachment: Attachment): Promise<SendMessageSuccessResponse>; | ||
} | ||
export {}; | ||
//# sourceMappingURL=SlackWebhookClient.d.ts.map |
@@ -8,2 +8,3 @@ "use strict"; | ||
const lodash_omit_1 = __importDefault(require("lodash.omit")); | ||
const snakecase_keys_1 = __importDefault(require("snakecase-keys")); | ||
const url_join_1 = __importDefault(require("url-join")); | ||
@@ -54,3 +55,5 @@ const messaging_api_common_1 = require("messaging-api-common"); | ||
sendRawBody(body) { | ||
return this._axios.post('', body).then(res => res.data); | ||
return this._axios | ||
.post('', snakecase_keys_1.default(body, { deep: true })) | ||
.then(res => res.data); | ||
} | ||
@@ -57,0 +60,0 @@ sendText(text) { |
@@ -9,3 +9,3 @@ { | ||
}, | ||
"version": "1.0.0-alpha.2", | ||
"version": "1.0.0-alpha.4", | ||
"main": "dist/index.js", | ||
@@ -32,3 +32,3 @@ "types": "dist/index.d.ts", | ||
}, | ||
"gitHead": "7581219e17a1b1d9ab2f600e14f75b9714dd6fa0" | ||
"gitHead": "3ba04ffaa1a5c9c7a2aedbe21242663adec99166" | ||
} |
@@ -5,3 +5,5 @@ import querystring from 'querystring'; | ||
import axios, { AxiosInstance } from 'axios'; | ||
import camelcaseKeys from 'camelcase-keys'; | ||
import omit from 'lodash.omit'; | ||
import snakecaseKeys from 'snakecase-keys'; | ||
import urlJoin from 'url-join'; | ||
@@ -11,7 +13,8 @@ import { onRequest } from 'messaging-api-common'; | ||
import { | ||
SlackAttachment, | ||
SlackAvailableMethod, | ||
SlackChannel, | ||
SlackOAuthAPIResponse, | ||
SlackUser, | ||
Attachment, | ||
AvailableMethod, | ||
Block, | ||
Channel, | ||
OAuthAPIResponse, | ||
User, | ||
} from './SlackTypes'; | ||
@@ -25,5 +28,5 @@ | ||
type PostEphemeralOptions = CommonOptions & { | ||
as_user?: boolean; | ||
attachments?: string | SlackAttachment[]; | ||
link_names?: boolean; | ||
asUser?: boolean; | ||
attachments?: string | Attachment[]; | ||
linkNames?: boolean; | ||
parse?: 'none' | 'full'; | ||
@@ -33,7 +36,12 @@ }; | ||
type GetInfoOptions = CommonOptions & { | ||
include_locale?: boolean; | ||
includeLocale?: boolean; | ||
}; | ||
type WithCursorOptions = CommonOptions & { | ||
type UserInfoOptions = CommonOptions & { | ||
includeLocale?: boolean; | ||
}; | ||
type ConversationMembersOptions = CommonOptions & { | ||
cursor?: string; | ||
limit?: number; | ||
}; | ||
@@ -43,3 +51,3 @@ | ||
cursor?: string; | ||
exclude_archived?: boolean; | ||
excludeArchived?: boolean; | ||
limit?: number; | ||
@@ -49,2 +57,8 @@ types?: string; | ||
type UserListOptions = CommonOptions & { | ||
cursor?: string; | ||
includeLocale?: boolean; | ||
limit?: number; | ||
}; | ||
type ClientConfig = { | ||
@@ -57,12 +71,12 @@ accessToken: string; | ||
interface PostMessageOptions extends CommonOptions { | ||
as_user?: boolean; | ||
attachments?: string | SlackAttachment[]; | ||
icon_emoji?: string; | ||
icon_url?: string; | ||
link_names?: boolean; | ||
asUser?: boolean; | ||
attachments?: string | Attachment[]; | ||
iconEmoji?: string; | ||
iconUrl?: string; | ||
linkNames?: boolean; | ||
parse?: 'none' | 'full'; | ||
reply_broadcast?: boolean; | ||
thread_ts?: string; | ||
unfurl_links?: boolean; | ||
unfurl_media?: boolean; | ||
replyBroadcast?: boolean; | ||
threadTs?: string; | ||
unfurlLinks?: boolean; | ||
unfurlMedia?: boolean; | ||
username?: string; | ||
@@ -140,17 +154,23 @@ } | ||
async callMethod( | ||
method: SlackAvailableMethod, | ||
_body: Record<string, any> = {} | ||
): Promise<SlackOAuthAPIResponse> { | ||
method: AvailableMethod, | ||
inputBody: Record<string, any> = {} | ||
): Promise<OAuthAPIResponse> { | ||
try { | ||
const body = omit(_body, ['token', 'accessToken']); | ||
body.token = _body.accessToken || _body.token || this._token; | ||
const body = { | ||
...omit(inputBody, ['token', 'accessToken']), | ||
token: inputBody.accessToken || inputBody.token || this._token, | ||
}; | ||
const response = await this._axios.post( | ||
method, | ||
querystring.stringify(body) | ||
querystring.stringify(snakecaseKeys(body, { deep: true }) as any) | ||
); | ||
const { data, config, request } = response; | ||
const data = (camelcaseKeys(response.data, { | ||
deep: true, | ||
}) as any) as OAuthAPIResponse; | ||
if (!data.ok) { | ||
const { config, request } = response; | ||
throw new AxiosError(`Slack API - ${data.error}`, { | ||
@@ -170,3 +190,3 @@ config, | ||
/** | ||
* Gets information about a public channel. | ||
* Gets information about a channel. | ||
* | ||
@@ -177,4 +197,4 @@ * https://api.slack.com/methods/channels.info | ||
channelId: string, | ||
options: GetInfoOptions = {} | ||
): Promise<SlackChannel> { | ||
options?: GetInfoOptions | ||
): Promise<Channel> { | ||
return this.callMethod('channels.info', { | ||
@@ -187,14 +207,2 @@ channel: channelId, | ||
/** | ||
* Lists all public channels in a Slack team. | ||
* | ||
* https://api.slack.com/methods/channels.list | ||
* FIXME: [breaking] support cursor, exclude_archived, exclude_members, limit | ||
*/ | ||
getChannelList(options: CommonOptions = {}): Promise<SlackChannel[]> { | ||
return this.callMethod('channels.list', options).then( | ||
data => data.channels | ||
); | ||
} | ||
/** | ||
* Retrieve information about a conversation. | ||
@@ -206,4 +214,4 @@ * | ||
channelId: string, | ||
options: GetInfoOptions = {} | ||
): Promise<SlackChannel> { | ||
options?: GetInfoOptions | ||
): Promise<Channel> { | ||
return this.callMethod('conversations.info', { | ||
@@ -222,3 +230,3 @@ channel: channelId, | ||
channelId: string, | ||
options: WithCursorOptions = {} | ||
options?: ConversationMembersOptions | ||
): Promise<{ | ||
@@ -233,3 +241,3 @@ members: string[]; | ||
members: data.members, | ||
next: data.response_metadata && data.response_metadata.next_cursor, | ||
next: data.responseMetadata && data.responseMetadata.nextCursor, | ||
})); | ||
@@ -240,3 +248,3 @@ } | ||
channelId: string, | ||
options: CommonOptions = {} | ||
options?: Omit<ConversationMembersOptions, 'cursor'> | ||
): Promise<string[]> { | ||
@@ -272,5 +280,5 @@ let allMembers: string[] = []; | ||
getConversationList( | ||
options: ConversationListOptions = {} | ||
options?: ConversationListOptions | ||
): Promise<{ | ||
channels: SlackChannel[]; | ||
channels: Channel[]; | ||
next?: string; | ||
@@ -280,3 +288,3 @@ }> { | ||
channels: data.channels, | ||
next: data.response_metadata && data.response_metadata.next_cursor, | ||
next: data.responseMetadata && data.responseMetadata.nextCursor, | ||
})); | ||
@@ -286,9 +294,9 @@ } | ||
async getAllConversationList( | ||
options: ConversationListOptions = {} | ||
): Promise<SlackChannel[]> { | ||
let allChannels: SlackChannel[] = []; | ||
options?: Omit<ConversationListOptions, 'cursor'> | ||
): Promise<Channel[]> { | ||
let allChannels: Channel[] = []; | ||
let continuationCursor: string | undefined; | ||
do { | ||
const _options = continuationCursor | ||
const nextOptions = continuationCursor | ||
? { cursor: continuationCursor, ...options } | ||
@@ -300,3 +308,3 @@ : options; | ||
// eslint-disable-next-line no-await-in-loop | ||
} = await this.getConversationList(_options); | ||
} = await this.getConversationList(nextOptions); | ||
allChannels = allChannels.concat(channels); | ||
@@ -316,27 +324,28 @@ continuationCursor = next; | ||
channel: string, | ||
message: | ||
| { text?: string; attachments?: SlackAttachment[] | string } | ||
inputMessage: | ||
| { | ||
text?: string; | ||
attachments?: Attachment[] | string; | ||
blocks?: Block[] | string; | ||
} | ||
| string, | ||
options: PostMessageOptions = {} | ||
): Promise<SlackOAuthAPIResponse> { | ||
if (options.attachments && typeof options.attachments !== 'string') { | ||
// A JSON-based array of structured attachments, presented as a URL-encoded string. | ||
): Promise<OAuthAPIResponse> { | ||
const message = | ||
typeof inputMessage === 'string' ? { text: inputMessage } : inputMessage; | ||
if (message.attachments && typeof message.attachments !== 'string') { | ||
// eslint-disable-next-line no-param-reassign | ||
options.attachments = JSON.stringify(options.attachments); | ||
} else if ( | ||
typeof message === 'object' && | ||
message.attachments && | ||
typeof message.attachments !== 'string' | ||
) { | ||
message.attachments = JSON.stringify( | ||
snakecaseKeys(message.attachments, { deep: true }) | ||
); | ||
} | ||
if (message.blocks && typeof message.blocks !== 'string') { | ||
// eslint-disable-next-line no-param-reassign | ||
message.attachments = JSON.stringify(message.attachments); | ||
message.blocks = JSON.stringify( | ||
snakecaseKeys(message.blocks, { deep: true }) | ||
); | ||
} | ||
if (typeof message === 'string') { | ||
return this.callMethod('chat.postMessage', { | ||
channel, | ||
text: message, | ||
...options, | ||
}); | ||
} | ||
return this.callMethod('chat.postMessage', { | ||
@@ -357,28 +366,26 @@ channel, | ||
user: string, | ||
message: | ||
| { text?: string; attachments?: SlackAttachment[] | string } | ||
| string, | ||
inputMessage: { | ||
text?: string; | ||
attachments?: Attachment[] | string; | ||
blocks?: Block[] | string; | ||
}, | ||
options: PostEphemeralOptions = {} | ||
): Promise<SlackOAuthAPIResponse> { | ||
if (options.attachments && typeof options.attachments !== 'string') { | ||
// A JSON-based array of structured attachments, presented as a URL-encoded string. | ||
): Promise<OAuthAPIResponse> { | ||
const message = | ||
typeof inputMessage === 'string' ? { text: inputMessage } : inputMessage; | ||
if (message.attachments && typeof message.attachments !== 'string') { | ||
// eslint-disable-next-line no-param-reassign | ||
options.attachments = JSON.stringify(options.attachments); | ||
} else if ( | ||
typeof message === 'object' && | ||
message.attachments && | ||
typeof message.attachments !== 'string' | ||
) { | ||
message.attachments = JSON.stringify( | ||
snakecaseKeys(message.attachments, { deep: true }) | ||
); | ||
} | ||
if (message.blocks && typeof message.blocks !== 'string') { | ||
// eslint-disable-next-line no-param-reassign | ||
message.attachments = JSON.stringify(message.attachments); | ||
message.blocks = JSON.stringify( | ||
snakecaseKeys(message.blocks, { deep: true }) | ||
); | ||
} | ||
if (typeof message === 'string') { | ||
return this.callMethod('chat.postEphemeral', { | ||
channel, | ||
user, | ||
text: message, | ||
...options, | ||
}); | ||
} | ||
return this.callMethod('chat.postEphemeral', { | ||
@@ -397,6 +404,3 @@ channel, | ||
*/ | ||
getUserInfo( | ||
userId: string, | ||
options: GetInfoOptions = {} | ||
): Promise<SlackUser> { | ||
getUserInfo(userId: string, options?: UserInfoOptions): Promise<User> { | ||
return this.callMethod('users.info', { user: userId, ...options }).then( | ||
@@ -411,29 +415,19 @@ data => data.user | ||
* https://api.slack.com/methods/users.list | ||
* FIXME: [breaking] support include_locale, limit, presence | ||
*/ | ||
getUserList( | ||
cursorOrOptions?: string | WithCursorOptions | ||
options?: UserListOptions | ||
): Promise<{ | ||
members: SlackUser[]; | ||
members: User[]; | ||
next?: string; | ||
}> { | ||
if (typeof cursorOrOptions === 'string') { | ||
// cursorOrOptions is cursor string | ||
return this.callMethod('users.list', { cursor: cursorOrOptions }).then( | ||
data => ({ | ||
members: data.members, | ||
next: data.response_metadata && data.response_metadata.next_cursor, | ||
}) | ||
); | ||
} | ||
// cursorOrOptions is options object | ||
return this.callMethod('users.list', cursorOrOptions).then(data => ({ | ||
return this.callMethod('users.list', options).then(data => ({ | ||
members: data.members, | ||
next: data.response_metadata && data.response_metadata.next_cursor, | ||
next: data.responseMetadata && data.responseMetadata.nextCursor, | ||
})); | ||
} | ||
async getAllUserList(options: CommonOptions = {}): Promise<SlackUser[]> { | ||
let allUsers: SlackUser[] = []; | ||
async getAllUserList( | ||
options?: Omit<UserListOptions, 'cursor'> | ||
): Promise<User[]> { | ||
let allUsers: User[] = []; | ||
let continuationCursor; | ||
@@ -446,3 +440,3 @@ | ||
}: { | ||
members: SlackUser[]; | ||
members: User[]; | ||
next?: string; | ||
@@ -454,2 +448,3 @@ // eslint-disable-next-line no-await-in-loop | ||
}); | ||
allUsers = allUsers.concat(users); | ||
@@ -456,0 +451,0 @@ continuationCursor = next; |
@@ -1,10 +0,10 @@ | ||
export type SlackAttachment = { | ||
export type Attachment = { | ||
fallback: string; | ||
pretext?: string; | ||
color?: string; | ||
author_name?: string; | ||
author_link?: string; | ||
author_icon?: string; | ||
authorName?: string; | ||
authorLink?: string; | ||
authorIcon?: string; | ||
title?: string; | ||
title_link?: string; | ||
titleLink?: string; | ||
text?: string; | ||
@@ -16,8 +16,8 @@ fields?: { | ||
}[]; | ||
image_url?: string; | ||
thumb_url?: string; | ||
imageUrl?: string; | ||
thumbUrl?: string; | ||
footer?: string; | ||
footer_icon?: string; | ||
callback_id?: string; | ||
attachment_type?: string; | ||
footerIcon?: string; | ||
callbackId?: string; | ||
attachmentType?: string; | ||
actions: { | ||
@@ -33,4 +33,4 @@ name?: string; | ||
text?: string; | ||
ok_text?: string; | ||
dismiss_text?: string; | ||
okText?: string; | ||
dismissText?: string; | ||
}; | ||
@@ -41,9 +41,288 @@ }[]; | ||
// Block Kit | ||
// Composition Objects | ||
// https://api.slack.com/reference/block-kit/composition-objects | ||
export type CompositionObject = TextObject | ConfirmObject | OptionObject; | ||
export type TextObject = PlainTextObject | MrkdwnObject; | ||
export type PlainTextObject = { | ||
type: 'plain_text'; | ||
text: string; | ||
emoji?: boolean; | ||
}; | ||
export type MrkdwnObject = { | ||
type: 'mrkdwn'; | ||
text: string; | ||
verbatim?: boolean; | ||
}; | ||
// https://api.slack.com/reference/block-kit/composition-objects#confirm | ||
export type ConfirmObject = { | ||
title: PlainTextObject; | ||
text: TextObject; | ||
confirm: PlainTextObject; | ||
deny: PlainTextObject; | ||
}; | ||
// https://api.slack.com/reference/block-kit/composition-objects#option | ||
export type OptionObject = { | ||
text: PlainTextObject; | ||
value: string; | ||
url?: string; // TODO: The url attribute is only available in overflow menus | ||
}; | ||
// https://api.slack.com/reference/block-kit/composition-objects#option_group | ||
export type OptionGroupObject = { | ||
label: PlainTextObject; | ||
options: OptionObject[]; | ||
}; | ||
// Block Elements | ||
// https://api.slack.com/reference/block-kit/block-elements | ||
export type BlockElement = | ||
| ButtonElement | ||
| DatepickerElement | ||
| ImageElement | ||
| MultiSelectElement | ||
| OverflowElement | ||
| PlainTextInputElement | ||
| RadioButtonsElement | ||
| SelectElement; | ||
export type ButtonElement = { | ||
type: 'button'; | ||
text: PlainTextObject; | ||
actionId: string; | ||
url?: string; | ||
value?: string; | ||
style?: 'primary' | 'danger'; | ||
confirm?: ConfirmObject; | ||
}; | ||
export type DatepickerElement = { | ||
type: 'datepicker'; | ||
actionId: string; | ||
placeholder?: PlainTextObject; | ||
initialDate?: string; | ||
confirm?: ConfirmObject; | ||
}; | ||
export type ImageElement = { | ||
type: 'image'; | ||
imageUrl: string; | ||
altText: string; | ||
}; | ||
export type MultiSelectElement = | ||
| MultiStaticSelectElement | ||
| MultiExternalSelectElement | ||
| MultiUsersSelectElement | ||
| MultiConversationsSelectElement | ||
| MultiChannelsSelectElement; | ||
export type MultiStaticSelectElement = { | ||
type: 'multi_static_select'; | ||
placeholder: PlainTextObject; | ||
actionId: string; | ||
options: OptionObject[]; // TODO: If option_groups is specified, this field should not be. | ||
optionGroups?: OptionGroupObject[]; // TODO: If options is specified, this field should not be. | ||
initialOptions?: OptionObject[]; | ||
confirm?: ConfirmObject; | ||
}; | ||
export type MultiExternalSelectElement = { | ||
type: 'multi_external_select'; | ||
placeholder: PlainTextObject; | ||
actionId: string; | ||
minQueryLength?: number; | ||
initialOptions?: OptionObject[]; | ||
confirm?: ConfirmObject; | ||
}; | ||
export type MultiUsersSelectElement = { | ||
type: 'multi_users_select'; | ||
placeholder: PlainTextObject; | ||
actionId: string; | ||
initialUsers?: string[]; | ||
confirm?: ConfirmObject; | ||
}; | ||
export type MultiConversationsSelectElement = { | ||
type: 'multi_conversations_select'; | ||
placeholder: PlainTextObject; | ||
actionId: string; | ||
initialConversations?: string[]; | ||
confirm?: ConfirmObject; | ||
}; | ||
export type MultiChannelsSelectElement = { | ||
type: 'multi_channels_select'; | ||
placeholder: PlainTextObject; | ||
actionId: string; | ||
initialChannels?: string[]; | ||
confirm?: ConfirmObject; | ||
}; | ||
export type OverflowElement = { | ||
type: 'overflow'; | ||
actionId: string; | ||
options: OptionObject[]; | ||
confirm?: ConfirmObject; | ||
}; | ||
export type PlainTextInputElement = { | ||
type: 'plain_text_input'; | ||
actionId: string; | ||
placeholder?: PlainTextObject; | ||
initialValue: string; | ||
multiline?: boolean; | ||
minLength?: number; | ||
maxLength?: number; | ||
}; | ||
export type RadioButtonsElement = { | ||
type: 'radio_buttons'; | ||
actionId: string; | ||
options: OptionObject[]; | ||
initialOption?: OptionObject; | ||
confirm?: ConfirmObject; | ||
}; | ||
export type SelectElement = | ||
| StaticSelectElement | ||
| ExternalSelectElement | ||
| UsersSelectElement | ||
| ConversationsSelectElement | ||
| ChannelsSelectElement; | ||
export type StaticSelectElement = { | ||
type: 'static_select'; | ||
placeholder: PlainTextObject; | ||
actionId: string; | ||
options: OptionObject[]; // TODO: If option_groups is specified, this field should not be. | ||
optionGroups?: OptionGroupObject[]; // TODO: If options is specified, this field should not be. | ||
initialOption?: OptionObject; | ||
confirm?: ConfirmObject; | ||
}; | ||
export type ExternalSelectElement = { | ||
type: 'external_select'; | ||
placeholder: PlainTextObject; | ||
actionId: string; | ||
minQueryLength?: number; | ||
initialOption?: OptionObject; | ||
confirm?: ConfirmObject; | ||
}; | ||
export type UsersSelectElement = { | ||
type: 'users_select'; | ||
placeholder: PlainTextObject; | ||
actionId: string; | ||
initialUser?: string; | ||
confirm?: ConfirmObject; | ||
}; | ||
export type ConversationsSelectElement = { | ||
type: 'conversations_select'; | ||
placeholder: PlainTextObject; | ||
actionId: string; | ||
initialConversation?: string; | ||
confirm?: ConfirmObject; | ||
}; | ||
export type ChannelsSelectElement = { | ||
type: 'channels_select'; | ||
placeholder: PlainTextObject; | ||
actionId: string; | ||
initialChannel?: string; | ||
confirm?: ConfirmObject; | ||
}; | ||
// Layout Blocks | ||
// https://api.slack.com/reference/block-kit/blocks | ||
export type Block = | ||
| ActionsBlock | ||
| ContextBlock | ||
| DividerBlock | ||
| FileBlock | ||
| ImageBlock | ||
| InputBlock | ||
| SectionBlock; | ||
export type ActionsBlockElement = | ||
| ButtonElement | ||
| SelectElement | ||
| OverflowElement | ||
| DatepickerElement; | ||
export type ActionsBlock = { | ||
type: 'action'; | ||
elements: ActionsBlockElement[]; | ||
blockId?: string; | ||
}; | ||
export type ContextBlockElement = TextObject | ImageElement; | ||
export type ContextBlock = { | ||
type: 'context'; | ||
elements: ContextBlockElement[]; | ||
blockId?: string; | ||
}; | ||
export type DividerBlock = { | ||
type: 'divider'; | ||
blockId?: string; | ||
}; | ||
export type FileBlock = { | ||
type: 'file'; | ||
externalId: string; | ||
source: string; | ||
blockId?: string; | ||
}; | ||
export type ImageBlock = { | ||
type: 'image'; | ||
imageUrl: string; | ||
altText: string; | ||
title?: PlainTextObject; | ||
blockId?: string; | ||
}; | ||
export type InputBlockElement = | ||
| PlainTextInputElement | ||
| SelectElement | ||
| MultiSelectElement | ||
| DatepickerElement; | ||
export type InputBlock = { | ||
type: 'input'; | ||
label: PlainTextObject; | ||
element: InputBlockElement; | ||
blockId?: string; | ||
hint?: PlainTextObject; | ||
optional?: boolean; | ||
}; | ||
export type SectionBlock = { | ||
type: 'section'; | ||
text: TextObject; | ||
blockId?: string; | ||
fields?: TextObject[]; | ||
accessory?: BlockElement; | ||
}; | ||
export type SendMessageSuccessResponse = 'ok'; | ||
export type SlackOAuthAPIResponse = Record<string, any> & { | ||
export type OAuthAPIResponse = Record<string, any> & { | ||
ok: boolean; | ||
}; | ||
export type SlackAvailableMethod = | ||
export type AvailableMethod = | ||
| 'api.test' | ||
@@ -175,12 +454,12 @@ | 'apps.permissions.info' | ||
export interface SlackUser { | ||
export interface User { | ||
id: string; | ||
name: string; | ||
real_name: string; | ||
realName: string; | ||
} | ||
export type SlackChannel = { | ||
export type Channel = { | ||
id: string; | ||
name: string; | ||
members?: SlackUser[]; | ||
members?: User[]; | ||
}; |
import axios, { AxiosInstance } from 'axios'; | ||
import omit from 'lodash.omit'; | ||
import snakecaseKeys from 'snakecase-keys'; | ||
import urlJoin from 'url-join'; | ||
import { onRequest } from 'messaging-api-common'; | ||
import { SendMessageSuccessResponse, SlackAttachment } from './SlackTypes'; | ||
import { Attachment, SendMessageSuccessResponse } from './SlackTypes'; | ||
@@ -74,3 +75,5 @@ type URL = string; | ||
sendRawBody(body: Record<string, any>): Promise<SendMessageSuccessResponse> { | ||
return this._axios.post('', body).then(res => res.data); | ||
return this._axios | ||
.post('', snakecaseKeys(body, { deep: true })) | ||
.then(res => res.data); | ||
} | ||
@@ -89,3 +92,3 @@ | ||
sendAttachments( | ||
attachments: SlackAttachment[] | ||
attachments: Attachment[] | ||
): Promise<SendMessageSuccessResponse> { | ||
@@ -95,7 +98,5 @@ return this.sendRawBody({ attachments }); | ||
sendAttachment( | ||
attachment: SlackAttachment | ||
): Promise<SendMessageSuccessResponse> { | ||
sendAttachment(attachment: Attachment): Promise<SendMessageSuccessResponse> { | ||
return this.sendAttachments([attachment]); | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
250847
3855