@helyx/bot 1.5.4 → 1.7.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.
Files changed (57) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +5 -2
  3. package/command-root-catalogue.json +21 -5
  4. package/dist/cloud-connector.js +2 -0
  5. package/dist/cloud-control-dispatcher.js +20 -0
  6. package/dist/command-registration-policy.js +2 -0
  7. package/dist/control-directory-contracts.d.ts +50 -0
  8. package/dist/control-directory-contracts.js +2 -0
  9. package/dist/control-server-schemas.d.ts +3 -3
  10. package/dist/control-server.d.ts +10 -46
  11. package/dist/control-server.js +50 -3
  12. package/dist/creator-invite-service.d.ts +7 -0
  13. package/dist/creator-invite-service.js +17 -0
  14. package/dist/developer-operations-module.js +0 -55
  15. package/dist/diagnostic-command.js +1 -0
  16. package/dist/discord-guild-health.d.ts +2 -2
  17. package/dist/discord-guild-health.js +1 -0
  18. package/dist/events.d.ts +1 -0
  19. package/dist/events.js +2 -0
  20. package/dist/help-credentials.d.ts +25 -0
  21. package/dist/help-credentials.js +149 -0
  22. package/dist/help-module.d.ts +27 -0
  23. package/dist/help-module.js +288 -0
  24. package/dist/help-runtime.d.ts +3 -0
  25. package/dist/help-runtime.js +42 -0
  26. package/dist/help-transport.d.ts +53 -0
  27. package/dist/help-transport.js +267 -0
  28. package/dist/index.d.ts +2 -0
  29. package/dist/index.js +10 -0
  30. package/dist/interactions.js +10 -6
  31. package/dist/process-info-module.d.ts +3 -0
  32. package/dist/process-info-module.js +97 -0
  33. package/dist/server-overview-control.d.ts +35 -0
  34. package/dist/server-overview-control.js +362 -0
  35. package/dist/server-overview-discord.d.ts +33 -0
  36. package/dist/server-overview-discord.js +212 -0
  37. package/dist/server-overview-profile.d.ts +8 -0
  38. package/dist/server-overview-profile.js +62 -0
  39. package/dist/server-overview-routes.d.ts +4 -0
  40. package/dist/server-overview-routes.js +41 -0
  41. package/dist/shard-contracts.d.ts +66 -0
  42. package/dist/shard-contracts.js +23 -0
  43. package/dist/shard-coordinator.d.ts +1 -1
  44. package/dist/shard-router.d.ts +9 -0
  45. package/dist/shard-router.js +6 -0
  46. package/dist/shard-supervisor.d.ts +1 -1
  47. package/dist/shard-supervisor.js +8 -0
  48. package/dist/shard-worker.d.ts +1 -1
  49. package/dist/shard-worker.js +8 -0
  50. package/dist/verification-service.d.ts +4 -0
  51. package/dist/verification-service.js +10 -0
  52. package/documentation/README.md +1 -0
  53. package/documentation/examples/.env.example +29 -85
  54. package/documentation/guides/help-command.md +62 -0
  55. package/documentation/reference/environment.md +7 -6
  56. package/documentation/runbooks/installation-and-upgrades.md +4 -1
  57. package/package.json +6 -6
