@hogsend/plugin-discord 0.24.0 → 0.25.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/package.json +2 -2
- package/src/actions/broadcast.ts +40 -0
- package/src/actions/dm.ts +60 -0
- package/src/actions/index.ts +38 -0
- package/src/actions/mention.ts +85 -0
- package/src/actions/rest.ts +66 -0
- package/src/actions/send-channel-message.ts +39 -0
- package/src/gateway/index.ts +1 -0
- package/src/gateway/runtime.ts +46 -0
- package/src/gateway/worker.ts +10 -1
- package/src/index.ts +16 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hogsend/plugin-discord",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"access": "public"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@hogsend/engine": "^0.
|
|
26
|
+
"@hogsend/engine": "^0.25.0"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"discord.js": ">=14.0.0"
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type DefinedConnectorAction,
|
|
3
|
+
defineConnectorAction,
|
|
4
|
+
} from "@hogsend/engine";
|
|
5
|
+
import { DISCORD_PROVIDER_ID } from "../constants.js";
|
|
6
|
+
import { botFetch, type SendMessageResult } from "./rest.js";
|
|
7
|
+
|
|
8
|
+
export interface BroadcastToChannelArgs {
|
|
9
|
+
/** Target channel snowflake. */
|
|
10
|
+
channelId: string;
|
|
11
|
+
/** Message content (Discord markdown). */
|
|
12
|
+
content: string;
|
|
13
|
+
/**
|
|
14
|
+
* Whether `@everyone` / `@here` in the content actually ping. Default `true`
|
|
15
|
+
* (a broadcast is announcement-shaped); set `false` to ping roles only.
|
|
16
|
+
*/
|
|
17
|
+
pingEveryone?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Broadcast to a channel, ALLOWING @everyone/@here + role pings to fire. */
|
|
21
|
+
export const broadcastToChannel: DefinedConnectorAction<
|
|
22
|
+
BroadcastToChannelArgs,
|
|
23
|
+
SendMessageResult
|
|
24
|
+
> = defineConnectorAction({
|
|
25
|
+
connectorId: DISCORD_PROVIDER_ID,
|
|
26
|
+
name: "broadcastToChannel",
|
|
27
|
+
description:
|
|
28
|
+
"Broadcast a message to a Discord channel, allowing @everyone/@role pings.",
|
|
29
|
+
async run(args) {
|
|
30
|
+
const allowed =
|
|
31
|
+
args.pingEveryone === false
|
|
32
|
+
? { parse: ["roles"] }
|
|
33
|
+
: { parse: ["everyone", "roles"] };
|
|
34
|
+
const res = (await botFetch(`/channels/${args.channelId}/messages`, {
|
|
35
|
+
method: "POST",
|
|
36
|
+
body: { content: args.content, allowed_mentions: allowed },
|
|
37
|
+
})) as { id?: string } | null;
|
|
38
|
+
return { messageId: res?.id ?? null };
|
|
39
|
+
},
|
|
40
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type DefinedConnectorAction,
|
|
3
|
+
defineConnectorAction,
|
|
4
|
+
} from "@hogsend/engine";
|
|
5
|
+
import { DISCORD_PROVIDER_ID } from "../constants.js";
|
|
6
|
+
import { botFetch, resolveDiscordId } from "./rest.js";
|
|
7
|
+
|
|
8
|
+
export interface DmMemberArgs {
|
|
9
|
+
/** Recipient: email, external id, or raw discord snowflake. */
|
|
10
|
+
member: string;
|
|
11
|
+
/** Message content (Discord markdown). */
|
|
12
|
+
content: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface DmResult {
|
|
16
|
+
messageId: string | null;
|
|
17
|
+
/** False when unresolved OR the user's DMs are closed (a soft, non-throwing failure). */
|
|
18
|
+
delivered: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Direct-message a member (resolved contact → discord_id). A closed-DM / no
|
|
23
|
+
* shared-guild rejection is a SOFT failure (`delivered: false`, logged) rather
|
|
24
|
+
* than a throw — a single un-DMable recipient must not fail a journey.
|
|
25
|
+
*/
|
|
26
|
+
export const dmMember: DefinedConnectorAction<DmMemberArgs, DmResult> =
|
|
27
|
+
defineConnectorAction({
|
|
28
|
+
connectorId: DISCORD_PROVIDER_ID,
|
|
29
|
+
name: "dmMember",
|
|
30
|
+
description:
|
|
31
|
+
"Send a direct message to a member (resolved contact → discord_id).",
|
|
32
|
+
async run(args, ctx) {
|
|
33
|
+
const id = await resolveDiscordId(ctx, args.member);
|
|
34
|
+
if (!id) {
|
|
35
|
+
ctx.logger.warn("discord dmMember: recipient unresolved", {
|
|
36
|
+
member: args.member,
|
|
37
|
+
});
|
|
38
|
+
return { messageId: null, delivered: false };
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
// Open (or fetch) the 1:1 DM channel, then post into it.
|
|
42
|
+
const dm = (await botFetch("/users/@me/channels", {
|
|
43
|
+
method: "POST",
|
|
44
|
+
body: { recipient_id: id },
|
|
45
|
+
})) as { id?: string } | null;
|
|
46
|
+
if (!dm?.id) return { messageId: null, delivered: false };
|
|
47
|
+
const res = (await botFetch(`/channels/${dm.id}/messages`, {
|
|
48
|
+
method: "POST",
|
|
49
|
+
body: { content: args.content },
|
|
50
|
+
})) as { id?: string } | null;
|
|
51
|
+
return { messageId: res?.id ?? null, delivered: Boolean(res?.id) };
|
|
52
|
+
} catch (err) {
|
|
53
|
+
// Closed DMs / no shared guild → Discord 403. Soft-fail.
|
|
54
|
+
ctx.logger.warn("discord dmMember: delivery failed", {
|
|
55
|
+
error: err instanceof Error ? err.message : String(err),
|
|
56
|
+
});
|
|
57
|
+
return { messageId: null, delivered: false };
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { DefinedConnectorAction } from "@hogsend/engine";
|
|
2
|
+
import { broadcastToChannel } from "./broadcast.js";
|
|
3
|
+
import { dmMember } from "./dm.js";
|
|
4
|
+
import { mentionMembers, mentionRole } from "./mention.js";
|
|
5
|
+
import { sendChannelMessage } from "./send-channel-message.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Every Discord OUTBOUND action — pass to
|
|
9
|
+
* `createHogsendClient({ connectorActions: discordActions })`, then invoke from a
|
|
10
|
+
* journey via the standalone `sendConnectorAction({ connectorId: "discord", … })`.
|
|
11
|
+
* All are bot-REST (token only), socket-free, and independent of the inbound
|
|
12
|
+
* gateway runtime.
|
|
13
|
+
*/
|
|
14
|
+
export const discordActions: DefinedConnectorAction[] = [
|
|
15
|
+
sendChannelMessage,
|
|
16
|
+
broadcastToChannel,
|
|
17
|
+
mentionMembers,
|
|
18
|
+
mentionRole,
|
|
19
|
+
dmMember,
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
export {
|
|
23
|
+
type BroadcastToChannelArgs,
|
|
24
|
+
broadcastToChannel,
|
|
25
|
+
} from "./broadcast.js";
|
|
26
|
+
export { type DmMemberArgs, type DmResult, dmMember } from "./dm.js";
|
|
27
|
+
export {
|
|
28
|
+
type MentionMembersArgs,
|
|
29
|
+
type MentionMembersResult,
|
|
30
|
+
type MentionRoleArgs,
|
|
31
|
+
mentionMembers,
|
|
32
|
+
mentionRole,
|
|
33
|
+
} from "./mention.js";
|
|
34
|
+
export type { SendMessageResult } from "./rest.js";
|
|
35
|
+
export {
|
|
36
|
+
type SendChannelMessageArgs,
|
|
37
|
+
sendChannelMessage,
|
|
38
|
+
} from "./send-channel-message.js";
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type DefinedConnectorAction,
|
|
3
|
+
defineConnectorAction,
|
|
4
|
+
} from "@hogsend/engine";
|
|
5
|
+
import { DISCORD_PROVIDER_ID } from "../constants.js";
|
|
6
|
+
import { botFetch, resolveDiscordId, type SendMessageResult } from "./rest.js";
|
|
7
|
+
|
|
8
|
+
export interface MentionMembersArgs {
|
|
9
|
+
/** Target channel snowflake. */
|
|
10
|
+
channelId: string;
|
|
11
|
+
/** Recipients: emails, external ids, or raw discord snowflakes. */
|
|
12
|
+
members: string[];
|
|
13
|
+
/** Optional message appended after the mentions. */
|
|
14
|
+
content?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface MentionMembersResult extends SendMessageResult {
|
|
18
|
+
/** The discord ids that resolved + were mentioned. */
|
|
19
|
+
mentioned: string[];
|
|
20
|
+
/** Refs that could not be resolved to a discord id (skipped). */
|
|
21
|
+
unresolved: string[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Post a message @-mentioning specific members (resolved contact → discord_id). */
|
|
25
|
+
export const mentionMembers: DefinedConnectorAction<
|
|
26
|
+
MentionMembersArgs,
|
|
27
|
+
MentionMembersResult
|
|
28
|
+
> = defineConnectorAction({
|
|
29
|
+
connectorId: DISCORD_PROVIDER_ID,
|
|
30
|
+
name: "mentionMembers",
|
|
31
|
+
description:
|
|
32
|
+
"Post a message @-mentioning specific members (resolved contact → discord_id).",
|
|
33
|
+
async run(args, ctx) {
|
|
34
|
+
const mentioned: string[] = [];
|
|
35
|
+
const unresolved: string[] = [];
|
|
36
|
+
for (const ref of args.members) {
|
|
37
|
+
const id = await resolveDiscordId(ctx, ref);
|
|
38
|
+
if (id) mentioned.push(id);
|
|
39
|
+
else unresolved.push(ref);
|
|
40
|
+
}
|
|
41
|
+
if (mentioned.length === 0) {
|
|
42
|
+
ctx.logger.warn("discord mentionMembers: no members resolved", {
|
|
43
|
+
unresolved,
|
|
44
|
+
});
|
|
45
|
+
return { messageId: null, mentioned, unresolved };
|
|
46
|
+
}
|
|
47
|
+
const mentions = mentioned.map((id) => `<@${id}>`).join(" ");
|
|
48
|
+
const content = args.content ? `${mentions} ${args.content}` : mentions;
|
|
49
|
+
const res = (await botFetch(`/channels/${args.channelId}/messages`, {
|
|
50
|
+
method: "POST",
|
|
51
|
+
// Only the explicitly-resolved users may ping — never widen to everyone.
|
|
52
|
+
body: { content, allowed_mentions: { users: mentioned } },
|
|
53
|
+
})) as { id?: string } | null;
|
|
54
|
+
return { messageId: res?.id ?? null, mentioned, unresolved };
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
export interface MentionRoleArgs {
|
|
59
|
+
/** Target channel snowflake. */
|
|
60
|
+
channelId: string;
|
|
61
|
+
/** Role snowflake to mention (a group of members). */
|
|
62
|
+
roleId: string;
|
|
63
|
+
/** Optional message appended after the mention. */
|
|
64
|
+
content?: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Post a message @-mentioning a role (a group of members). */
|
|
68
|
+
export const mentionRole: DefinedConnectorAction<
|
|
69
|
+
MentionRoleArgs,
|
|
70
|
+
SendMessageResult
|
|
71
|
+
> = defineConnectorAction({
|
|
72
|
+
connectorId: DISCORD_PROVIDER_ID,
|
|
73
|
+
name: "mentionRole",
|
|
74
|
+
description: "Post a message @-mentioning a role (group of members).",
|
|
75
|
+
async run(args) {
|
|
76
|
+
const content = args.content
|
|
77
|
+
? `<@&${args.roleId}> ${args.content}`
|
|
78
|
+
: `<@&${args.roleId}>`;
|
|
79
|
+
const res = (await botFetch(`/channels/${args.channelId}/messages`, {
|
|
80
|
+
method: "POST",
|
|
81
|
+
body: { content, allowed_mentions: { roles: [args.roleId] } },
|
|
82
|
+
})) as { id?: string } | null;
|
|
83
|
+
return { messageId: res?.id ?? null };
|
|
84
|
+
},
|
|
85
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { ConnectorActionCtx } from "@hogsend/engine";
|
|
2
|
+
import { DISCORD_API_BASE } from "../constants.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Shared bot-REST plumbing for the Discord OUTBOUND actions. Every action is a
|
|
6
|
+
* pure HTTPS call to discord.com needing only the bot token — NO `discord.js`,
|
|
7
|
+
* NO gateway socket — so actions run on any replica regardless of the inbound
|
|
8
|
+
* runtime's state.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** The bot token, read from the platform's own env. Throws when unset. */
|
|
12
|
+
export function getBotToken(): string {
|
|
13
|
+
const token = process.env.DISCORD_BOT_TOKEN;
|
|
14
|
+
if (!token) {
|
|
15
|
+
throw new Error(
|
|
16
|
+
"DISCORD_BOT_TOKEN is required for Discord outbound actions",
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
return token;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* One bot-REST call. Throws on a non-2xx (STATUS ONLY in the message — never the
|
|
24
|
+
* response body, which can echo the request carrying the `Bot` token). Returns
|
|
25
|
+
* the parsed JSON, or null for 204 / empty bodies.
|
|
26
|
+
*/
|
|
27
|
+
export async function botFetch(
|
|
28
|
+
path: string,
|
|
29
|
+
init: { method: string; body?: unknown },
|
|
30
|
+
): Promise<unknown> {
|
|
31
|
+
const res = await fetch(`${DISCORD_API_BASE}${path}`, {
|
|
32
|
+
method: init.method,
|
|
33
|
+
headers: {
|
|
34
|
+
"Content-Type": "application/json",
|
|
35
|
+
Authorization: `Bot ${getBotToken()}`,
|
|
36
|
+
},
|
|
37
|
+
...(init.body !== undefined ? { body: JSON.stringify(init.body) } : {}),
|
|
38
|
+
});
|
|
39
|
+
if (!res.ok) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`discord bot-REST ${init.method} ${path} failed (${res.status})`,
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
if (res.status === 204) return null;
|
|
45
|
+
return res.json().catch(() => null);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Resolve a recipient ref to a Discord snowflake: the contact store first
|
|
50
|
+
* (email / external id / discord id), then an all-digit ref treated as a raw
|
|
51
|
+
* snowflake. Null when unresolvable.
|
|
52
|
+
*/
|
|
53
|
+
export async function resolveDiscordId(
|
|
54
|
+
ctx: ConnectorActionCtx,
|
|
55
|
+
ref: string,
|
|
56
|
+
): Promise<string | null> {
|
|
57
|
+
const contact = await ctx.resolveContact(ref);
|
|
58
|
+
if (contact?.discordId) return contact.discordId;
|
|
59
|
+
if (/^\d{5,}$/.test(ref)) return ref;
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** The shared result shape for a channel post. */
|
|
64
|
+
export interface SendMessageResult {
|
|
65
|
+
messageId: string | null;
|
|
66
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type DefinedConnectorAction,
|
|
3
|
+
defineConnectorAction,
|
|
4
|
+
} from "@hogsend/engine";
|
|
5
|
+
import { DISCORD_PROVIDER_ID } from "../constants.js";
|
|
6
|
+
import { botFetch, type SendMessageResult } from "./rest.js";
|
|
7
|
+
|
|
8
|
+
export interface SendChannelMessageArgs {
|
|
9
|
+
/** Target channel snowflake. */
|
|
10
|
+
channelId: string;
|
|
11
|
+
/** Message content (Discord markdown). */
|
|
12
|
+
content: string;
|
|
13
|
+
/**
|
|
14
|
+
* Discord `allowed_mentions` object. Defaults to `{ parse: [] }` — a message
|
|
15
|
+
* that merely CONTAINS `<@id>` text should not ping by surprise; opt in
|
|
16
|
+
* explicitly (or use `mentionMembers` / `broadcastToChannel`).
|
|
17
|
+
*/
|
|
18
|
+
allowedMentions?: unknown;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Post a plain message to a Discord channel (no pings by default). */
|
|
22
|
+
export const sendChannelMessage: DefinedConnectorAction<
|
|
23
|
+
SendChannelMessageArgs,
|
|
24
|
+
SendMessageResult
|
|
25
|
+
> = defineConnectorAction({
|
|
26
|
+
connectorId: DISCORD_PROVIDER_ID,
|
|
27
|
+
name: "sendChannelMessage",
|
|
28
|
+
description: "Post a message to a Discord channel (bot-REST).",
|
|
29
|
+
async run(args) {
|
|
30
|
+
const res = (await botFetch(`/channels/${args.channelId}/messages`, {
|
|
31
|
+
method: "POST",
|
|
32
|
+
body: {
|
|
33
|
+
content: args.content,
|
|
34
|
+
allowed_mentions: args.allowedMentions ?? { parse: [] },
|
|
35
|
+
},
|
|
36
|
+
})) as { id?: string } | null;
|
|
37
|
+
return { messageId: res?.id ?? null };
|
|
38
|
+
},
|
|
39
|
+
});
|
package/src/gateway/index.ts
CHANGED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ConnectorRuntime, ConnectorRuntimeDeps } from "@hogsend/engine";
|
|
2
|
+
import { createDiscordGatewayWorker } from "./worker.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The Discord {@link ConnectorRuntime} factory — the plugin's contribution to
|
|
6
|
+
* the engine's connector-runtime seam. The consumer passes it to
|
|
7
|
+
* `createWorker({ connectorRuntimes: { discord: createDiscordRuntime } })`; the
|
|
8
|
+
* engine elects a single leader replica and calls this with an in-process
|
|
9
|
+
* `ingest` sink, so the gateway socket forwards dispatches straight into
|
|
10
|
+
* `transform`→`ingestEvent` — no HTTP ingress hop, no `CONNECTOR_INGRESS_SECRET`.
|
|
11
|
+
*
|
|
12
|
+
* Returns `null` when `DISCORD_BOT_TOKEN` is unset — the engine then skips
|
|
13
|
+
* Discord cleanly (no lease held, dashboard stays truthfully Offline). The bot
|
|
14
|
+
* token is the platform's OWN env, read here (not in the engine) so the engine
|
|
15
|
+
* stays platform-neutral; `discord.js` is still imported only inside the worker's
|
|
16
|
+
* `start()` (dynamic import), so enabling the runtime without the optional peer
|
|
17
|
+
* fails loudly at start rather than at module load.
|
|
18
|
+
*/
|
|
19
|
+
export function createDiscordRuntime(
|
|
20
|
+
deps: ConnectorRuntimeDeps,
|
|
21
|
+
): ConnectorRuntime | null {
|
|
22
|
+
const botToken = process.env.DISCORD_BOT_TOKEN;
|
|
23
|
+
if (!botToken) {
|
|
24
|
+
deps.logger.info(
|
|
25
|
+
"Discord runtime: DISCORD_BOT_TOKEN not set; gateway will not start",
|
|
26
|
+
);
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const worker = createDiscordGatewayWorker({
|
|
31
|
+
botToken,
|
|
32
|
+
// Unused in inline mode — the poster below replaces the HTTP ingress hop.
|
|
33
|
+
apiPublicUrl: "",
|
|
34
|
+
ingressSecret: "",
|
|
35
|
+
poster: async ({ dispatchType, data }) => deps.ingest(dispatchType, data),
|
|
36
|
+
// Fold the guild id (seen at GUILD_CREATE) into the engine heartbeat so
|
|
37
|
+
// Studio confirms "Bot installed".
|
|
38
|
+
onGuildObserved: (guildId) => deps.onMetadata({ guildId }),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
start: () => worker.start(),
|
|
43
|
+
stop: () => worker.stop(),
|
|
44
|
+
getMetadata: () => ({ intents: worker.getIntents() }),
|
|
45
|
+
};
|
|
46
|
+
}
|
package/src/gateway/worker.ts
CHANGED
|
@@ -24,6 +24,13 @@ export interface DiscordGatewayWorkerConfig {
|
|
|
24
24
|
* it into the gateway heartbeat so Studio can confirm "Bot installed".
|
|
25
25
|
*/
|
|
26
26
|
onGuildObserved?: (guildId: string) => void;
|
|
27
|
+
/**
|
|
28
|
+
* In-process dispatch sink. When supplied, each raw dispatch is handed to this
|
|
29
|
+
* poster INSTEAD of the default HTTP ingress POST — so an engine-hosted inline
|
|
30
|
+
* runtime feeds `transform`→`ingest` directly, with no network hop and no
|
|
31
|
+
* shared ingress secret. Omit for the standalone (HTTP) path.
|
|
32
|
+
*/
|
|
33
|
+
poster?: IngressPoster;
|
|
27
34
|
}
|
|
28
35
|
|
|
29
36
|
export interface DiscordGatewayWorker {
|
|
@@ -125,7 +132,9 @@ export function createDiscordGatewayWorker(
|
|
|
125
132
|
}
|
|
126
133
|
// Fire-and-forget: forwardDispatch never throws (it try/catches and logs),
|
|
127
134
|
// so a slow/failed ingress POST never blocks the socket or crashes us.
|
|
128
|
-
|
|
135
|
+
// `config.poster` (engine inline runtime) overrides the default HTTP poster;
|
|
136
|
+
// undefined ⇒ the standalone HTTP ingress path.
|
|
137
|
+
void forwardDispatch(config, packet, config.poster);
|
|
129
138
|
});
|
|
130
139
|
// discord.js v14 routes SOCKET errors to `shardError` (and signals lifecycle
|
|
131
140
|
// via `shardDisconnect`/`invalidated`), NOT the generic `error` event. The
|
package/src/index.ts
CHANGED
|
@@ -6,6 +6,22 @@
|
|
|
6
6
|
* `"@hogsend/plugin-discord/gateway"` subpath.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
export {
|
|
10
|
+
type BroadcastToChannelArgs,
|
|
11
|
+
broadcastToChannel,
|
|
12
|
+
type DmMemberArgs,
|
|
13
|
+
type DmResult,
|
|
14
|
+
discordActions,
|
|
15
|
+
dmMember,
|
|
16
|
+
type MentionMembersArgs,
|
|
17
|
+
type MentionMembersResult,
|
|
18
|
+
type MentionRoleArgs,
|
|
19
|
+
mentionMembers,
|
|
20
|
+
mentionRole,
|
|
21
|
+
type SendChannelMessageArgs,
|
|
22
|
+
type SendMessageResult,
|
|
23
|
+
sendChannelMessage,
|
|
24
|
+
} from "./actions/index.js";
|
|
9
25
|
export {
|
|
10
26
|
ephemeralReply,
|
|
11
27
|
handleInteraction,
|