@minesa-org/mini-interaction 0.1.6 → 0.1.7
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/README.md +0 -4
- package/dist/clients/MiniInteraction.d.ts +31 -10
- package/dist/clients/MiniInteraction.js +65 -17
- package/dist/index.d.ts +1 -1
- package/dist/utils/constants.d.ts +1 -15
- package/dist/utils/constants.js +1 -15
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
1
|
# Mini Interaction
|
|
2
2
|
|
|
3
3
|
Mini interaction, connecting your app with Discord via HTTP-interaction (Vercel support).
|
|
4
|
-
|
|
5
|
-
- Read the [Discord OAuth Linked Roles setup guide](docs/discord-oauth-setup.md)
|
|
6
|
-
for a step-by-step walkthrough that uses `mini.discordOAuthCallback()` and a
|
|
7
|
-
MongoDB connection configured via `MONGODB_URI`.
|
|
@@ -113,6 +113,23 @@ export type DiscordOAuthCallbackOptions = {
|
|
|
113
113
|
successRedirect?: string | ((context: DiscordOAuthAuthorizeContext) => string | null | undefined);
|
|
114
114
|
templates?: Partial<DiscordOAuthCallbackTemplates>;
|
|
115
115
|
};
|
|
116
|
+
/** Options accepted by {@link MiniInteraction.discordOAuthVerificationPage}. */
|
|
117
|
+
export type DiscordOAuthVerificationPageOptions = {
|
|
118
|
+
oauth?: OAuthConfig;
|
|
119
|
+
scopes?: string[];
|
|
120
|
+
/**
|
|
121
|
+
* Path to the HTML file to load. Relative paths resolve from {@link process.cwd}.
|
|
122
|
+
*
|
|
123
|
+
* @defaultValue "index.html"
|
|
124
|
+
*/
|
|
125
|
+
htmlFile?: string;
|
|
126
|
+
/**
|
|
127
|
+
* Placeholder token (with or without the `{{ }}` wrapper) that will be replaced with the generated OAuth URL.
|
|
128
|
+
*
|
|
129
|
+
* @defaultValue "OAUTH_URL"
|
|
130
|
+
*/
|
|
131
|
+
placeholder?: string;
|
|
132
|
+
};
|
|
116
133
|
/**
|
|
117
134
|
* Minimal interface describing a function capable of verifying Discord interaction signatures.
|
|
118
135
|
*/
|
|
@@ -123,7 +140,6 @@ type VerifyKeyFunction = (message: string | Uint8Array, signature: string, times
|
|
|
123
140
|
export declare class MiniInteraction {
|
|
124
141
|
readonly applicationId: string;
|
|
125
142
|
readonly publicKey: string;
|
|
126
|
-
private readonly baseUrl;
|
|
127
143
|
private readonly fetchImpl;
|
|
128
144
|
private readonly verifyKeyImpl;
|
|
129
145
|
private readonly commandsDirectory;
|
|
@@ -213,25 +229,26 @@ export declare class MiniInteraction {
|
|
|
213
229
|
*/
|
|
214
230
|
handleRequest(request: MiniInteractionRequest): Promise<MiniInteractionHandlerResult>;
|
|
215
231
|
/**
|
|
216
|
-
* Creates a Node.js style request handler
|
|
232
|
+
* Creates a Node.js style request handler compatible with Express, Next.js API routes,
|
|
233
|
+
* Vercel serverless functions, and any runtime that expects a `(req, res)` listener.
|
|
217
234
|
*/
|
|
218
235
|
createNodeHandler(): MiniInteractionNodeHandler;
|
|
219
236
|
/**
|
|
220
|
-
*
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
*
|
|
237
|
+
* Generates a lightweight verification handler that serves an HTML page with an embedded OAuth link.
|
|
238
|
+
*
|
|
239
|
+
* This is primarily used when Discord asks for a verification URL while setting up Linked Roles.
|
|
240
|
+
* Provide an HTML file that contains the `{{OAUTH_URL}}` placeholder (or a custom placeholder defined in options)
|
|
241
|
+
* and this helper will replace the token with a freshly generated OAuth link on every request.
|
|
225
242
|
*/
|
|
226
|
-
|
|
243
|
+
discordOAuthVerificationPage(options?: DiscordOAuthVerificationPageOptions): MiniInteractionNodeHandler;
|
|
227
244
|
/**
|
|
228
245
|
* Loads an HTML file and returns a success template that replaces useful placeholders.
|
|
229
246
|
*
|
|
230
247
|
* The following placeholders are available in the HTML file:
|
|
231
248
|
* - `{{username}}`, `{{discriminator}}`, `{{user_id}}`, `{{user_tag}}`
|
|
232
249
|
* - `{{access_token}}`, `{{refresh_token}}`, `{{token_type}}`, `{{scope}}`, `{{expires_at}}`
|
|
233
|
-
|
|
234
|
-
|
|
250
|
+
* - `{{state}}`
|
|
251
|
+
*/
|
|
235
252
|
connectedOAuthPage(filePath: string): DiscordOAuthCallbackTemplates["success"];
|
|
236
253
|
/**
|
|
237
254
|
* Loads an HTML file and returns an error template that can be reused for all failure cases.
|
|
@@ -249,6 +266,10 @@ export declare class MiniInteraction {
|
|
|
249
266
|
* Replaces placeholder tokens in a template with escaped HTML values.
|
|
250
267
|
*/
|
|
251
268
|
private renderHtmlTemplate;
|
|
269
|
+
/**
|
|
270
|
+
* Normalizes placeholder tokens to the bare key the HTML renderer expects.
|
|
271
|
+
*/
|
|
272
|
+
private normalizeTemplateKey;
|
|
252
273
|
/**
|
|
253
274
|
* Creates a minimal Discord OAuth callback handler that renders helpful HTML responses.
|
|
254
275
|
*
|
|
@@ -9,7 +9,7 @@ import { createCommandInteraction } from "../utils/CommandInteractionOptions.js"
|
|
|
9
9
|
import { createMessageComponentInteraction, } from "../utils/MessageComponentInteraction.js";
|
|
10
10
|
import { createModalSubmitInteraction, } from "../utils/ModalSubmitInteraction.js";
|
|
11
11
|
import { createUserContextMenuInteraction, createMessageContextMenuInteraction, } from "../utils/ContextMenuInteraction.js";
|
|
12
|
-
import { getOAuthTokens, getDiscordUser, } from "../oauth/DiscordOAuth.js";
|
|
12
|
+
import { generateOAuthUrl, getOAuthTokens, getDiscordUser, } from "../oauth/DiscordOAuth.js";
|
|
13
13
|
/** File extensions that are treated as loadable modules when auto-loading. */
|
|
14
14
|
const SUPPORTED_MODULE_EXTENSIONS = new Set([
|
|
15
15
|
".js",
|
|
@@ -25,7 +25,6 @@ const SUPPORTED_MODULE_EXTENSIONS = new Set([
|
|
|
25
25
|
export class MiniInteraction {
|
|
26
26
|
applicationId;
|
|
27
27
|
publicKey;
|
|
28
|
-
baseUrl;
|
|
29
28
|
fetchImpl;
|
|
30
29
|
verifyKeyImpl;
|
|
31
30
|
commandsDirectory;
|
|
@@ -54,7 +53,6 @@ export class MiniInteraction {
|
|
|
54
53
|
}
|
|
55
54
|
this.applicationId = applicationId;
|
|
56
55
|
this.publicKey = publicKey;
|
|
57
|
-
this.baseUrl = DISCORD_BASE_URL;
|
|
58
56
|
this.fetchImpl = fetchImpl;
|
|
59
57
|
this.verifyKeyImpl = verifyKeyImplementation ?? verifyKey;
|
|
60
58
|
this.commandsDirectory =
|
|
@@ -271,7 +269,7 @@ export class MiniInteraction {
|
|
|
271
269
|
if (!Array.isArray(resolvedCommands) || resolvedCommands.length === 0) {
|
|
272
270
|
throw new Error("[MiniInteraction] commands must be a non-empty array payload");
|
|
273
271
|
}
|
|
274
|
-
const url = `${
|
|
272
|
+
const url = `${DISCORD_BASE_URL}/applications/${this.applicationId}/commands`;
|
|
275
273
|
const response = await this.fetchImpl(url, {
|
|
276
274
|
method: "PUT",
|
|
277
275
|
headers: {
|
|
@@ -299,7 +297,7 @@ export class MiniInteraction {
|
|
|
299
297
|
if (!Array.isArray(metadata) || metadata.length === 0) {
|
|
300
298
|
throw new Error("[MiniInteraction] metadata must be a non-empty array payload");
|
|
301
299
|
}
|
|
302
|
-
const url = `${
|
|
300
|
+
const url = `${DISCORD_BASE_URL}/applications/${this.applicationId}/role-connections/metadata`;
|
|
303
301
|
const response = await this.fetchImpl(url, {
|
|
304
302
|
method: "PUT",
|
|
305
303
|
headers: {
|
|
@@ -372,7 +370,8 @@ export class MiniInteraction {
|
|
|
372
370
|
};
|
|
373
371
|
}
|
|
374
372
|
/**
|
|
375
|
-
* Creates a Node.js style request handler
|
|
373
|
+
* Creates a Node.js style request handler compatible with Express, Next.js API routes,
|
|
374
|
+
* Vercel serverless functions, and any runtime that expects a `(req, res)` listener.
|
|
376
375
|
*/
|
|
377
376
|
createNodeHandler() {
|
|
378
377
|
return (request, response) => {
|
|
@@ -426,16 +425,35 @@ export class MiniInteraction {
|
|
|
426
425
|
};
|
|
427
426
|
}
|
|
428
427
|
/**
|
|
429
|
-
*
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
/**
|
|
435
|
-
* Convenience alias for {@link createNodeHandler} tailored to Vercel serverless functions.
|
|
428
|
+
* Generates a lightweight verification handler that serves an HTML page with an embedded OAuth link.
|
|
429
|
+
*
|
|
430
|
+
* This is primarily used when Discord asks for a verification URL while setting up Linked Roles.
|
|
431
|
+
* Provide an HTML file that contains the `{{OAUTH_URL}}` placeholder (or a custom placeholder defined in options)
|
|
432
|
+
* and this helper will replace the token with a freshly generated OAuth link on every request.
|
|
436
433
|
*/
|
|
437
|
-
|
|
438
|
-
|
|
434
|
+
discordOAuthVerificationPage(options = {}) {
|
|
435
|
+
const scopes = options.scopes ?? ["identify", "role_connections.write"];
|
|
436
|
+
const htmlFile = options.htmlFile ?? "index.html";
|
|
437
|
+
const placeholderKey = this.normalizeTemplateKey(options.placeholder ?? "OAUTH_URL");
|
|
438
|
+
const template = this.loadHtmlTemplate(htmlFile);
|
|
439
|
+
const oauthConfig = resolveOAuthConfig(options.oauth);
|
|
440
|
+
return (_request, response) => {
|
|
441
|
+
try {
|
|
442
|
+
const { url, state } = generateOAuthUrl(oauthConfig, scopes);
|
|
443
|
+
const html = this.renderHtmlTemplate(template, {
|
|
444
|
+
OAUTH_URL: url,
|
|
445
|
+
OAUTH_STATE: state,
|
|
446
|
+
...(placeholderKey !== "OAUTH_URL"
|
|
447
|
+
? { [placeholderKey]: url }
|
|
448
|
+
: {}),
|
|
449
|
+
});
|
|
450
|
+
sendHtml(response, html);
|
|
451
|
+
}
|
|
452
|
+
catch (error) {
|
|
453
|
+
console.error("[MiniInteraction] Failed to render OAuth verification page:", error);
|
|
454
|
+
sendHtml(response, DEFAULT_VERIFICATION_ERROR_HTML, 500);
|
|
455
|
+
}
|
|
456
|
+
};
|
|
439
457
|
}
|
|
440
458
|
/**
|
|
441
459
|
* Loads an HTML file and returns a success template that replaces useful placeholders.
|
|
@@ -443,8 +461,8 @@ export class MiniInteraction {
|
|
|
443
461
|
* The following placeholders are available in the HTML file:
|
|
444
462
|
* - `{{username}}`, `{{discriminator}}`, `{{user_id}}`, `{{user_tag}}`
|
|
445
463
|
* - `{{access_token}}`, `{{refresh_token}}`, `{{token_type}}`, `{{scope}}`, `{{expires_at}}`
|
|
446
|
-
|
|
447
|
-
|
|
464
|
+
* - `{{state}}`
|
|
465
|
+
*/
|
|
448
466
|
connectedOAuthPage(filePath) {
|
|
449
467
|
const template = this.loadHtmlTemplate(filePath);
|
|
450
468
|
return ({ user, tokens, state }) => {
|
|
@@ -511,6 +529,20 @@ export class MiniInteraction {
|
|
|
511
529
|
return escapeHtml(String(value));
|
|
512
530
|
});
|
|
513
531
|
}
|
|
532
|
+
/**
|
|
533
|
+
* Normalizes placeholder tokens to the bare key the HTML renderer expects.
|
|
534
|
+
*/
|
|
535
|
+
normalizeTemplateKey(token) {
|
|
536
|
+
if (!token) {
|
|
537
|
+
return "OAUTH_URL";
|
|
538
|
+
}
|
|
539
|
+
const trimmed = token.trim();
|
|
540
|
+
const match = trimmed.match(/^\{\{\s*(\w+)\s*\}\}$/);
|
|
541
|
+
if (match) {
|
|
542
|
+
return match[1];
|
|
543
|
+
}
|
|
544
|
+
return trimmed || "OAUTH_URL";
|
|
545
|
+
}
|
|
514
546
|
/**
|
|
515
547
|
* Creates a minimal Discord OAuth callback handler that renders helpful HTML responses.
|
|
516
548
|
*
|
|
@@ -1224,6 +1256,22 @@ const DEFAULT_DISCORD_OAUTH_TEMPLATES = {
|
|
|
1224
1256
|
</body>
|
|
1225
1257
|
</html>`,
|
|
1226
1258
|
};
|
|
1259
|
+
const DEFAULT_VERIFICATION_ERROR_HTML = `<!DOCTYPE html>
|
|
1260
|
+
<html>
|
|
1261
|
+
<head>
|
|
1262
|
+
<meta charset="utf-8" />
|
|
1263
|
+
<title>Server Error</title>
|
|
1264
|
+
<style>
|
|
1265
|
+
body { font-family: Arial, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; text-align: center; }
|
|
1266
|
+
.error { color: #d32f2f; background: #ffebee; padding: 15px; border-radius: 5px; display: inline-block; }
|
|
1267
|
+
</style>
|
|
1268
|
+
</head>
|
|
1269
|
+
<body>
|
|
1270
|
+
<div class="error">
|
|
1271
|
+
<p>We were unable to load the Discord verification page. Please try again later.</p>
|
|
1272
|
+
</div>
|
|
1273
|
+
</body>
|
|
1274
|
+
</html>`;
|
|
1227
1275
|
function sendHtml(response, body, statusCode = 200) {
|
|
1228
1276
|
if (response.headersSent || response.writableEnded) {
|
|
1229
1277
|
return;
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export type { AttachmentOptionBuilder, ChannelOptionBuilder, MentionableOptionBu
|
|
|
7
7
|
export { CommandInteractionOptionResolver, createCommandInteraction, } from "./utils/CommandInteractionOptions.js";
|
|
8
8
|
export type { CommandInteraction, MentionableOption, ResolvedUserOption, } from "./utils/CommandInteractionOptions.js";
|
|
9
9
|
export type { UserContextMenuInteraction, MessageContextMenuInteraction, } from "./utils/ContextMenuInteraction.js";
|
|
10
|
-
export type { MiniInteractionFetchHandler, MiniInteractionNodeHandler, MiniInteractionHandlerResult, MiniInteractionRequest, MiniInteractionOptions, DiscordOAuthAuthorizeContext, DiscordOAuthCallbackOptions, DiscordOAuthCallbackTemplates, DiscordOAuthErrorTemplateContext, DiscordOAuthServerErrorTemplateContext, DiscordOAuthStateTemplateContext, DiscordOAuthSuccessTemplateContext, } from "./clients/MiniInteraction.js";
|
|
10
|
+
export type { MiniInteractionFetchHandler, MiniInteractionNodeHandler, MiniInteractionHandlerResult, MiniInteractionRequest, MiniInteractionOptions, DiscordOAuthAuthorizeContext, DiscordOAuthCallbackOptions, DiscordOAuthCallbackTemplates, DiscordOAuthErrorTemplateContext, DiscordOAuthServerErrorTemplateContext, DiscordOAuthStateTemplateContext, DiscordOAuthSuccessTemplateContext, DiscordOAuthVerificationPageOptions, } from "./clients/MiniInteraction.js";
|
|
11
11
|
export type { MiniInteractionCommand, SlashCommandHandler, UserCommandHandler, MessageCommandHandler, CommandHandler, } from "./types/Commands.js";
|
|
12
12
|
export type { MiniInteractionComponent, MiniInteractionButtonHandler, MiniInteractionStringSelectHandler, MiniInteractionRoleSelectHandler, MiniInteractionUserSelectHandler, MiniInteractionChannelSelectHandler, MiniInteractionMentionableSelectHandler, MiniInteractionComponentHandler, MiniInteractionModal, MiniInteractionModalHandler, MiniInteractionHandler, } from "./clients/MiniInteraction.js";
|
|
13
13
|
export type { MessageComponentInteraction, ButtonInteraction, StringSelectInteraction, RoleSelectInteraction, UserSelectInteraction, ChannelSelectInteraction, MentionableSelectInteraction, ResolvedUserOption as ComponentResolvedUserOption, ResolvedMentionableOption as ComponentResolvedMentionableOption, } from "./utils/MessageComponentInteraction.js";
|
|
@@ -1,16 +1,2 @@
|
|
|
1
|
-
import "dotenv/config";
|
|
2
|
-
/** Discord application's public key used for request signature verification. */
|
|
3
|
-
declare const DISCORD_APP_PUBLIC_KEY: string;
|
|
4
|
-
/** Discord application identifier used for REST requests. */
|
|
5
|
-
declare const DISCORD_APPLICATION_ID: string;
|
|
6
|
-
/** Bot token used when registering commands against Discord's API. */
|
|
7
|
-
declare const DISCORD_BOT_TOKEN: string;
|
|
8
|
-
/** Guild identifier used for guild-scoped command registration. */
|
|
9
|
-
declare const DISCORD_GUILD_ID: string;
|
|
10
|
-
/** Whether commands should be registered globally instead of per guild. */
|
|
11
|
-
declare const DISCORD_GLOBAL: boolean;
|
|
12
|
-
/** Local development port for the example interaction server. */
|
|
13
|
-
declare const DISCORD_APP_PORT: string;
|
|
14
1
|
/** Discord REST API base URL used for all network requests. */
|
|
15
|
-
declare const DISCORD_BASE_URL
|
|
16
|
-
export { DISCORD_APPLICATION_ID, DISCORD_APP_PORT, DISCORD_APP_PUBLIC_KEY, DISCORD_BASE_URL, DISCORD_BOT_TOKEN, DISCORD_GLOBAL, DISCORD_GUILD_ID, };
|
|
2
|
+
export declare const DISCORD_BASE_URL: "https://discord.com/api/v10";
|
package/dist/utils/constants.js
CHANGED
|
@@ -1,16 +1,2 @@
|
|
|
1
|
-
import "dotenv/config";
|
|
2
|
-
/** Discord application's public key used for request signature verification. */
|
|
3
|
-
const DISCORD_APP_PUBLIC_KEY = process.env.DISCORD_APP_PUBLIC_KEY;
|
|
4
|
-
/** Discord application identifier used for REST requests. */
|
|
5
|
-
const DISCORD_APPLICATION_ID = process.env.DISCORD_APPLICATION_ID;
|
|
6
|
-
/** Bot token used when registering commands against Discord's API. */
|
|
7
|
-
const DISCORD_BOT_TOKEN = process.env.DISCORD_BOT_TOKEN;
|
|
8
|
-
/** Guild identifier used for guild-scoped command registration. */
|
|
9
|
-
const DISCORD_GUILD_ID = process.env.DISCORD_GUILD_ID;
|
|
10
|
-
/** Whether commands should be registered globally instead of per guild. */
|
|
11
|
-
const DISCORD_GLOBAL = (process.env.DISCORD_GLOBAL ?? "false").toLowerCase() === "true";
|
|
12
|
-
/** Local development port for the example interaction server. */
|
|
13
|
-
const DISCORD_APP_PORT = process.env.DISCORD_PORT;
|
|
14
1
|
/** Discord REST API base URL used for all network requests. */
|
|
15
|
-
const DISCORD_BASE_URL = "https://discord.com/api/v10";
|
|
16
|
-
export { DISCORD_APPLICATION_ID, DISCORD_APP_PORT, DISCORD_APP_PUBLIC_KEY, DISCORD_BASE_URL, DISCORD_BOT_TOKEN, DISCORD_GLOBAL, DISCORD_GUILD_ID, };
|
|
2
|
+
export const DISCORD_BASE_URL = "https://discord.com/api/v10";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@minesa-org/mini-interaction",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "Mini interaction, connecting your app with Discord via HTTP-interaction (Vercel support).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -41,8 +41,7 @@
|
|
|
41
41
|
"homepage": "https://github.com/minesa-org/mini-interaction#readme",
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"discord-api-types": "^0.38.32",
|
|
44
|
-
"discord-interactions": "^4.4.0"
|
|
45
|
-
"dotenv": "^17.2.3"
|
|
44
|
+
"discord-interactions": "^4.4.0"
|
|
46
45
|
},
|
|
47
46
|
"devDependencies": {
|
|
48
47
|
"@types/node": "^24.10.0",
|