@@ -0,0 +1,267 @@
1
+ import { z } from "zod";
2
+ import { createHelpRuntimeCollection, HELP_DOCS_URL, } from "@helyx/core";
3
+ import { HELP_API_ORIGIN, parseHelpCredential, } from "./help-credentials.js";
4
+ export class HelpTransportError extends Error {
5
+ code;
6
+ constructor(code = "unavailable") {
7
+ super(`Help ${code.replaceAll("_", " ")}`);
8
+ this.code = code;
9
+ }
10
+ }
11
+ const responseSchema = z
12
+ .object({
13
+ contractVersion: z.literal(1),
14
+ requestId: z.string().uuid(),
15
+ revision: z.string().regex(/^[a-f0-9]{64}$/u),
16
+ mode: z.enum(["lexical", "hybrid"]),
17
+ kind: z.enum(["answer", "choices", "no_match", "invalid"]),
18
+ degraded: z
19
+ .enum(["provider_disabled", "provider_unavailable", "budget_exhausted"])
20
+ .optional(),
21
+ faq: z.unknown().optional(),
22
+ faqs: z.array(z.unknown()).max(3).optional(),
23
+ choiceToken: z.string().max(2048).optional(),
24
+ reason: z.string().optional(),
25
+ docsUrl: z.string().optional(),
26
+ })
27
+ .strict();
28
+ function parseResponse(value) {
29
+ const parsed = responseSchema.parse(value), base = {
30
+ mode: parsed.mode,
31
+ revision: parsed.revision,
32
+ ...(parsed.degraded ? { degraded: parsed.degraded } : {}),
33
+ };
34
+ if (parsed.kind === "answer") {
35
+ const faqs = createHelpRuntimeCollection([
36
+ parsed.faq,
37
+ ]).faqs;
38
+ return { ...base, kind: "answer", faq: faqs[0] };
39
+ }
40
+ if (parsed.kind === "choices") {
41
+ if (!parsed.faqs?.length || !parsed.choiceToken)
42
+ throw new HelpTransportError();
43
+ const input = parsed.faqs;
44
+ const valid = new Map(createHelpRuntimeCollection(input).faqs.map((faq) => [faq.id, faq]));
45
+ const faqs = input.map((faq) => valid.get(faq.id));
46
+ return { ...base, kind: "choices", faqs, choiceToken: parsed.choiceToken };
47
+ }
48
+ if (parsed.kind === "no_match" &&
49
+ ["empty", "weak_match"].includes(parsed.reason ?? "") &&
50
+ parsed.docsUrl === HELP_DOCS_URL)
51
+ return {
52
+ ...base,
53
+ kind: "no_match",
54
+ reason: parsed.reason,
55
+ docsUrl: HELP_DOCS_URL,
56
+ };
57
+ if (parsed.kind === "invalid" && parsed.reason === "too_long")
58
+ return { ...base, kind: "invalid", reason: "too_long" };
59
+ throw new HelpTransportError();
60
+ }
61
+ export class HttpHelpTransport {
62
+ options;
63
+ blocked = false;
64
+ blockedUntil = 0;
65
+ failures = 0;
66
+ origin;
67
+ controller = new AbortController();
68
+ constructor(options) {
69
+ this.options = options;
70
+ const url = new URL(options.baseUrl ?? HELP_API_ORIGIN);
71
+ if (url.username ||
72
+ url.password ||
73
+ url.pathname !== "/" ||
74
+ url.search ||
75
+ url.hash ||
76
+ (url.protocol !== "https:" &&
77
+ !(url.protocol === "http:" &&
78
+ ["127.0.0.1", "localhost", "[::1]"].includes(url.hostname))) ||
79
+ (options.kind === "self-host" && url.origin !== HELP_API_ORIGIN))
80
+ throw new HelpTransportError();
81
+ this.origin = url.origin;
82
+ }
83
+ query(input) {
84
+ return this.request("query", {
85
+ question: input.question,
86
+ ...(input.module ? { module: input.module } : {}),
87
+ }, input);
88
+ }
89
+ choose(input) {
90
+ return this.request("choose", { choiceToken: input.choiceToken, faqId: input.faqId }, input);
91
+ }
92
+ close() {
93
+ this.controller.abort();
94
+ }
95
+ async request(path, body, identity) {
96
+ if (this.blocked ||
97
+ Date.now() < this.blockedUntil ||
98
+ this.controller.signal.aborted)
99
+ throw new HelpTransportError();
100
+ try {
101
+ const response = await (this.options.fetch ?? fetch)(`${this.origin}/v1/help/${path}`, {
102
+ method: "POST",
103
+ redirect: "error",
104
+ signal: AbortSignal.any([
105
+ this.controller.signal,
106
+ AbortSignal.timeout(6000),
107
+ ]),
108
+ headers: {
109
+ Authorization: `Bearer ${this.options.token}`,
110
+ "Content-Type": "application/json",
111
+ },
112
+ body: JSON.stringify({
113
+ contractVersion: 1,
114
+ locale: "en-GB",
115
+ botVersion: this.options.botVersion,
116
+ ...body,
117
+ ...(this.options.kind === "hosted"
118
+ ? {
119
+ subject: {
120
+ userId: identity.userId,
121
+ ...(identity.guildId ? { guildId: identity.guildId } : {}),
122
+ },
123
+ }
124
+ : {}),
125
+ }),
126
+ });
127
+ if (response.status === 401 || response.status === 403)
128
+ this.blocked = true;
129
+ if (response.status === 429)
130
+ this.blockedUntil =
131
+ Date.now() +
132
+ Math.min(3600, Math.max(60, Number(response.headers.get("Retry-After")) || 60)) *
133
+ 1000;
134
+ if (!response.ok) {
135
+ await response.body?.cancel();
136
+ if (response.status === 410)
137
+ throw new HelpTransportError("expired_choice");
138
+ throw new HelpTransportError();
139
+ }
140
+ const value = parseResponse(await boundedJson(response));
141
+ this.failures = 0;
142
+ return value;
143
+ }
144
+ catch (error) {
145
+ if (error instanceof HelpTransportError &&
146
+ error.code === "expired_choice")
147
+ throw error;
148
+ if (++this.failures >= 3)
149
+ this.blockedUntil = Math.max(this.blockedUntil, Date.now() + 30000);
150
+ throw new HelpTransportError();
151
+ }
152
+ }
153
+ }
154
+ /** Read per request so local disconnect/replacement takes effect without a restart. */
155
+ export class FileHelpTransport {
156
+ store;
157
+ botVersion;
158
+ fetcher;
159
+ current = null;
160
+ constructor(store, botVersion, fetcher) {
161
+ this.store = store;
162
+ this.botVersion = botVersion;
163
+ this.fetcher = fetcher;
164
+ }
165
+ async transport() {
166
+ const credential = await this.store.read();
167
+ if (!credential || Date.parse(credential.expiresAt) <= Date.now()) {
168
+ this.current?.transport.close();
169
+ this.current = null;
170
+ throw new HelpTransportError();
171
+ }
172
+ if (this.current?.token !== credential.token) {
173
+ this.current?.transport.close();
174
+ this.current = {
175
+ token: credential.token,
176
+ transport: new HttpHelpTransport({
177
+ token: credential.token,
178
+ kind: "self-host",
179
+ botVersion: this.botVersion,
180
+ ...(this.fetcher ? { fetch: this.fetcher } : {}),
181
+ }),
182
+ };
183
+ }
184
+ return this.current.transport;
185
+ }
186
+ async query(input) {
187
+ return (await this.transport()).query(input);
188
+ }
189
+ async choose(input) {
190
+ return (await this.transport()).choose(input);
191
+ }
192
+ close() {
193
+ this.current?.transport.close();
194
+ this.current = null;
195
+ }
196
+ }
197
+ export async function exchangeHelpEnrolment(code, fetcher = fetch) {
198
+ if (!/^hhe_[A-Za-z0-9_-]{43}$/u.test(code))
199
+ throw new HelpTransportError();
200
+ try {
201
+ const response = await fetcher(`${HELP_API_ORIGIN}/v1/help/enrolments/exchange`, {
202
+ method: "POST",
203
+ redirect: "error",
204
+ signal: AbortSignal.timeout(10000),
205
+ headers: { "Content-Type": "application/json" },
206
+ body: JSON.stringify({ code }),
207
+ });
208
+ if (!response.ok) {
209
+ await response.body?.cancel();
210
+ throw new HelpTransportError();
211
+ }
212
+ return parseHelpCredential(await boundedJson(response));
213
+ }
214
+ catch {
215
+ throw new HelpTransportError();
216
+ }
217
+ }
218
+ export async function revokeHelpCredential(token, fetcher = fetch) {
219
+ if (!/^hhp_[A-Za-z0-9_-]{43}$/u.test(token))
220
+ throw new HelpTransportError();
221
+ try {
222
+ const response = await fetcher(`${HELP_API_ORIGIN}/v1/help/disconnect`, {
223
+ method: "POST",
224
+ redirect: "error",
225
+ signal: AbortSignal.timeout(10000),
226
+ headers: {
227
+ Authorization: `Bearer ${token}`,
228
+ "Content-Type": "application/json",
229
+ },
230
+ body: JSON.stringify({ contractVersion: 1 }),
231
+ });
232
+ if (!response.ok) {
233
+ await response.body?.cancel();
234
+ throw new HelpTransportError();
235
+ }
236
+ z.object({ revoked: z.literal(true) })
237
+ .strict()
238
+ .parse(await boundedJson(response));
239
+ }
240
+ catch {
241
+ throw new HelpTransportError();
242
+ }
243
+ }
244
+ async function boundedJson(response) {
245
+ const max = 512 * 1024;
246
+ if (!response.body ||
247
+ Number(response.headers.get("Content-Length") ?? 0) > max)
248
+ throw new HelpTransportError();
249
+ const reader = response.body.getReader(), chunks = [];
250
+ let size = 0;
251
+ try {
252
+ while (true) {
253
+ const chunk = await reader.read();
254
+ if (chunk.done)
255
+ break;
256
+ const value = chunk.value;
257
+ if (!(value instanceof Uint8Array) || (size += value.byteLength) > max)
258
+ throw new HelpTransportError();
259
+ chunks.push(value);
260
+ }
261
+ }
262
+ finally {
263
+ await reader.cancel().catch(() => undefined);
264
+ }
265
+ return JSON.parse(Buffer.concat(chunks, size).toString("utf8"));
266
+ }
267
+ //# sourceMappingURL=help-transport.js.map
package/dist/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { type ModuleDefinition } from "@helyx/sdk";
2
2
  import { GatewayIntentBits } from "discord.js";
