dschook 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Webhook.d.ts +242 -0
- package/lib/Webhook.js +108 -0
- package/lib/attachment.d.ts +2 -0
- package/lib/attachment.js +2 -0
- package/lib/color.d.ts +6 -0
- package/lib/color.js +56 -0
- package/lib/components.d.ts +56 -0
- package/lib/components.js +47 -0
- package/package.json +30 -0
- package/readme.md +80 -0
package/lib/Webhook.d.ts
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { Attachment } from "./attachment.js";
|
|
2
|
+
import { Component } from "./components.js";
|
|
3
|
+
export declare class Webhook {
|
|
4
|
+
#private;
|
|
5
|
+
/** Declarative, functional API for composing ComponentsV2. */
|
|
6
|
+
static components: {
|
|
7
|
+
section: (components: Component[]) => {
|
|
8
|
+
type: 9;
|
|
9
|
+
components: Component[];
|
|
10
|
+
};
|
|
11
|
+
text: (content: string) => {
|
|
12
|
+
type: 10;
|
|
13
|
+
content: string;
|
|
14
|
+
};
|
|
15
|
+
thumbnail: (url: string, description?: string, spoiler?: boolean) => {
|
|
16
|
+
type: 11;
|
|
17
|
+
media: {
|
|
18
|
+
url: string;
|
|
19
|
+
};
|
|
20
|
+
description?: string;
|
|
21
|
+
spoiler?: boolean;
|
|
22
|
+
};
|
|
23
|
+
media: (url: string, description?: string, spoiler?: boolean) => {
|
|
24
|
+
media: {
|
|
25
|
+
url: string;
|
|
26
|
+
};
|
|
27
|
+
description?: string;
|
|
28
|
+
spoiler?: boolean;
|
|
29
|
+
};
|
|
30
|
+
media_gallery: (...items: {
|
|
31
|
+
media: {
|
|
32
|
+
url: string;
|
|
33
|
+
};
|
|
34
|
+
description?: string;
|
|
35
|
+
spoiler?: boolean;
|
|
36
|
+
}[]) => {
|
|
37
|
+
type: 12;
|
|
38
|
+
items: {
|
|
39
|
+
media: {
|
|
40
|
+
url: string;
|
|
41
|
+
};
|
|
42
|
+
description?: string;
|
|
43
|
+
spoiler?: boolean;
|
|
44
|
+
}[];
|
|
45
|
+
};
|
|
46
|
+
file: (url: string, spoiler?: boolean) => {
|
|
47
|
+
type: 13;
|
|
48
|
+
file: {
|
|
49
|
+
url: string;
|
|
50
|
+
};
|
|
51
|
+
spoiler?: boolean;
|
|
52
|
+
};
|
|
53
|
+
separator: (divider?: boolean, spacing?: 1 | 2) => {
|
|
54
|
+
type: 14;
|
|
55
|
+
divider?: boolean;
|
|
56
|
+
spacing?: 1 | 2;
|
|
57
|
+
};
|
|
58
|
+
container: (accent_color?: number, spoiler?: boolean, ...components: ({
|
|
59
|
+
type: 9;
|
|
60
|
+
components: Component[];
|
|
61
|
+
} | {
|
|
62
|
+
type: 10;
|
|
63
|
+
content: string;
|
|
64
|
+
} | {
|
|
65
|
+
type: 12;
|
|
66
|
+
items: {
|
|
67
|
+
media: {
|
|
68
|
+
url: string;
|
|
69
|
+
};
|
|
70
|
+
description?: string;
|
|
71
|
+
spoiler?: boolean;
|
|
72
|
+
}[];
|
|
73
|
+
} | {
|
|
74
|
+
type: 13;
|
|
75
|
+
file: {
|
|
76
|
+
url: string;
|
|
77
|
+
};
|
|
78
|
+
spoiler?: boolean;
|
|
79
|
+
} | {
|
|
80
|
+
type: 14;
|
|
81
|
+
divider?: boolean;
|
|
82
|
+
spacing?: 1 | 2;
|
|
83
|
+
})[]) => {
|
|
84
|
+
type: 17;
|
|
85
|
+
components: ({
|
|
86
|
+
type: 9;
|
|
87
|
+
components: Component[];
|
|
88
|
+
} | {
|
|
89
|
+
type: 10;
|
|
90
|
+
content: string;
|
|
91
|
+
} | {
|
|
92
|
+
type: 12;
|
|
93
|
+
items: {
|
|
94
|
+
media: {
|
|
95
|
+
url: string;
|
|
96
|
+
};
|
|
97
|
+
description?: string;
|
|
98
|
+
spoiler?: boolean;
|
|
99
|
+
}[];
|
|
100
|
+
} | {
|
|
101
|
+
type: 13;
|
|
102
|
+
file: {
|
|
103
|
+
url: string;
|
|
104
|
+
};
|
|
105
|
+
spoiler?: boolean;
|
|
106
|
+
} | {
|
|
107
|
+
type: 14;
|
|
108
|
+
divider?: boolean;
|
|
109
|
+
spacing?: 1 | 2;
|
|
110
|
+
})[];
|
|
111
|
+
accent_color?: number;
|
|
112
|
+
spoiler?: boolean;
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
/** Utility functions for Discord's integer color formatting. */
|
|
116
|
+
static colors: {
|
|
117
|
+
hexCode: (code: string) => number;
|
|
118
|
+
rgb: (r: number, g: number, b: number) => number;
|
|
119
|
+
hsl: (h: number, s: number, l: number) => number;
|
|
120
|
+
hsv: (h: number, s: number, v: number) => number;
|
|
121
|
+
};
|
|
122
|
+
/** @param url Discord webhook URL */
|
|
123
|
+
constructor(url: string);
|
|
124
|
+
/**
|
|
125
|
+
* Send the next message with a different username and/or avatar.
|
|
126
|
+
* Re-returns the Webhook instance for method chaining.
|
|
127
|
+
*/
|
|
128
|
+
as_user(username?: string, avatar_url?: string): this;
|
|
129
|
+
/**
|
|
130
|
+
* Send the next message in a new thread.
|
|
131
|
+
* Note: Will only work if the webhook is in a forum.
|
|
132
|
+
* @param thread_name name for the new created thread
|
|
133
|
+
* @param applied_tags Snowflakes for forum tags to be applied to the thread
|
|
134
|
+
*/
|
|
135
|
+
in_thread(thread_name: string, applied_tags?: string[]): this;
|
|
136
|
+
/**
|
|
137
|
+
* Enable/disable TTS for the next message.
|
|
138
|
+
* Re-returns the Webhook instance for method chaining.
|
|
139
|
+
*/
|
|
140
|
+
with_tts(tts?: boolean): this;
|
|
141
|
+
/**
|
|
142
|
+
* Send a message with one or more content types.
|
|
143
|
+
* Note that the presence of components will override any other contents.
|
|
144
|
+
*/
|
|
145
|
+
send(contents: WebhookContents): void;
|
|
146
|
+
/** Send a text message. */
|
|
147
|
+
send_text(content: string): void;
|
|
148
|
+
/** Send a message with 1-10 rich embeds. */
|
|
149
|
+
send_embed(...embeds: Embed[]): void;
|
|
150
|
+
/**
|
|
151
|
+
* Send a message with one or more ComponentsV2.
|
|
152
|
+
* Use the static `Webhook.components` for a declarative functional API for constructing components.
|
|
153
|
+
*/
|
|
154
|
+
send_components(...components: Component[]): void;
|
|
155
|
+
/** Send a poll message. */
|
|
156
|
+
send_poll(question: string, answers: (string | {
|
|
157
|
+
text: string;
|
|
158
|
+
emoji_id?: string;
|
|
159
|
+
emoji_name?: string;
|
|
160
|
+
})[], duration_hours?: number, allow_multiselect?: boolean): void;
|
|
161
|
+
}
|
|
162
|
+
export { Component };
|
|
163
|
+
export type WebhookBody = WebhookContents & {
|
|
164
|
+
username?: string;
|
|
165
|
+
avatar_url?: string;
|
|
166
|
+
tts?: boolean;
|
|
167
|
+
allowed_mentions?: {};
|
|
168
|
+
payload_json?: string;
|
|
169
|
+
attachments?: Attachment[];
|
|
170
|
+
flags?: number;
|
|
171
|
+
thread_name?: string;
|
|
172
|
+
applied_tags?: string[];
|
|
173
|
+
};
|
|
174
|
+
export type WebhookContents = Partial<{
|
|
175
|
+
content: string;
|
|
176
|
+
embeds: Embed[];
|
|
177
|
+
files: File[];
|
|
178
|
+
poll: Poll;
|
|
179
|
+
components: Component[];
|
|
180
|
+
}>;
|
|
181
|
+
export type Poll = {
|
|
182
|
+
question: {
|
|
183
|
+
text: string;
|
|
184
|
+
};
|
|
185
|
+
answers: PollAnswer[];
|
|
186
|
+
duration?: number;
|
|
187
|
+
allow_multiselect?: boolean;
|
|
188
|
+
};
|
|
189
|
+
export type PollAnswer = {
|
|
190
|
+
poll_media: {
|
|
191
|
+
text: string;
|
|
192
|
+
emoji?: Partial<{
|
|
193
|
+
name: string;
|
|
194
|
+
id: string;
|
|
195
|
+
}>;
|
|
196
|
+
};
|
|
197
|
+
};
|
|
198
|
+
export type Embed = {
|
|
199
|
+
title?: string;
|
|
200
|
+
description?: string;
|
|
201
|
+
url?: string;
|
|
202
|
+
timestamp?: string;
|
|
203
|
+
color?: number;
|
|
204
|
+
footer?: EmbedFooter;
|
|
205
|
+
image?: EmbedMedia;
|
|
206
|
+
thumbnail?: EmbedMedia;
|
|
207
|
+
video?: EmbedMedia;
|
|
208
|
+
provider?: EmbedProvider;
|
|
209
|
+
author?: EmbedAuthor;
|
|
210
|
+
fields?: EmbedField[];
|
|
211
|
+
};
|
|
212
|
+
type EmbedFooter = {
|
|
213
|
+
text: string;
|
|
214
|
+
icon_url?: string;
|
|
215
|
+
proxy_icon_url?: string;
|
|
216
|
+
};
|
|
217
|
+
type EmbedMedia = {
|
|
218
|
+
url: string;
|
|
219
|
+
proxy_url?: string;
|
|
220
|
+
height?: number;
|
|
221
|
+
width?: number;
|
|
222
|
+
content_type?: number;
|
|
223
|
+
placeholder?: string;
|
|
224
|
+
placeholder_version?: number;
|
|
225
|
+
description?: string;
|
|
226
|
+
flags?: 32;
|
|
227
|
+
};
|
|
228
|
+
type EmbedProvider = {
|
|
229
|
+
name?: string;
|
|
230
|
+
url?: string;
|
|
231
|
+
};
|
|
232
|
+
type EmbedAuthor = {
|
|
233
|
+
name: string;
|
|
234
|
+
url?: string;
|
|
235
|
+
icon_url?: string;
|
|
236
|
+
proxy_icon_url?: string;
|
|
237
|
+
};
|
|
238
|
+
type EmbedField = {
|
|
239
|
+
name: string;
|
|
240
|
+
value: string;
|
|
241
|
+
inline?: boolean;
|
|
242
|
+
};
|
package/lib/Webhook.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Webhook = void 0;
|
|
4
|
+
const color_js_1 = require("./color.js");
|
|
5
|
+
const components_js_1 = require("./components.js");
|
|
6
|
+
class Webhook {
|
|
7
|
+
/** Declarative, functional API for composing ComponentsV2. */
|
|
8
|
+
static components = components_js_1.components;
|
|
9
|
+
/** Utility functions for Discord's integer color formatting. */
|
|
10
|
+
static colors = color_js_1.colors;
|
|
11
|
+
// Internal fields and modifiers
|
|
12
|
+
#url;
|
|
13
|
+
#tts = undefined;
|
|
14
|
+
#as_user = {};
|
|
15
|
+
#in_thread = {};
|
|
16
|
+
/** @param url Discord webhook URL */
|
|
17
|
+
constructor(url) {
|
|
18
|
+
this.#url = url;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Send the next message with a different username and/or avatar.
|
|
22
|
+
* Re-returns the Webhook instance for method chaining.
|
|
23
|
+
*/
|
|
24
|
+
as_user(username, avatar_url) {
|
|
25
|
+
this.#as_user.username = username;
|
|
26
|
+
if (avatar_url)
|
|
27
|
+
this.#as_user.avatar_url = avatar_url;
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Send the next message in a new thread.
|
|
32
|
+
* Note: Will only work if the webhook is in a forum.
|
|
33
|
+
* @param thread_name name for the new created thread
|
|
34
|
+
* @param applied_tags Snowflakes for forum tags to be applied to the thread
|
|
35
|
+
*/
|
|
36
|
+
in_thread(thread_name, applied_tags) {
|
|
37
|
+
this.#in_thread.thread_name = thread_name;
|
|
38
|
+
if (applied_tags)
|
|
39
|
+
this.#in_thread.applied_tags = applied_tags;
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Enable/disable TTS for the next message.
|
|
44
|
+
* Re-returns the Webhook instance for method chaining.
|
|
45
|
+
*/
|
|
46
|
+
with_tts(tts = true) {
|
|
47
|
+
this.#tts = tts;
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Send a message with one or more content types.
|
|
52
|
+
* Note that the presence of components will override any other contents.
|
|
53
|
+
*/
|
|
54
|
+
send(contents) { this.#send_raw(contents); }
|
|
55
|
+
/** Send a text message. */
|
|
56
|
+
send_text(content) { this.#send_raw({ content }); }
|
|
57
|
+
/** Send a message with 1-10 rich embeds. */
|
|
58
|
+
send_embed(...embeds) { this.#send_raw({ embeds }); }
|
|
59
|
+
/**
|
|
60
|
+
* Send a message with one or more ComponentsV2.
|
|
61
|
+
* Use the static `Webhook.components` for a declarative functional API for constructing components.
|
|
62
|
+
*/
|
|
63
|
+
send_components(...components) { this.#send_raw({ components }); }
|
|
64
|
+
/** Send a poll message. */
|
|
65
|
+
send_poll(question, answers, duration_hours, allow_multiselect) {
|
|
66
|
+
let poll_answers = answers.map((answer, i) => {
|
|
67
|
+
if (typeof answer == "string")
|
|
68
|
+
return { poll_media: { text: answer } };
|
|
69
|
+
let ans = { poll_media: { text: answer.text } };
|
|
70
|
+
if (answer.emoji_name)
|
|
71
|
+
ans.poll_media.emoji = { name: answer.emoji_name };
|
|
72
|
+
if (answer.emoji_id)
|
|
73
|
+
ans.poll_media.emoji = { id: answer.emoji_id };
|
|
74
|
+
return ans;
|
|
75
|
+
});
|
|
76
|
+
let poll = { question: { text: question }, answers: poll_answers };
|
|
77
|
+
if (typeof duration_hours == "number")
|
|
78
|
+
poll.duration = duration_hours;
|
|
79
|
+
if (typeof allow_multiselect == "boolean")
|
|
80
|
+
poll.allow_multiselect = allow_multiselect;
|
|
81
|
+
this.#send_raw({ poll });
|
|
82
|
+
}
|
|
83
|
+
// Internal send function that sets the appropriate parameters and resets temporary modifiers after making the request.
|
|
84
|
+
#send_raw(body) {
|
|
85
|
+
let url = this.#url;
|
|
86
|
+
if (body.components) {
|
|
87
|
+
url += "?with_components=true";
|
|
88
|
+
body.flags = (body.flags ?? 0) | components_js_1.IS_COMPONENTS_V2;
|
|
89
|
+
}
|
|
90
|
+
if (typeof this.#tts == "boolean")
|
|
91
|
+
body.tts = this.#tts;
|
|
92
|
+
fetch(url, {
|
|
93
|
+
method: "POST",
|
|
94
|
+
headers: { "Content-Type": "application/json" },
|
|
95
|
+
body: JSON.stringify({
|
|
96
|
+
...this.#as_user,
|
|
97
|
+
...this.#in_thread,
|
|
98
|
+
...body
|
|
99
|
+
})
|
|
100
|
+
}).then(async (response) => {
|
|
101
|
+
if (response.status > 399)
|
|
102
|
+
console.warn("[DiscordWebhook] Webhook execution returned error code", response.status, await response.json());
|
|
103
|
+
});
|
|
104
|
+
this.#as_user = this.#in_thread = {};
|
|
105
|
+
this.#tts = undefined;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
exports.Webhook = Webhook;
|
package/lib/color.d.ts
ADDED
package/lib/color.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.colors = void 0;
|
|
4
|
+
exports.colors = {
|
|
5
|
+
hexCode: (code) => parseInt(code.startsWith('#') ? code.slice(1) : code, 16),
|
|
6
|
+
rgb: (r, g, b) => (r << 16) | (g << 8) | b,
|
|
7
|
+
hsl: (h, s, l) => {
|
|
8
|
+
const k = (n) => (n + h / 30) % 12;
|
|
9
|
+
const a = s * Math.min(l, 1 - l);
|
|
10
|
+
const f = (n) => l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
|
|
11
|
+
const r = Math.round(255 * f(0));
|
|
12
|
+
const g = Math.round(255 * f(8));
|
|
13
|
+
const b = Math.round(255 * f(4));
|
|
14
|
+
return (r << 16) | (g << 8) | b;
|
|
15
|
+
},
|
|
16
|
+
hsv: (h, s, v) => {
|
|
17
|
+
const c = v * s;
|
|
18
|
+
const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
|
|
19
|
+
const m = v - c;
|
|
20
|
+
let r = 0, g = 0, b = 0;
|
|
21
|
+
if (h < 60) {
|
|
22
|
+
r = c;
|
|
23
|
+
g = x;
|
|
24
|
+
b = 0;
|
|
25
|
+
}
|
|
26
|
+
else if (h < 120) {
|
|
27
|
+
r = x;
|
|
28
|
+
g = c;
|
|
29
|
+
b = 0;
|
|
30
|
+
}
|
|
31
|
+
else if (h < 180) {
|
|
32
|
+
r = 0;
|
|
33
|
+
g = c;
|
|
34
|
+
b = x;
|
|
35
|
+
}
|
|
36
|
+
else if (h < 240) {
|
|
37
|
+
r = 0;
|
|
38
|
+
g = x;
|
|
39
|
+
b = c;
|
|
40
|
+
}
|
|
41
|
+
else if (h < 300) {
|
|
42
|
+
r = x;
|
|
43
|
+
g = 0;
|
|
44
|
+
b = c;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
r = c;
|
|
48
|
+
g = 0;
|
|
49
|
+
b = x;
|
|
50
|
+
}
|
|
51
|
+
r = Math.round((r + m) * 255);
|
|
52
|
+
g = Math.round((g + m) * 255);
|
|
53
|
+
b = Math.round((b + m) * 255);
|
|
54
|
+
return (r << 16) | (g << 8) | b;
|
|
55
|
+
},
|
|
56
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export declare const IS_COMPONENTS_V2: number;
|
|
2
|
+
export type Component = Section | TextDisplay | Thumbnail | MediaGallery | File | Separator | Container;
|
|
3
|
+
type Section = {
|
|
4
|
+
type: 9;
|
|
5
|
+
components: Component[];
|
|
6
|
+
};
|
|
7
|
+
type TextDisplay = {
|
|
8
|
+
type: 10;
|
|
9
|
+
content: string;
|
|
10
|
+
};
|
|
11
|
+
type Thumbnail = {
|
|
12
|
+
type: 11;
|
|
13
|
+
media: UnfurledMediaItem;
|
|
14
|
+
description?: string;
|
|
15
|
+
spoiler?: boolean;
|
|
16
|
+
};
|
|
17
|
+
type MediaGallery = {
|
|
18
|
+
type: 12;
|
|
19
|
+
items: MediaGalleryItem[];
|
|
20
|
+
};
|
|
21
|
+
type File = {
|
|
22
|
+
type: 13;
|
|
23
|
+
file: UnfurledMediaItem;
|
|
24
|
+
spoiler?: boolean;
|
|
25
|
+
};
|
|
26
|
+
type Separator = {
|
|
27
|
+
type: 14;
|
|
28
|
+
divider?: boolean;
|
|
29
|
+
spacing?: 1 | 2;
|
|
30
|
+
};
|
|
31
|
+
type Container = {
|
|
32
|
+
type: 17;
|
|
33
|
+
components: ContainerChild[];
|
|
34
|
+
accent_color?: number;
|
|
35
|
+
spoiler?: boolean;
|
|
36
|
+
};
|
|
37
|
+
type UnfurledMediaItem = {
|
|
38
|
+
url: string;
|
|
39
|
+
};
|
|
40
|
+
type MediaGalleryItem = {
|
|
41
|
+
media: UnfurledMediaItem;
|
|
42
|
+
description?: string;
|
|
43
|
+
spoiler?: boolean;
|
|
44
|
+
};
|
|
45
|
+
type ContainerChild = Section | TextDisplay | MediaGallery | Separator | File;
|
|
46
|
+
export declare const components: {
|
|
47
|
+
section: (components: Component[]) => Section;
|
|
48
|
+
text: (content: string) => TextDisplay;
|
|
49
|
+
thumbnail: (url: string, description?: string, spoiler?: boolean) => Thumbnail;
|
|
50
|
+
media: (url: string, description?: string, spoiler?: boolean) => MediaGalleryItem;
|
|
51
|
+
media_gallery: (...items: MediaGalleryItem[]) => MediaGallery;
|
|
52
|
+
file: (url: string, spoiler?: boolean) => File;
|
|
53
|
+
separator: (divider?: boolean, spacing?: 1 | 2) => Separator;
|
|
54
|
+
container: (accent_color?: number, spoiler?: boolean, ...components: ContainerChild[]) => Container;
|
|
55
|
+
};
|
|
56
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.components = exports.IS_COMPONENTS_V2 = void 0;
|
|
4
|
+
exports.IS_COMPONENTS_V2 = 1 << 15;
|
|
5
|
+
exports.components = {
|
|
6
|
+
section: (components) => ({ type: 9, components }),
|
|
7
|
+
text: (content) => ({ type: 10, content }),
|
|
8
|
+
thumbnail: (url, description, spoiler) => {
|
|
9
|
+
let thumbnail = { type: 11, media: { url } };
|
|
10
|
+
if (description)
|
|
11
|
+
thumbnail.description = description;
|
|
12
|
+
if (typeof spoiler == "boolean")
|
|
13
|
+
thumbnail.spoiler = spoiler;
|
|
14
|
+
return thumbnail;
|
|
15
|
+
},
|
|
16
|
+
media: (url, description, spoiler) => {
|
|
17
|
+
let item = { media: { url } };
|
|
18
|
+
if (description)
|
|
19
|
+
item.description = description;
|
|
20
|
+
if (typeof spoiler == "boolean")
|
|
21
|
+
item.spoiler = spoiler;
|
|
22
|
+
return item;
|
|
23
|
+
},
|
|
24
|
+
media_gallery: (...items) => ({ type: 12, items }),
|
|
25
|
+
file: (url, spoiler) => {
|
|
26
|
+
let file = { type: 13, file: { url } };
|
|
27
|
+
if (typeof spoiler == "boolean")
|
|
28
|
+
file.spoiler = spoiler;
|
|
29
|
+
return file;
|
|
30
|
+
},
|
|
31
|
+
separator: (divider, spacing) => {
|
|
32
|
+
let separator = { type: 14 };
|
|
33
|
+
if (divider)
|
|
34
|
+
separator.divider = divider;
|
|
35
|
+
if (spacing)
|
|
36
|
+
separator.spacing = spacing;
|
|
37
|
+
return separator;
|
|
38
|
+
},
|
|
39
|
+
container: (accent_color, spoiler, ...components) => {
|
|
40
|
+
let container = { type: 17, components };
|
|
41
|
+
if (typeof accent_color == "number")
|
|
42
|
+
container.accent_color = accent_color;
|
|
43
|
+
if (typeof spoiler == "boolean")
|
|
44
|
+
container.spoiler = spoiler;
|
|
45
|
+
return container;
|
|
46
|
+
}
|
|
47
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dschook",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Convenience library for Discord's Webhook API",
|
|
5
|
+
"main": "lib/Webhook.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"readme.md",
|
|
8
|
+
"lib"
|
|
9
|
+
],
|
|
10
|
+
"keywords": [
|
|
11
|
+
"Discord",
|
|
12
|
+
"Webhook"
|
|
13
|
+
],
|
|
14
|
+
"author": "Alfio (p2js)",
|
|
15
|
+
"license": "ISC",
|
|
16
|
+
"devEngines": {
|
|
17
|
+
"packageManager": {
|
|
18
|
+
"name": "pnpm",
|
|
19
|
+
"version": "^11.9.0",
|
|
20
|
+
"onFail": "download"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/node": "^25.9.1",
|
|
25
|
+
"typescript": "^6.0.3"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
29
|
+
}
|
|
30
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# dschook
|
|
2
|
+
|
|
3
|
+
Simple convenience library for type-safe interaction with discord's Webhook API.
|
|
4
|
+
|
|
5
|
+
Includes a functional API for componentsV2 objects.
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
Install:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
pnpm install dschook # or npm, bun, ...
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Use:
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
import { Webhook } from "discord-webhook";
|
|
19
|
+
const hook = new Webhook("https://discord.com/api/webhooks/...");
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Currently supported
|
|
23
|
+
|
|
24
|
+
Sending regular text messages:
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
hook.send_text("Hello!");
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Sending ComponentsV2 (via the static `Webhook.components` and `Webhook.colors` APIs):
|
|
31
|
+
|
|
32
|
+
```js
|
|
33
|
+
const { container, text } = Webhook.components;
|
|
34
|
+
const { rgb } = Webhook.colors;
|
|
35
|
+
|
|
36
|
+
hook.send_components(
|
|
37
|
+
text("Hello"),
|
|
38
|
+
container(rgb(100, 0, 0), false, [
|
|
39
|
+
text("I'm stuck inside a red-lined container!")
|
|
40
|
+
])
|
|
41
|
+
);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Sending polls:
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
hook.send_poll(
|
|
48
|
+
"What's your favourite color?",
|
|
49
|
+
["Red", "Orange", "Yellow", { text: "green", emoji_name: "💚" }],
|
|
50
|
+
// Optional arguments: poll duration in hours and whether to allow selecting multiple options
|
|
51
|
+
5, true
|
|
52
|
+
);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Sending 1-10 embed objects:
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
hook.send_embed({
|
|
59
|
+
color: Webhook.colors.rgb(100, 0, 0)
|
|
60
|
+
author: { name: "github user" },
|
|
61
|
+
fields: [
|
|
62
|
+
{ name: "foo", value: "bar" }
|
|
63
|
+
]
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
*(Note: While sending embeds is supported, using message components is the recommended modern approach.)*
|
|
67
|
+
|
|
68
|
+
Sending multiple content types in one message:
|
|
69
|
+
```js
|
|
70
|
+
hook.send({
|
|
71
|
+
text: "foo",
|
|
72
|
+
embeds: [/* ... */]
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Currently unsupported
|
|
77
|
+
|
|
78
|
+
PRs welcome!
|
|
79
|
+
- Uploading attachments and/or files
|
|
80
|
+
- Editing and deleting uploaded webhooks
|