@dereekb/nestjs 13.1.0 → 13.2.1
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/discord/index.cjs.default.js +1 -0
- package/discord/index.cjs.js +491 -0
- package/discord/index.cjs.mjs +2 -0
- package/discord/index.d.ts +1 -0
- package/discord/index.esm.js +475 -0
- package/discord/package.json +24 -0
- package/discord/src/index.d.ts +1 -0
- package/discord/src/lib/discord.api.d.ts +55 -0
- package/discord/src/lib/discord.api.page.d.ts +89 -0
- package/discord/src/lib/discord.config.d.ts +36 -0
- package/discord/src/lib/discord.module.d.ts +13 -0
- package/discord/src/lib/discord.type.d.ts +22 -0
- package/discord/src/lib/discord.util.d.ts +25 -0
- package/discord/src/lib/index.d.ts +7 -0
- package/discord/src/lib/webhook/index.d.ts +6 -0
- package/discord/src/lib/webhook/webhook.discord.config.d.ts +18 -0
- package/discord/src/lib/webhook/webhook.discord.controller.d.ts +8 -0
- package/discord/src/lib/webhook/webhook.discord.d.ts +58 -0
- package/discord/src/lib/webhook/webhook.discord.module.d.ts +14 -0
- package/discord/src/lib/webhook/webhook.discord.service.d.ts +18 -0
- package/discord/src/lib/webhook/webhook.discord.verify.d.ts +45 -0
- package/mailgun/package.json +6 -6
- package/openai/package.json +6 -6
- package/package.json +9 -2
- package/stripe/package.json +6 -6
- package/typeform/package.json +6 -6
- package/vapiai/package.json +6 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
exports._default = require('./index.cjs.js').default;
|
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var util = require('@dereekb/util');
|
|
4
|
+
var discord_js = require('discord.js');
|
|
5
|
+
var nestjs = require('@dereekb/nestjs');
|
|
6
|
+
var common = require('@nestjs/common');
|
|
7
|
+
var crypto = require('crypto');
|
|
8
|
+
var config = require('@nestjs/config');
|
|
9
|
+
var fetch = require('@dereekb/util/fetch');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Casts an untyped Discord interaction to a typed one.
|
|
13
|
+
*
|
|
14
|
+
* @param interaction - the raw interaction to cast
|
|
15
|
+
*/
|
|
16
|
+
function discordWebhookInteraction(interaction) {
|
|
17
|
+
return interaction;
|
|
18
|
+
}
|
|
19
|
+
const discordInteractionHandlerFactory = util.handlerFactory((x) => x.type);
|
|
20
|
+
const discordInteractionHandlerConfigurerFactory = util.handlerConfigurerFactory({
|
|
21
|
+
configurerForAccessor: (accessor) => {
|
|
22
|
+
// eslint-disable-next-line
|
|
23
|
+
const fnWithKey = util.handlerMappedSetFunctionFactory(accessor, discordWebhookInteraction);
|
|
24
|
+
const configurer = {
|
|
25
|
+
...accessor,
|
|
26
|
+
handleApplicationCommand: fnWithKey(discord_js.InteractionType.ApplicationCommand),
|
|
27
|
+
handleMessageComponent: fnWithKey(discord_js.InteractionType.MessageComponent),
|
|
28
|
+
handleModalSubmit: fnWithKey(discord_js.InteractionType.ModalSubmit),
|
|
29
|
+
handleAutocomplete: fnWithKey(discord_js.InteractionType.ApplicationCommandAutocomplete)
|
|
30
|
+
};
|
|
31
|
+
return configurer;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Default environment variable for the Discord application public key.
|
|
37
|
+
*/
|
|
38
|
+
const DISCORD_PUBLIC_KEY_ENV_VAR = 'DISCORD_PUBLIC_KEY';
|
|
39
|
+
/**
|
|
40
|
+
* Configuration for the DiscordWebhookService.
|
|
41
|
+
*/
|
|
42
|
+
class DiscordWebhookServiceConfig {
|
|
43
|
+
discordWebhook;
|
|
44
|
+
static assertValidConfig(config) {
|
|
45
|
+
if (!config.discordWebhook.publicKey) {
|
|
46
|
+
throw new Error('No Discord public key specified.');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/******************************************************************************
|
|
52
|
+
Copyright (c) Microsoft Corporation.
|
|
53
|
+
|
|
54
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
55
|
+
purpose with or without fee is hereby granted.
|
|
56
|
+
|
|
57
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
58
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
59
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
60
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
61
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
62
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
63
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
64
|
+
***************************************************************************** */
|
|
65
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
function __decorate(decorators, target, key, desc) {
|
|
69
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
70
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
71
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
72
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function __param(paramIndex, decorator) {
|
|
76
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
80
|
+
var e = new Error(message);
|
|
81
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Creates a verifier for Discord interaction webhook requests.
|
|
86
|
+
*
|
|
87
|
+
* Discord signs interaction webhook requests with Ed25519. The signed message is
|
|
88
|
+
* the concatenation of the x-signature-timestamp header and the raw request body.
|
|
89
|
+
* The signature is provided in the x-signature-ed25519 header as a hex string.
|
|
90
|
+
*
|
|
91
|
+
* Uses Node.js built-in crypto with JWK key import — no external dependencies required.
|
|
92
|
+
*
|
|
93
|
+
* @param config - verification config containing the application's public key
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* const verifier = discordWebhookEventVerifier({ publicKey: 'your-hex-public-key' });
|
|
98
|
+
* const result = await verifier(req, rawBody);
|
|
99
|
+
*
|
|
100
|
+
* if (result.valid) {
|
|
101
|
+
* // result.body contains the parsed interaction
|
|
102
|
+
* }
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
function discordWebhookEventVerifier(config) {
|
|
106
|
+
const { publicKey: publicKeyHex } = config;
|
|
107
|
+
// Import the raw 32-byte Ed25519 public key via JWK format.
|
|
108
|
+
const publicKey = crypto.createPublicKey({
|
|
109
|
+
key: {
|
|
110
|
+
kty: 'OKP',
|
|
111
|
+
crv: 'Ed25519',
|
|
112
|
+
x: Buffer.from(publicKeyHex, 'hex').toString('base64url')
|
|
113
|
+
},
|
|
114
|
+
format: 'jwk'
|
|
115
|
+
});
|
|
116
|
+
return async (request, rawBody) => {
|
|
117
|
+
const signature = request.headers['x-signature-ed25519'];
|
|
118
|
+
const timestamp = request.headers['x-signature-timestamp'];
|
|
119
|
+
let result;
|
|
120
|
+
if (!signature || !timestamp) {
|
|
121
|
+
result = { valid: false };
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
const message = Buffer.concat([Buffer.from(timestamp), rawBody]);
|
|
125
|
+
const signatureBuffer = Buffer.from(signature, 'hex');
|
|
126
|
+
let valid = false;
|
|
127
|
+
try {
|
|
128
|
+
valid = crypto.verify(null, message, publicKey, signatureBuffer);
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
valid = false;
|
|
132
|
+
}
|
|
133
|
+
if (valid) {
|
|
134
|
+
const body = JSON.parse(rawBody.toString('utf-8'));
|
|
135
|
+
result = { valid: true, body };
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
result = { valid: false };
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return result;
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Service that handles Discord interaction webhook events.
|
|
147
|
+
*
|
|
148
|
+
* Verifies incoming webhook signatures and dispatches interactions to registered handlers.
|
|
149
|
+
*/
|
|
150
|
+
exports.DiscordWebhookService = class DiscordWebhookService {
|
|
151
|
+
logger = new common.Logger('DiscordWebhookService');
|
|
152
|
+
_verifier;
|
|
153
|
+
handler = discordInteractionHandlerFactory();
|
|
154
|
+
configure = discordInteractionHandlerConfigurerFactory(this.handler);
|
|
155
|
+
constructor(discordWebhookServiceConfig) {
|
|
156
|
+
this._verifier = discordWebhookEventVerifier({
|
|
157
|
+
publicKey: discordWebhookServiceConfig.discordWebhook.publicKey
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
async updateForWebhook(req, rawBody) {
|
|
161
|
+
const result = await this._verifier(req, rawBody);
|
|
162
|
+
if (!result.valid) {
|
|
163
|
+
this.logger.warn('Received invalid Discord interaction event.', req);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
await this.updateForDiscordInteraction(result.body);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
async updateForDiscordInteraction(interaction) {
|
|
170
|
+
const result = await this.handler(interaction);
|
|
171
|
+
if (!result) {
|
|
172
|
+
this.logger.warn('Received unexpected/unhandled Discord interaction.', interaction);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
exports.DiscordWebhookService = __decorate([
|
|
177
|
+
common.Injectable(),
|
|
178
|
+
__param(0, common.Inject(DiscordWebhookServiceConfig))
|
|
179
|
+
], exports.DiscordWebhookService);
|
|
180
|
+
|
|
181
|
+
exports.DiscordWebhookController = class DiscordWebhookController {
|
|
182
|
+
_discordWebhookService;
|
|
183
|
+
constructor(discordWebhookService) {
|
|
184
|
+
this._discordWebhookService = discordWebhookService;
|
|
185
|
+
}
|
|
186
|
+
async handleDiscordWebhook(req, rawBody) {
|
|
187
|
+
await this._discordWebhookService.updateForWebhook(req, rawBody);
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
__decorate([
|
|
191
|
+
common.Post(),
|
|
192
|
+
__param(0, common.Req()),
|
|
193
|
+
__param(1, nestjs.RawBody())
|
|
194
|
+
], exports.DiscordWebhookController.prototype, "handleDiscordWebhook", null);
|
|
195
|
+
exports.DiscordWebhookController = __decorate([
|
|
196
|
+
common.Controller('/webhook/discord'),
|
|
197
|
+
__param(0, common.Inject(exports.DiscordWebhookService))
|
|
198
|
+
], exports.DiscordWebhookController);
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Factory that creates a DiscordWebhookServiceConfig from environment variables.
|
|
202
|
+
*/
|
|
203
|
+
function discordWebhookServiceConfigFactory(configService) {
|
|
204
|
+
const config = {
|
|
205
|
+
discordWebhook: {
|
|
206
|
+
publicKey: configService.get(DISCORD_PUBLIC_KEY_ENV_VAR)
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
DiscordWebhookServiceConfig.assertValidConfig(config);
|
|
210
|
+
return config;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* NestJS module that provides Discord interaction webhook handling.
|
|
214
|
+
*
|
|
215
|
+
* Standalone — does not depend on DiscordModule (no bot token needed).
|
|
216
|
+
* Reads the application public key from the DISCORD_PUBLIC_KEY environment variable.
|
|
217
|
+
*/
|
|
218
|
+
exports.DiscordWebhookModule = class DiscordWebhookModule {
|
|
219
|
+
};
|
|
220
|
+
exports.DiscordWebhookModule = __decorate([
|
|
221
|
+
common.Module({
|
|
222
|
+
imports: [config.ConfigModule],
|
|
223
|
+
controllers: [exports.DiscordWebhookController],
|
|
224
|
+
providers: [
|
|
225
|
+
{
|
|
226
|
+
provide: DiscordWebhookServiceConfig,
|
|
227
|
+
inject: [config.ConfigService],
|
|
228
|
+
useFactory: discordWebhookServiceConfigFactory
|
|
229
|
+
},
|
|
230
|
+
exports.DiscordWebhookService
|
|
231
|
+
],
|
|
232
|
+
exports: [exports.DiscordWebhookService]
|
|
233
|
+
})
|
|
234
|
+
], exports.DiscordWebhookModule);
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Default environment variable for the Discord bot token.
|
|
238
|
+
*/
|
|
239
|
+
const DISCORD_BOT_TOKEN_ENV_VAR = 'DISCORD_BOT_TOKEN';
|
|
240
|
+
/**
|
|
241
|
+
* Default gateway intents for a bot that reads guild messages.
|
|
242
|
+
*
|
|
243
|
+
* Includes Guilds, GuildMessages, and MessageContent.
|
|
244
|
+
* Note: MessageContent is a privileged intent and must be enabled in the Discord Developer Portal.
|
|
245
|
+
*/
|
|
246
|
+
const DISCORD_DEFAULT_INTENTS = [discord_js.GatewayIntentBits.Guilds, discord_js.GatewayIntentBits.GuildMessages, discord_js.GatewayIntentBits.MessageContent];
|
|
247
|
+
/**
|
|
248
|
+
* Configuration for the DiscordApi service.
|
|
249
|
+
*/
|
|
250
|
+
class DiscordServiceConfig {
|
|
251
|
+
discord;
|
|
252
|
+
static assertValidConfig(config) {
|
|
253
|
+
if (!config.discord.botToken) {
|
|
254
|
+
throw new Error('No Discord bot token specified.');
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Injectable service that wraps the discord.js Client for bot operations.
|
|
261
|
+
*
|
|
262
|
+
* Automatically logs in on module init and destroys the client on module destroy
|
|
263
|
+
* when autoLogin is enabled (default).
|
|
264
|
+
*/
|
|
265
|
+
exports.DiscordApi = class DiscordApi {
|
|
266
|
+
config;
|
|
267
|
+
logger = new common.Logger('DiscordApi');
|
|
268
|
+
/**
|
|
269
|
+
* The underlying discord.js Client instance.
|
|
270
|
+
*/
|
|
271
|
+
client;
|
|
272
|
+
constructor(config) {
|
|
273
|
+
this.config = config;
|
|
274
|
+
const { clientOptions } = config.discord;
|
|
275
|
+
this.client = new discord_js.Client({
|
|
276
|
+
intents: DISCORD_DEFAULT_INTENTS,
|
|
277
|
+
...clientOptions
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
async onModuleInit() {
|
|
281
|
+
const { autoLogin = true, botToken } = this.config.discord;
|
|
282
|
+
let result;
|
|
283
|
+
if (autoLogin) {
|
|
284
|
+
result = this.client
|
|
285
|
+
.login(botToken)
|
|
286
|
+
.then(() => { })
|
|
287
|
+
.catch((e) => {
|
|
288
|
+
this.logger.error('Failed to log in to Discord', e);
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
result = Promise.resolve();
|
|
293
|
+
}
|
|
294
|
+
return result;
|
|
295
|
+
}
|
|
296
|
+
async onModuleDestroy() {
|
|
297
|
+
return this.client.destroy();
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Sends a text message to a Discord channel.
|
|
301
|
+
*
|
|
302
|
+
* @param channelId - target channel's snowflake ID
|
|
303
|
+
* @param content - message text to send
|
|
304
|
+
*
|
|
305
|
+
* @throws {Error} When the channel is not found or is not a text channel.
|
|
306
|
+
*
|
|
307
|
+
* @example
|
|
308
|
+
* ```ts
|
|
309
|
+
* const message = await discordApi.sendMessage('123456789', 'Hello from the bot!');
|
|
310
|
+
* ```
|
|
311
|
+
*/
|
|
312
|
+
async sendMessage(channelId, content) {
|
|
313
|
+
const channel = await this.client.channels.fetch(channelId);
|
|
314
|
+
if (!channel || !(channel instanceof discord_js.TextChannel)) {
|
|
315
|
+
throw new Error(`Channel ${channelId} not found or is not a text channel.`);
|
|
316
|
+
}
|
|
317
|
+
return channel.send(content);
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Registers a handler for the MessageCreate event (incoming messages).
|
|
321
|
+
*
|
|
322
|
+
* Returns an unsubscribe function to remove the handler.
|
|
323
|
+
*
|
|
324
|
+
* @param handler - callback invoked for each incoming message
|
|
325
|
+
*
|
|
326
|
+
* @example
|
|
327
|
+
* ```ts
|
|
328
|
+
* const unsubscribe = discordApi.onMessage((message) => {
|
|
329
|
+
* if (!message.author.bot) {
|
|
330
|
+
* console.log(`${message.author.tag}: ${message.content}`);
|
|
331
|
+
* }
|
|
332
|
+
* });
|
|
333
|
+
*
|
|
334
|
+
* // Later, to stop listening:
|
|
335
|
+
* unsubscribe();
|
|
336
|
+
* ```
|
|
337
|
+
*/
|
|
338
|
+
onMessage(handler) {
|
|
339
|
+
this.client.on(discord_js.Events.MessageCreate, handler);
|
|
340
|
+
return () => this.client.off(discord_js.Events.MessageCreate, handler);
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
exports.DiscordApi = __decorate([
|
|
344
|
+
common.Injectable(),
|
|
345
|
+
__param(0, common.Inject(DiscordServiceConfig))
|
|
346
|
+
], exports.DiscordApi);
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Factory that creates a DiscordServiceConfig from environment variables.
|
|
350
|
+
*/
|
|
351
|
+
function discordServiceConfigFactory(configService) {
|
|
352
|
+
const config = {
|
|
353
|
+
discord: {
|
|
354
|
+
botToken: configService.get(DISCORD_BOT_TOKEN_ENV_VAR),
|
|
355
|
+
autoLogin: true
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
DiscordServiceConfig.assertValidConfig(config);
|
|
359
|
+
return config;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* NestJS module that provides the DiscordApi service.
|
|
363
|
+
*
|
|
364
|
+
* Reads the bot token from the DISCORD_BOT_TOKEN environment variable.
|
|
365
|
+
*/
|
|
366
|
+
exports.DiscordModule = class DiscordModule {
|
|
367
|
+
};
|
|
368
|
+
exports.DiscordModule = __decorate([
|
|
369
|
+
common.Module({
|
|
370
|
+
imports: [config.ConfigModule],
|
|
371
|
+
providers: [
|
|
372
|
+
{
|
|
373
|
+
provide: DiscordServiceConfig,
|
|
374
|
+
inject: [config.ConfigService],
|
|
375
|
+
useFactory: discordServiceConfigFactory
|
|
376
|
+
},
|
|
377
|
+
exports.DiscordApi
|
|
378
|
+
],
|
|
379
|
+
exports: [exports.DiscordApi]
|
|
380
|
+
})
|
|
381
|
+
], exports.DiscordModule);
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Default number of messages per page when fetching Discord channel messages.
|
|
385
|
+
*/
|
|
386
|
+
const DISCORD_DEFAULT_MESSAGES_PER_PAGE = 100;
|
|
387
|
+
/**
|
|
388
|
+
* Creates a page factory that wraps a Discord message fetch function with automatic cursor-based pagination.
|
|
389
|
+
*
|
|
390
|
+
* Discord paginates via `before`/`after` snowflake IDs. This factory automatically reads the last
|
|
391
|
+
* message's ID from each response and sets it as the `before` cursor for the next request.
|
|
392
|
+
* When the number of returned messages is less than the requested limit, pagination stops.
|
|
393
|
+
*
|
|
394
|
+
* @param fetch - The Discord fetch function to paginate over
|
|
395
|
+
* @param config - Optional config for reading message IDs
|
|
396
|
+
* @param defaults - Optional default configuration for the page factory
|
|
397
|
+
* @returns A page factory that produces iterable page fetchers
|
|
398
|
+
*
|
|
399
|
+
* @example
|
|
400
|
+
* ```typescript
|
|
401
|
+
* const pageFactory = discordFetchMessagePageFactory(fetchChannelMessages);
|
|
402
|
+
*
|
|
403
|
+
* const fetchPage = pageFactory({ limit: 50 });
|
|
404
|
+
* const firstPage = await fetchPage.fetchNext();
|
|
405
|
+
*
|
|
406
|
+
* if (firstPage.hasNext) {
|
|
407
|
+
* const secondPage = await firstPage.fetchNext();
|
|
408
|
+
* }
|
|
409
|
+
* ```
|
|
410
|
+
*/
|
|
411
|
+
function discordFetchMessagePageFactory(fetch$1, config, defaults) {
|
|
412
|
+
const readMessageId = config?.readMessageId ?? ((message) => message.id);
|
|
413
|
+
return fetch.fetchPageFactory({
|
|
414
|
+
...defaults,
|
|
415
|
+
fetch: fetch$1,
|
|
416
|
+
readFetchPageResultInfo(result) {
|
|
417
|
+
const count = result.data.length;
|
|
418
|
+
const lastMessage = util.lastValue(result.data);
|
|
419
|
+
const nextCursor = lastMessage ? readMessageId(lastMessage) : undefined;
|
|
420
|
+
return {
|
|
421
|
+
hasNext: count > 0,
|
|
422
|
+
nextPageCursor: nextCursor
|
|
423
|
+
};
|
|
424
|
+
},
|
|
425
|
+
buildInputForNextPage(pageResult, input, options) {
|
|
426
|
+
const nextCursor = pageResult.nextPageCursor;
|
|
427
|
+
const effectiveLimit = options.maxItemsPerPage ?? input.limit ?? DISCORD_DEFAULT_MESSAGES_PER_PAGE;
|
|
428
|
+
const resultCount = pageResult.result?.data.length ?? 0;
|
|
429
|
+
// Discord signals no more results when fewer items than the limit are returned
|
|
430
|
+
if (!nextCursor || resultCount < effectiveLimit) {
|
|
431
|
+
return undefined;
|
|
432
|
+
}
|
|
433
|
+
return {
|
|
434
|
+
...input,
|
|
435
|
+
before: nextCursor,
|
|
436
|
+
after: undefined,
|
|
437
|
+
around: undefined,
|
|
438
|
+
limit: effectiveLimit
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Returns default ClientOptions for a bot that reads guild messages.
|
|
446
|
+
*
|
|
447
|
+
* Includes Guilds, GuildMessages, and MessageContent intents.
|
|
448
|
+
*
|
|
449
|
+
* @example
|
|
450
|
+
* ```ts
|
|
451
|
+
* const options = discordDefaultClientOptions();
|
|
452
|
+
* // options.intents === [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent]
|
|
453
|
+
* ```
|
|
454
|
+
*/
|
|
455
|
+
function discordDefaultClientOptions() {
|
|
456
|
+
return {
|
|
457
|
+
intents: DISCORD_DEFAULT_INTENTS
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Returns ClientOptions with additional intents merged with the defaults.
|
|
462
|
+
*
|
|
463
|
+
* @param additionalIntents - extra intents to include beyond the defaults
|
|
464
|
+
*
|
|
465
|
+
* @example
|
|
466
|
+
* ```ts
|
|
467
|
+
* const options = discordClientOptionsWithIntents([GatewayIntentBits.DirectMessages]);
|
|
468
|
+
* // options.intents includes Guilds, GuildMessages, MessageContent, and DirectMessages
|
|
469
|
+
* ```
|
|
470
|
+
*/
|
|
471
|
+
function discordClientOptionsWithIntents(additionalIntents) {
|
|
472
|
+
return {
|
|
473
|
+
intents: [...DISCORD_DEFAULT_INTENTS, ...additionalIntents]
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
exports.DISCORD_BOT_TOKEN_ENV_VAR = DISCORD_BOT_TOKEN_ENV_VAR;
|
|
478
|
+
exports.DISCORD_DEFAULT_INTENTS = DISCORD_DEFAULT_INTENTS;
|
|
479
|
+
exports.DISCORD_DEFAULT_MESSAGES_PER_PAGE = DISCORD_DEFAULT_MESSAGES_PER_PAGE;
|
|
480
|
+
exports.DISCORD_PUBLIC_KEY_ENV_VAR = DISCORD_PUBLIC_KEY_ENV_VAR;
|
|
481
|
+
exports.DiscordServiceConfig = DiscordServiceConfig;
|
|
482
|
+
exports.DiscordWebhookServiceConfig = DiscordWebhookServiceConfig;
|
|
483
|
+
exports.discordClientOptionsWithIntents = discordClientOptionsWithIntents;
|
|
484
|
+
exports.discordDefaultClientOptions = discordDefaultClientOptions;
|
|
485
|
+
exports.discordFetchMessagePageFactory = discordFetchMessagePageFactory;
|
|
486
|
+
exports.discordInteractionHandlerConfigurerFactory = discordInteractionHandlerConfigurerFactory;
|
|
487
|
+
exports.discordInteractionHandlerFactory = discordInteractionHandlerFactory;
|
|
488
|
+
exports.discordServiceConfigFactory = discordServiceConfigFactory;
|
|
489
|
+
exports.discordWebhookEventVerifier = discordWebhookEventVerifier;
|
|
490
|
+
exports.discordWebhookInteraction = discordWebhookInteraction;
|
|
491
|
+
exports.discordWebhookServiceConfigFactory = discordWebhookServiceConfigFactory;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./src/index";
|