3
3
  import { type ShardHealthSnapshot } from "./shard-contracts.js";
4
+ export { HelpCredentialStore } from "./help-credentials.js";
5
+ export { exchangeHelpEnrolment, revokeHelpCredential, } from "./help-transport.js";
4
6
  export { loadConfiguredModulePackages } from "./modules.js";
5
7
  export { assertConfiguredModuleDatabaseCompatibility } from "./modules.js";
6
8
  export { resolveModulePackageSpecifiers } from "./module-configuration.js";
package/dist/index.js CHANGED
@@ -35,6 +35,10 @@ import { shardHealthSnapshotSchema, } from "./shard-contracts.js";
35
35
  import { createSupportModule } from "./support-module.js";
36
36
  import { createOAuthModule } from "./oauth-module.js";
37
37
  import { createPrivacyModule } from "./privacy-module.js";
38
+ import { createProcessInfoModule } from "./process-info-module.js";
39
+ import { createRuntimeHelpModule } from "./help-runtime.js";
40
+ export { HelpCredentialStore } from "./help-credentials.js";
41
+ export { exchangeHelpEnrolment, revokeHelpCredential, } from "./help-transport.js";
38
42
  import { installModerationPlatformServices } from "./moderation-platform-services.js";
39
43
  import { EckoEvidenceReceiver } from "./ecko-evidence-receiver.js";
