forked from slackapi/node-slack-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
IncomingWebhook.ts
154 lines (133 loc) · 4.65 KB
/
IncomingWebhook.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import axios, { AxiosResponse, AxiosError } from 'axios';
import { CodedError, errorWithCode, ErrorCode } from './errors';
import { MessageAttachment } from './methods';
import { callbackify } from './util';
/**
* A client for Slack's Incoming Webhooks
*/
export class IncomingWebhook {
/**
* The webhook URL
*/
private url: string;
/**
* Default arguments for posting messages with this webhook
*/
private defaults: IncomingWebhookDefaultArguments;
constructor(url: string, defaults: IncomingWebhookDefaultArguments = {}) {
if (url === undefined) {
throw new Error('Incoming webhook URL is required');
}
this.url = url;
this.defaults = defaults;
}
/**
* Send a notification to a conversation
* @param message the message (a simple string, or an object describing the message)
*/
public send(message: string | IncomingWebhookSendArguments): Promise<IncomingWebhookResult>;
public send(message: string | IncomingWebhookSendArguments, callback: IncomingWebhookResultCallback): void;
public send(message: string | IncomingWebhookSendArguments,
callback?: IncomingWebhookResultCallback): Promise<IncomingWebhookResult> | void {
// NOTE: no support for proxy
// NOTE: no support for TLS config
let payload: IncomingWebhookSendArguments = Object.assign({}, this.defaults);
if (typeof message === 'string') {
payload.text = message;
} else {
payload = Object.assign(payload, message);
}
const implementation = () => axios.post(this.url, payload)
.catch((error: AxiosError) => {
// Wrap errors in this packages own error types (abstract the implementation details' types)
if (error.response !== undefined) {
throw httpErrorWithOriginal(error);
} else if (error.request !== undefined) {
throw requestErrorWithOriginal(error);
} else {
throw error;
}
})
.then((response: AxiosResponse) => {
return this.buildResult(response);
});
if (callback !== undefined) {
callbackify(implementation)(callback);
return;
}
return implementation();
}
/**
* Processes an HTTP response into an IncomingWebhookResult.
*/
private buildResult(response: AxiosResponse): IncomingWebhookResult {
return {
text: response.data,
};
}
}
/*
* Exported types
*/
export interface IncomingWebhookDefaultArguments {
username?: string;
icon_emoji?: string; // SEMVER:MAJOR used to be iconEmoji
icon_url?: string; // SEMVER:MAJOR used to be iconUrl
channel?: string;
text?: string;
link_names?: boolean; // SEMVER:MAJOR used to be linkNames
}
export interface IncomingWebhookSendArguments extends IncomingWebhookDefaultArguments {
attachments?: MessageAttachment[];
unfurl_links?: boolean;
unful_media?: boolean;
}
export interface IncomingWebhookResult {
text: string;
}
export interface IncomingWebhookResultCallback {
(error: IncomingWebhookSendError, result: IncomingWebhookResult): void;
}
export type IncomingWebhookSendError = IncomingWebhookRequestError | IncomingWebhookReadError |
IncomingWebhookHTTPError;
export interface IncomingWebhookRequestError extends CodedError {
code: ErrorCode.IncomingWebhookRequestError;
original: Error;
}
// NOTE: this is no longer used, but might once again be used if a more specific means to detect it becomes evident
export interface IncomingWebhookReadError extends CodedError {
code: ErrorCode.IncomingWebhookReadError;
original: Error;
}
export interface IncomingWebhookHTTPError extends CodedError {
code: ErrorCode.IncomingWebhookHTTPError;
original: Error;
}
/*
* Helpers
*/
/**
* A factory to create IncomingWebhookRequestError objects
* @param original The original error
*/
function requestErrorWithOriginal(original: Error): IncomingWebhookRequestError {
const error = errorWithCode(
new Error(`A request error occurred: ${original.message}`),
ErrorCode.IncomingWebhookRequestError,
) as Partial<IncomingWebhookRequestError>;
error.original = original;
return (error as IncomingWebhookRequestError);
}
/**
* A factory to create IncomingWebhookHTTPError objects
* @param original The original error
*/
function httpErrorWithOriginal(original: Error): IncomingWebhookHTTPError {
const error = errorWithCode(
// `any` cast is used because the got definition file doesn't export the got.HTTPError type
new Error(`An HTTP protocol error occurred: statusCode = ${(original as any).statusCode}`),
ErrorCode.IncomingWebhookHTTPError,
) as Partial<IncomingWebhookHTTPError>;
error.original = original;
return (error as IncomingWebhookHTTPError);
}