40
44
  import { EckoTransportAuthenticator } from "./ecko-transport-auth.js";
@@ -361,6 +365,8 @@ async function startUnshardedBot(processEnvironment) {
361
365
  : undefined;
362
366
  const supportModule = createSupportModule(cloudConnector);
363
367
  const privacyModule = createPrivacyModule();
368
+ const processInfoModule = createProcessInfoModule("unsharded bot process");
369
+ const helpModule = createRuntimeHelpModule(environment);
364
370
  const premiumEnvironment = requirePremiumProviderEnvironment(featureModules, environment.STRIPE_ENVIRONMENT);
365
371
  const premiumActivationModule = !premiumEnvironment || !database
366
372
  ? undefined
@@ -380,6 +386,8 @@ async function startUnshardedBot(processEnvironment) {
380
386
  permissionsModule,
381
387
  supportModule,
382
388
  privacyModule,
389
+ processInfoModule,
390
+ helpModule,
383
391
  ...(premiumActivationModule ? [premiumActivationModule] : []),
384
392
  ...(oauthModule ? [oauthModule] : []),
385
393
  ...(cloudManagementModule ? [cloudManagementModule] : []),
@@ -458,6 +466,8 @@ async function startUnshardedBot(processEnvironment) {
458
466
  permissionsModule,
459
467
  supportModule,
460
468
  privacyModule,
469
+ processInfoModule,
470
+ helpModule,
461
471
  ...(premiumActivationModule ? [premiumActivationModule] : []),
462
472
  ...(oauthModule ? [oauthModule] : []),
463
473
  ...(cloudManagementModule ? [cloudManagementModule] : []),
@@ -141,15 +141,19 @@ export function installInteractions(client, modules, registration, logger, servi
141
141
  const subcommand = resolveCommandSubcommand(registered?.contribution, subcommandName, groupName);
142
142
  const owner = resolveCommandOwner(registered, subcommandName, groupName);
143
143
  const ownerModuleId = owner?.moduleId ?? registered?.moduleId;
144
+ const autocompleteOwner = subcommand ??
145
+ (!hasNestedCommands(registered?.contribution)
146
+ ? registered?.contribution
147
+ : undefined);
144
148
  if (!registered ||
145
- !subcommand?.autocomplete ||
149
+ !autocompleteOwner?.autocomplete ||
146
150
  !ownerModuleId ||
147
151
  !(await authorizeAutocomplete(interaction, ownerModuleId, resolveDirectCommandPath(registered.contribution, subcommand, groupName).permissionId, services, registration.selfAuthorizingGuildModuleIds?.has(ownerModuleId) ??
148
- false, subcommand.authorization === "resource-scoped", isInstallationIndependentModule(modulesById, ownerModuleId), subcommand.authorization, requiredCommandModule(modulesById, ownerModuleId)))) {
152
+ false, autocompleteOwner.authorization === "resource-scoped", isInstallationIndependentModule(modulesById, ownerModuleId), autocompleteOwner.authorization, requiredCommandModule(modulesById, ownerModuleId)))) {
149
153
  await response.respond([]);
150
154
  return;
151
155
  }
152
- await subcommand.autocomplete(createAutocompleteContext(interaction, services, response.respond));
156
+ await autocompleteOwner.autocomplete(createAutocompleteContext(interaction, services, response.respond));
153
157
  }
154
158
  catch (error) {
155
159
  logger.error({
@@ -217,15 +221,15 @@ export function installInteractions(client, modules, registration, logger, servi
217
221
  const acknowledgement = subcommand?.acknowledgement ?? command.acknowledgement;
218
222
  const authorization = subcommand?.authorization ?? command.authorization;
219
223
  const rateLimit = subcommand?.rateLimit ?? command.rateLimit;
224
+ if (acknowledgement === "deferred-ephemeral") {
225
+ await interaction.deferReply({ flags: MessageFlags.Ephemeral });
226
+ }
220
227
  if (installationIndependentCommand &&
221
228
  authorization === "public" &&
222
229
  !rateLimit) {
223
230
  await execute(createCommandContext(interaction, services));
224
231
  return;
225
232
  }
226
- if (acknowledgement === "deferred-ephemeral") {
227
- await interaction.deferReply({ flags: MessageFlags.Ephemeral });
228
- }
229
233
  if (await authorizeCommand(interaction, ownerModuleId, permissionId, rateLimit, services, registration.selfAuthorizingGuildModuleIds?.has(ownerModuleId) ??
230
234
  false, subcommand?.authorization === "resource-scoped", owner?.moduleName, installationIndependentCommand, authorization, requiredCommandModule(modulesById, ownerModuleId))) {
231
235
  const context = createCommandContext(interaction, services);
@@ -0,0 +1,3 @@
1
+ /** Local process metrics remain available without database or installation checks. */
2
+ export declare function createProcessInfoModule(processLabel: string): import("@helyx/sdk").ModuleDefinition;
3
+ //# sourceMappingURL=process-info-module.d.ts.map
@@ -0,0 +1,97 @@
1
+ import { defineModule } from "@helyx/sdk";
2
+ import { INTERNAL_MODULE_MANIFEST_FIELDS } from "./internal-module-manifest.js";
3
+ const everyonePolicy = {
4
+ everyone: true,
5
+ requiredPermissions: [],
6
+ allowedRoleIds: [],
7
+ deniedRoleIds: [],
8
+ allowedUserIds: [],
9
+ deniedUserIds: [],
10
+ };
11
+ /** Local process metrics remain available without database or installation checks. */
12
+ export function createProcessInfoModule(processLabel) {
13
+ return defineModule({
14
+ manifest: {
15
+ ...INTERNAL_MODULE_MANIFEST_FIELDS,
16
+ releaseStatus: "live",
17
+ id: "helyx.process-info",
18
+ name: "Helyx Process Information",
19
+ version: "0.1.0",
20
+ description: "Reports safe resource and uptime information for the running bot.",
21
+ entry: "./dist/process-info-module.js",
22
+ framework: "^0.1.0",
23
+ dependencies: [],
24
+ permissions: [],
25
+ contributions: { commands: ["proc"], events: [] },
26
+ },
27
+ defaultPermissions: {
28
+ module: everyonePolicy,
29
+ commands: { proc: everyonePolicy },
30
+ },
31
+ interactions: {
32
+ commands: [
33
+ {
34
+ name: "proc",
35
+ permissionId: "proc",
36
+ description: "Show safe process resource and uptime information",
37
+ acknowledgement: "immediate-response",
38
+ registrationPolicy: "platform-global",
39
+ contexts: ["guild", "bot_dm"],
40
+ integrationTypes: ["guild_install"],
41
+ authorization: "public",
42
+ async execute(context) {
43
+ const memory = process.memoryUsage();
44
+ const cpu = process.cpuUsage();
45
+ await context.reply({
46
+ ephemeral: true,
47
+ componentsV2: {
48
+ accentColor: 0x2563eb,
49
+ text: [
50
+ {
51
+ content: [
52
+ "## Process information",
53
+ `Runtime: ${processLabel}`,
54
+ `Uptime: ${formatDuration(process.uptime())}`,
55
+ `RSS memory: ${formatBytes(memory.rss)}`,
56
+ `Heap: ${formatBytes(memory.heapUsed)} used / ${formatBytes(memory.heapTotal)} allocated`,
57
+ `External memory: ${formatBytes(memory.external)}`,
58
+ `CPU time: ${formatCpu(cpu.user)} user / ${formatCpu(cpu.system)} system`,
59
+ `Node: ${safeInlineCode(process.version)}`,
60
+ `Platform: ${safeInlineCode(`${process.platform}/${process.arch}`)}`,
61
+ `PID: ${process.pid}`,
62
+ ].join("\n"),
63
+ },
64
+ ],
65
+ },
66
+ });
67
+ },
68
+ },
69
+ ],
70
+ },
71
+ start: () => Promise.resolve(),
72
+ stop: () => Promise.resolve(),
73
+ });
74
+ }
75
+ function safeInlineCode(value) {
76
+ return `\`${value.replaceAll("`", "'").slice(0, 120)}\``;
77
+ }
78
+ function formatBytes(value) {
79
+ return `${(value / (1024 * 1024)).toFixed(1)} MiB`;
80
+ }
81
+ function formatCpu(microseconds) {
82
+ return `${(microseconds / 1_000_000).toFixed(2)}s`;
83
+ }
84
+ function formatDuration(seconds) {
85
+ const total = Math.max(0, Math.floor(seconds));
86
+ const days = Math.floor(total / 86_400);
87
+ const hours = Math.floor((total % 86_400) / 3_600);
88
+ const minutes = Math.floor((total % 3_600) / 60);
89
+ const remainder = total % 60;
90
+ return [
91
+ ...(days > 0 ? [`${days}d`] : []),
92
+ ...(days > 0 || hours > 0 ? [`${hours}h`] : []),
93
+ `${minutes}m`,
94
+ `${remainder}s`,
95
+ ].join(" ");
96
+ }
97
+ //# sourceMappingURL=process-info-module.js.map
@@ -0,0 +1,35 @@
1
+ import { type OverviewReadInput, type OverviewResponse, type OverviewRevokeInput } from "@helyx/control-protocol";
2
+ import { type GuildAccessPolicy, type ManagedResourceContext, type ModuleDefinition, type PermissionActor, type PermissionPolicyService, type ServiceAccess } from "@helyx/sdk";
3
+ import type { OverviewDiscordDirectory } from "./server-overview-discord.js";
4
+ export declare function createServerOverviewControl(deps: {
5
+ modules: ReadonlyMap<string, ModuleDefinition>;
6
+ services: ServiceAccess;
7
+ permissions: PermissionPolicyService;
8
+ resolveActor(guildId: string, actorUserId: string): Promise<PermissionActor>;
9
+ readGuildPolicy(guildId: string): Promise<GuildAccessPolicy>;
10
+ listModules(guildId: string): Promise<readonly {
11
+ moduleId: string;
12
+ enabled: boolean;
13
+ }[]>;
14
+ requireAccessible(guildId: string, moduleId: string): Promise<void>;
15
+ directory?: OverviewDiscordDirectory | undefined;
16
+ auditInviteRevoke?(input: {
17
+ guildId: string;
18
+ actorUserId: string;
19
+ code: string;
20
+ outcome: "requested" | "revoked";
21
+ correlationId: string;
22
+ }): Promise<void>;
23
+ context(guildId: string, actor: PermissionActor): ManagedResourceContext;
24
+ }): {
25
+ invalidate(guildId: string): void;
26
+ readServerOverview(input: OverviewReadInput & {
27
+ actorUserId: string;
28
+ }): Promise<OverviewResponse>;
29
+ revokeServerOverviewInvite(input: OverviewRevokeInput & {
30
+ actorUserId: string;
31
+ }): Promise<{
32
+ revoked: true;
33
+ }>;
34
+ };
35
+ //# sourceMappingURL=server-overview-control.d.ts.map