@helyx/bot 1.3.0 → 1.4.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/CHANGELOG.md +92 -28
- package/README.md +65 -11
- package/dist/cloud-connector.d.ts +11 -4
- package/dist/cloud-connector.js +52 -15
- package/dist/cloud-control-dispatcher.d.ts +8 -3
- package/dist/cloud-control-dispatcher.js +62 -4
- package/dist/control-errors.d.ts +4 -0
- package/dist/control-errors.js +8 -0
- package/dist/control-server-schemas.d.ts +84 -0
- package/dist/control-server-schemas.js +101 -0
- package/dist/control-server.d.ts +21 -7
- package/dist/control-server.js +88 -132
- package/dist/core-retention.d.ts +26 -0
- package/dist/core-retention.js +49 -0
- package/dist/creator-guild-join-service.d.ts +25 -0
- package/dist/creator-guild-join-service.js +218 -0
- package/dist/creator-invite-service.d.ts +37 -0
- package/dist/creator-invite-service.js +686 -0
- package/dist/creator-onboarding-control.d.ts +12 -0
- package/dist/creator-onboarding-control.js +65 -0
- package/dist/creator-onboarding-platform.d.ts +20 -0
- package/dist/creator-onboarding-platform.js +58 -0
- package/dist/dashboard-action-control.d.ts +2 -2
- package/dist/dashboard-action-control.js +2 -3
- package/dist/database-bootstrap.d.ts +36 -0
- package/dist/database-bootstrap.js +101 -0
- package/dist/developer-operations-module.d.ts +1 -0
- package/dist/developer-operations-module.js +34 -16
- package/dist/discord-owned-message-service.d.ts +1 -0
- package/dist/discord-owned-message-service.js +3 -0
- package/dist/guild-command-read-service.d.ts +8 -3
- package/dist/guild-command-read-service.js +14 -7
- package/dist/guild-command-release.d.ts +15 -8
- package/dist/guild-command-release.js +10 -3
- package/dist/guild-command-worker.d.ts +17 -4
- package/dist/guild-command-worker.js +17 -6
- package/dist/guilds.d.ts +24 -3
- package/dist/guilds.js +185 -64
- package/dist/hosted-server-moderation.d.ts +2 -2
- package/dist/hosted-server-moderation.js +10 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +200 -81
- package/dist/interactions.js +16 -3
- package/dist/module-configuration.d.ts +1 -1
- package/dist/module-configuration.js +5 -2
- package/dist/module-logging.d.ts +8 -3
- package/dist/module-logging.js +13 -7
- package/dist/modules.d.ts +1 -0
- package/dist/modules.js +8 -1
- package/dist/mysql-runtime-persistence.d.ts +46 -0
- package/dist/mysql-runtime-persistence.js +91 -0
- package/dist/oauth-module.js +2 -2
- package/dist/oauth-service.d.ts +7 -0
- package/dist/oauth-service.js +3 -0
- package/dist/scheduled-task-runner.d.ts +9 -85
- package/dist/scheduled-task-runner.js +1 -1
- package/dist/shard-contracts.d.ts +135 -0
- package/dist/shard-contracts.js +13 -1
- package/dist/shard-router.d.ts +2 -1
- package/dist/shard-router.js +7 -0
- package/dist/shard-supervisor.js +43 -9
- package/dist/shard-worker.d.ts +5 -2
- package/dist/shard-worker.js +46 -5
- package/dist/supervisor-cloud-directory.d.ts +9 -3
- package/dist/supervisor-cloud-directory.js +8 -12
- package/dist/trivia-data-provider.d.ts +11 -0
- package/dist/trivia-data-provider.js +46 -26
- package/dist/verification-service.d.ts +2 -2
- package/dist/verification-service.js +6 -3
- package/documentation/README.md +5 -3
- package/documentation/examples/.env.example +15 -11
- package/documentation/guides/getting-started.md +29 -12
- package/documentation/guides/privacy-and-support.md +6 -5
- package/documentation/guides/self-hosting.md +16 -11
- package/documentation/modules/auto-moderation.md +7 -5
- package/documentation/modules/building-a-module.md +48 -2
- package/documentation/modules/moderation.md +5 -5
- package/documentation/modules/publishing-a-module.md +6 -4
- package/documentation/modules/testing-a-module.md +39 -4
- package/documentation/reference/environment.md +43 -9
- package/documentation/runbooks/backup-and-recovery.md +26 -7
- package/documentation/runbooks/installation-and-upgrades.md +97 -27
- package/package.json +20 -16
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { hasBoundedManagedResourceBytes, isBoundedManagedResourceValue, } from "./dashboard-feature-control.js";
|
|
3
|
+
export const snowflake = z.string().regex(/^\d{17,20}$/u);
|
|
4
|
+
export const moduleId = z.string().regex(/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)+$/u);
|
|
5
|
+
export const configurationValue = z.record(z.string(), z.union([
|
|
6
|
+
z.null(),
|
|
7
|
+
z.string(),
|
|
8
|
+
z.boolean(),
|
|
9
|
+
z.number().finite(),
|
|
10
|
+
z.array(z.string()).max(100),
|
|
11
|
+
]));
|
|
12
|
+
const permissionPreset = z.enum([
|
|
13
|
+
"everyone",
|
|
14
|
+
"moderators",
|
|
15
|
+
"administrators",
|
|
16
|
+
"custom",
|
|
17
|
+
]);
|
|
18
|
+
const dashboardPermissionPolicy = z.object({
|
|
19
|
+
preset: permissionPreset,
|
|
20
|
+
allowedRoleIds: z.array(snowflake).max(100),
|
|
21
|
+
deniedRoleIds: z.array(snowflake).max(100),
|
|
22
|
+
});
|
|
23
|
+
export const permissionState = z.object({
|
|
24
|
+
version: z.number().int().min(0),
|
|
25
|
+
module: dashboardPermissionPolicy,
|
|
26
|
+
commands: z
|
|
27
|
+
.array(z.object({
|
|
28
|
+
commandId: z.string().min(1).max(100),
|
|
29
|
+
version: z.number().int().min(0),
|
|
30
|
+
enabled: z.boolean(),
|
|
31
|
+
policy: dashboardPermissionPolicy,
|
|
32
|
+
}))
|
|
33
|
+
.max(100),
|
|
34
|
+
});
|
|
35
|
+
export const guildAccessPolicy = z
|
|
36
|
+
.object({
|
|
37
|
+
administratorRoleIds: z.array(snowflake).max(25),
|
|
38
|
+
moderatorRoleIds: z.array(snowflake).max(25),
|
|
39
|
+
dashboardModeratorsEnabled: z.boolean(),
|
|
40
|
+
dashboardAllowedRoleIds: z.array(snowflake).max(25),
|
|
41
|
+
dashboardDeniedRoleIds: z.array(snowflake).max(25),
|
|
42
|
+
})
|
|
43
|
+
.strict();
|
|
44
|
+
export const mutationContext = z.object({
|
|
45
|
+
actorUserId: snowflake,
|
|
46
|
+
correlationId: z.uuid(),
|
|
47
|
+
});
|
|
48
|
+
export const resourceId = z.string().trim().min(1).max(100);
|
|
49
|
+
export const resourceCursor = z.string().min(1).max(2_048);
|
|
50
|
+
export const resourceActionId = z.string().regex(/^[a-z][a-z0-9_-]*$/u);
|
|
51
|
+
export const managedResourceFilters = z
|
|
52
|
+
.record(z.string().regex(/^[a-z][a-zA-Z0-9_]*$/u), z.string().trim().min(1).max(100))
|
|
53
|
+
.refine((value) => Object.keys(value).length <= 8);
|
|
54
|
+
const managedResourceValue = z.custom((value) => isBoundedManagedResourceValue(value), "Managed resource value exceeds the transport limits");
|
|
55
|
+
export const managedResourceObject = z
|
|
56
|
+
.record(z.string().min(1).max(100), managedResourceValue)
|
|
57
|
+
.refine(hasBoundedManagedResourceBytes);
|
|
58
|
+
const managedResourceSummarySchema = z
|
|
59
|
+
.object({
|
|
60
|
+
id: resourceId,
|
|
61
|
+
revision: z.number().int().min(0),
|
|
62
|
+
status: z.string().trim().min(1).max(100),
|
|
63
|
+
title: z.string().trim().min(1).max(200),
|
|
64
|
+
description: z.string().max(500).optional(),
|
|
65
|
+
attributes: managedResourceObject.optional(),
|
|
66
|
+
updatedAt: z.iso.datetime({ offset: true }),
|
|
67
|
+
})
|
|
68
|
+
.strict();
|
|
69
|
+
export const managedResourceDetailSchema = managedResourceSummarySchema
|
|
70
|
+
.extend({
|
|
71
|
+
value: managedResourceObject,
|
|
72
|
+
availableActionIds: z.array(z.string().min(1).max(100)).max(50).optional(),
|
|
73
|
+
})
|
|
74
|
+
.strict()
|
|
75
|
+
.refine(hasBoundedManagedResourceBytes);
|
|
76
|
+
export const managedResourcePageSchema = z
|
|
77
|
+
.object({
|
|
78
|
+
items: z.array(managedResourceSummarySchema).max(50),
|
|
79
|
+
nextCursor: resourceCursor.optional(),
|
|
80
|
+
total: z.number().int().min(0).optional(),
|
|
81
|
+
})
|
|
82
|
+
.strict()
|
|
83
|
+
.refine(hasBoundedManagedResourceBytes);
|
|
84
|
+
export const managedResourceRelationPageSchema = z
|
|
85
|
+
.object({
|
|
86
|
+
items: z
|
|
87
|
+
.array(z
|
|
88
|
+
.object({
|
|
89
|
+
id: resourceId,
|
|
90
|
+
value: managedResourceObject,
|
|
91
|
+
})
|
|
92
|
+
.strict())
|
|
93
|
+
.max(50),
|
|
94
|
+
nextCursor: resourceCursor.optional(),
|
|
95
|
+
})
|
|
96
|
+
.strict()
|
|
97
|
+
.refine(hasBoundedManagedResourceBytes);
|
|
98
|
+
export const managedResourceDeleteResultSchema = z
|
|
99
|
+
.object({ deleted: z.boolean() })
|
|
100
|
+
.strict();
|
|
101
|
+
//# sourceMappingURL=control-server-schemas.js.map
|
package/dist/control-server.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { type DatabasePool, type GuildShardOwnership } from "@helyx/database";
|
|
1
|
+
import { AuditRepository, GuildAccessPolicyRepository, InstallationRepository, ModuleLoggingPolicyRepository, PermissionPolicyRepository, type DatabasePool, type GuildShardOwnership } from "@helyx/database";
|
|
2
|
+
import type { MysqlPool } from "@helyx/database-mysql";
|
|
3
|
+
import type { CreatorOnboardingRequest, CreatorOnboardingResponse } from "@helyx/sdk";
|
|
2
4
|
import { type DashboardActionInspection, type DashboardActionResult, type FeatureAccessDecision, type GuildAccessPolicy, type ManagedResourceCreationIntent, type ManagedResourceDetail, type ManagedResourcePage, type ManagedResourceRelationPage, type ManagedResourceValue, type MessageResponse, type ModuleDefinition, type OAuthConsumerCleanupResult, type PermissionActor, type PrivacyCapturePage, type PrivacyErasePage, type PrivacyProviderExecutor, type PublicAchievementProjectionPage, type ServiceAccess } from "@helyx/sdk";
|
|
3
5
|
import { type ActionReceipt, type SignedAssessmentEnvelope } from "@helyx/verification-contracts";
|
|
4
6
|
import { type Client } from "discord.js";
|
|
@@ -7,6 +9,7 @@ import { type BotModuleStatusMutationResult } from "./module-status-control.js";
|
|
|
7
9
|
import { type FirstTimeCommandSetupHandler } from "./first-time-command-setup.js";
|
|
8
10
|
import { type ShardHealthSnapshot } from "./shard-contracts.js";
|
|
9
11
|
import { type DashboardPermissionState } from "./control-permissions.js";
|
|
12
|
+
export { BotControlTransportError } from "./control-errors.js";
|
|
10
13
|
import { type DashboardModuleDefinition } from "./dashboard-module-projection.js";
|
|
11
14
|
import { type AvailabilityModuleCatalogue } from "./module-availability-control.js";
|
|
12
15
|
import { registerGuildCommandControlRoutes } from "./guild-command-control-routes.js";
|
|
@@ -118,6 +121,7 @@ export interface DashboardGuildAccessState extends GuildAccessPolicy {
|
|
|
118
121
|
updatedAt: string | null;
|
|
119
122
|
}
|
|
120
123
|
export interface BotControlHandler extends FirstTimeCommandSetupHandler, DashboardActionHandler {
|
|
124
|
+
creatorOnboarding?(input: CreatorOnboardingRequest): Promise<CreatorOnboardingResponse>;
|
|
121
125
|
cleanupOAuthConsumer(input: {
|
|
122
126
|
consumerBindingId: string;
|
|
123
127
|
moduleId: string;
|
|
@@ -324,21 +328,32 @@ export interface BotControlHandler extends FirstTimeCommandSetupHandler, Dashboa
|
|
|
324
328
|
cursor?: string;
|
|
325
329
|
}): Promise<PrivacyErasePage>;
|
|
326
330
|
}
|
|
327
|
-
export
|
|
328
|
-
|
|
329
|
-
|
|
331
|
+
export interface BotControlRepositories {
|
|
332
|
+
installations: Pick<InstallationRepository, "adoptGuildsForReconciliation" | "markGuildsRemovedForReconciliation" | "listModules" | "isModuleEnabled">;
|
|
333
|
+
accessPolicies: Pick<GuildAccessPolicyRepository, "get" | "save">;
|
|
334
|
+
loggingPolicies: Pick<ModuleLoggingPolicyRepository, "listForGuild" | "save">;
|
|
335
|
+
permissionPolicies: Pick<PermissionPolicyRepository, "save" | "deleteCommandPolicy">;
|
|
336
|
+
audit: Pick<AuditRepository, "append">;
|
|
330
337
|
}
|
|
338
|
+
interface ControlPersistence {
|
|
339
|
+
readonly repositories: BotControlRepositories;
|
|
340
|
+
withTransaction<Value>(operation: (repositories: BotControlRepositories) => Promise<Value>): Promise<Value>;
|
|
341
|
+
}
|
|
342
|
+
export interface BotControlPersistence extends ControlPersistence {
|
|
343
|
+
readonly engine: "mysql";
|
|
344
|
+
}
|
|
345
|
+
export declare function createMysqlBotControlPersistence(pool: MysqlPool): Promise<BotControlPersistence>;
|
|
331
346
|
export declare class BotControlService implements BotControlHandler {
|
|
332
347
|
#private;
|
|
333
|
-
private readonly database;
|
|
334
348
|
private readonly resources;
|
|
335
349
|
private readonly supportNotifications?;
|
|
336
350
|
private readonly presenceOwnership?;
|
|
337
351
|
private readonly presenceShardCount?;
|
|
338
|
-
constructor(
|
|
352
|
+
constructor(databaseOrPersistence: DatabasePool | BotControlPersistence, modules: readonly ModuleDefinition[], resources: BotControlGuildResourceDirectory, services: ServiceAccess, privacyExecutor?: PrivacyProviderExecutor, supportNotifications?: {
|
|
339
353
|
guildId: string;
|
|
340
354
|
channelId: string;
|
|
341
355
|
} | undefined, presenceOwnership?: GuildShardOwnership | undefined, presenceShardCount?: number | undefined, statusModules?: readonly ModuleDefinition[]);
|
|
356
|
+
creatorOnboarding(input: CreatorOnboardingRequest): Promise<CreatorOnboardingResponse>;
|
|
342
357
|
cleanupOAuthConsumer(input: {
|
|
343
358
|
consumerBindingId: string;
|
|
344
359
|
moduleId: string;
|
|
@@ -590,5 +605,4 @@ export declare function mapBotControlError(error: unknown): {
|
|
|
590
605
|
status: 400 | 403 | 404 | 409;
|
|
591
606
|
message: string;
|
|
592
607
|
} | undefined;
|
|
593
|
-
export {};
|
|
594
608
|
//# sourceMappingURL=control-server.d.ts.map
|
package/dist/control-server.js
CHANGED
|
@@ -13,116 +13,21 @@ import { canAccessModule, PREMIUM_MODULE_UNAVAILABLE_MESSAGE, } from "./premium-
|
|
|
13
13
|
import { completeFirstTimeCommandSetup, } from "./first-time-command-setup.js";
|
|
14
14
|
import { SHARD_HEALTH_STALE_MS, } from "./shard-contracts.js";
|
|
15
15
|
import { assertVersion, declaredManagedResourcePermission, fromDashboardPolicy, managedResourcePermissionId, permissionPoliciesEqual, permissionPolicyKey, safeOptionalVersion, safeVersion, toDashboardPolicy, } from "./control-permissions.js";
|
|
16
|
-
import { assertPermissionMutationAllowed, BotControlForbiddenError, } from "./control-errors.js";
|
|
16
|
+
import { assertPermissionMutationAllowed, BotControlForbiddenError, BotControlTransportError, } from "./control-errors.js";
|
|
17
|
+
export { BotControlTransportError } from "./control-errors.js";
|
|
17
18
|
import { dashboardCommands } from "./dashboard-commands.js";
|
|
19
|
+
import { executeCreatorOnboarding, registerCreatorOnboardingControlRoute, } from "./creator-onboarding-control.js";
|
|
18
20
|
import { mapDashboardModule, } from "./dashboard-module-projection.js";
|
|
19
21
|
import { availabilityCatalogueDefinitions, availabilityCatalogue, dashboardModuleStatus, disabledModuleSummary, moduleAvailabilityService, moduleAvailabilityStates, statusCatalogueDefinitions, } from "./module-availability-control.js";
|
|
20
22
|
import { registerGuildCommandControlRoutes } from "./guild-command-control-routes.js";
|
|
21
23
|
import { createPrivacyProviderRegistry, describePrivacyProviders, } from "./privacy-provider-registry.js";
|
|
22
|
-
import { changedSettingFeatureIds, configurationPreviewFeatureIds,
|
|
24
|
+
import { changedSettingFeatureIds, configurationPreviewFeatureIds, managedResourceColumnKeys, normalizeManagedResourceDetail, normalizeManagedResourcePage, normalizeManagedResourceRelationPage, projectManagedResourceObject, requireDashboardFeatures, resourceFieldFeatureIds, scalarInputFeatureIds, validateManagedResourceInput, } from "./dashboard-feature-control.js";
|
|
23
25
|
import { registerDashboardPreviewImportRoutes, registerDashboardResourceMutationRoutes, } from "./dashboard-preview-import-routes.js";
|
|
24
26
|
import { executeDashboardAction as executeDeclaredDashboardAction, previewDashboardAction as previewDeclaredDashboardAction, } from "./dashboard-action-control.js";
|
|
25
27
|
import { registerDashboardActionRoutes, } from "./dashboard-action-routes.js";
|
|
26
28
|
import { registerEckoTransportRoutes, } from "./ecko-transport-routes.js";
|
|
27
29
|
import { validateDiscordUserSettingSelections, validateDiscordSettingSelections, } from "./dashboard-discord-settings.js";
|
|
28
|
-
|
|
29
|
-
const moduleId = z.string().regex(/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)+$/u);
|
|
30
|
-
const configurationValue = z.record(z.string(), z.union([
|
|
31
|
-
z.null(),
|
|
32
|
-
z.string(),
|
|
33
|
-
z.boolean(),
|
|
34
|
-
z.number().finite(),
|
|
35
|
-
z.array(z.string()).max(100),
|
|
36
|
-
]));
|
|
37
|
-
const permissionPreset = z.enum([
|
|
38
|
-
"everyone",
|
|
39
|
-
"moderators",
|
|
40
|
-
"administrators",
|
|
41
|
-
"custom",
|
|
42
|
-
]);
|
|
43
|
-
const dashboardPermissionPolicy = z.object({
|
|
44
|
-
preset: permissionPreset,
|
|
45
|
-
allowedRoleIds: z.array(snowflake).max(100),
|
|
46
|
-
deniedRoleIds: z.array(snowflake).max(100),
|
|
47
|
-
});
|
|
48
|
-
const permissionState = z.object({
|
|
49
|
-
version: z.number().int().min(0),
|
|
50
|
-
module: dashboardPermissionPolicy,
|
|
51
|
-
commands: z
|
|
52
|
-
.array(z.object({
|
|
53
|
-
commandId: z.string().min(1).max(100),
|
|
54
|
-
version: z.number().int().min(0),
|
|
55
|
-
enabled: z.boolean(),
|
|
56
|
-
policy: dashboardPermissionPolicy,
|
|
57
|
-
}))
|
|
58
|
-
.max(100),
|
|
59
|
-
});
|
|
60
|
-
const guildAccessPolicy = z
|
|
61
|
-
.object({
|
|
62
|
-
administratorRoleIds: z.array(snowflake).max(25),
|
|
63
|
-
moderatorRoleIds: z.array(snowflake).max(25),
|
|
64
|
-
dashboardModeratorsEnabled: z.boolean(),
|
|
65
|
-
dashboardAllowedRoleIds: z.array(snowflake).max(25),
|
|
66
|
-
dashboardDeniedRoleIds: z.array(snowflake).max(25),
|
|
67
|
-
})
|
|
68
|
-
.strict();
|
|
69
|
-
const mutationContext = z.object({
|
|
70
|
-
actorUserId: snowflake,
|
|
71
|
-
correlationId: z.uuid(),
|
|
72
|
-
});
|
|
73
|
-
const resourceId = z.string().trim().min(1).max(100);
|
|
74
|
-
const resourceCursor = z.string().min(1).max(2_048);
|
|
75
|
-
const resourceActionId = z.string().regex(/^[a-z][a-z0-9_-]*$/u);
|
|
76
|
-
const managedResourceFilters = z
|
|
77
|
-
.record(z.string().regex(/^[a-z][a-zA-Z0-9_]*$/u), z.string().trim().min(1).max(100))
|
|
78
|
-
.refine((value) => Object.keys(value).length <= 8);
|
|
79
|
-
const managedResourceValue = z.custom((value) => isBoundedManagedResourceValue(value), "Managed resource value exceeds the transport limits");
|
|
80
|
-
const managedResourceObject = z
|
|
81
|
-
.record(z.string().min(1).max(100), managedResourceValue)
|
|
82
|
-
.refine(hasBoundedManagedResourceBytes);
|
|
83
|
-
const managedResourceSummarySchema = z
|
|
84
|
-
.object({
|
|
85
|
-
id: resourceId,
|
|
86
|
-
revision: z.number().int().min(0),
|
|
87
|
-
status: z.string().trim().min(1).max(100),
|
|
88
|
-
title: z.string().trim().min(1).max(200),
|
|
89
|
-
description: z.string().max(500).optional(),
|
|
90
|
-
attributes: managedResourceObject.optional(),
|
|
91
|
-
updatedAt: z.iso.datetime({ offset: true }),
|
|
92
|
-
})
|
|
93
|
-
.strict();
|
|
94
|
-
const managedResourceDetailSchema = managedResourceSummarySchema
|
|
95
|
-
.extend({
|
|
96
|
-
value: managedResourceObject,
|
|
97
|
-
availableActionIds: z.array(z.string().min(1).max(100)).max(50).optional(),
|
|
98
|
-
})
|
|
99
|
-
.strict()
|
|
100
|
-
.refine(hasBoundedManagedResourceBytes);
|
|
101
|
-
const managedResourcePageSchema = z
|
|
102
|
-
.object({
|
|
103
|
-
items: z.array(managedResourceSummarySchema).max(50),
|
|
104
|
-
nextCursor: resourceCursor.optional(),
|
|
105
|
-
total: z.number().int().min(0).optional(),
|
|
106
|
-
})
|
|
107
|
-
.strict()
|
|
108
|
-
.refine(hasBoundedManagedResourceBytes);
|
|
109
|
-
const managedResourceRelationPageSchema = z
|
|
110
|
-
.object({
|
|
111
|
-
items: z
|
|
112
|
-
.array(z
|
|
113
|
-
.object({
|
|
114
|
-
id: resourceId,
|
|
115
|
-
value: managedResourceObject,
|
|
116
|
-
})
|
|
117
|
-
.strict())
|
|
118
|
-
.max(50),
|
|
119
|
-
nextCursor: resourceCursor.optional(),
|
|
120
|
-
})
|
|
121
|
-
.strict()
|
|
122
|
-
.refine(hasBoundedManagedResourceBytes);
|
|
123
|
-
const managedResourceDeleteResultSchema = z
|
|
124
|
-
.object({ deleted: z.boolean() })
|
|
125
|
-
.strict();
|
|
30
|
+
import { configurationValue, guildAccessPolicy, managedResourceDeleteResultSchema, managedResourceDetailSchema, managedResourceFilters, managedResourceObject, managedResourcePageSchema, managedResourceRelationPageSchema, moduleId, mutationContext, permissionState, resourceActionId, resourceCursor, resourceId, snowflake, } from "./control-server-schemas.js";
|
|
126
31
|
export class DiscordGuildResourceDirectory {
|
|
127
32
|
client;
|
|
128
33
|
constructor(client) {
|
|
@@ -265,16 +170,37 @@ export class DiscordGuildResourceDirectory {
|
|
|
265
170
|
await sendDiscordMessageToChannel(this.client, channel.id, response, notificationId);
|
|
266
171
|
}
|
|
267
172
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
173
|
+
function createPostgresControlRepositories(connection) {
|
|
174
|
+
return {
|
|
175
|
+
installations: new InstallationRepository(connection),
|
|
176
|
+
accessPolicies: new GuildAccessPolicyRepository(connection),
|
|
177
|
+
loggingPolicies: new ModuleLoggingPolicyRepository(connection),
|
|
178
|
+
permissionPolicies: new PermissionPolicyRepository(connection),
|
|
179
|
+
audit: new AuditRepository(connection),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function createPostgresControlPersistence(database) {
|
|
183
|
+
return {
|
|
184
|
+
repositories: createPostgresControlRepositories(database),
|
|
185
|
+
withTransaction: (operation) => withTransaction(database, (connection) => operation(createPostgresControlRepositories(connection))),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
export async function createMysqlBotControlPersistence(pool) {
|
|
189
|
+
const mysql = await import("@helyx/database-mysql");
|
|
190
|
+
const repositories = (connection) => ({
|
|
191
|
+
installations: new mysql.InstallationRepository(connection),
|
|
192
|
+
accessPolicies: new mysql.GuildAccessPolicyRepository(connection),
|
|
193
|
+
loggingPolicies: new mysql.ModuleLoggingPolicyRepository(connection),
|
|
194
|
+
permissionPolicies: new mysql.PermissionPolicyRepository(connection),
|
|
195
|
+
audit: new mysql.AuditRepository(connection),
|
|
196
|
+
});
|
|
197
|
+
return {
|
|
198
|
+
engine: "mysql",
|
|
199
|
+
repositories: repositories(pool),
|
|
200
|
+
withTransaction: (operation) => mysql.withMysqlTransaction(pool, (connection) => operation(repositories(mysql.createMysqlQueryExecutor(connection)))),
|
|
201
|
+
};
|
|
275
202
|
}
|
|
276
203
|
export class BotControlService {
|
|
277
|
-
database;
|
|
278
204
|
resources;
|
|
279
205
|
supportNotifications;
|
|
280
206
|
presenceOwnership;
|
|
@@ -288,12 +214,16 @@ export class BotControlService {
|
|
|
288
214
|
#permissions;
|
|
289
215
|
#services;
|
|
290
216
|
#privacyProviders;
|
|
291
|
-
|
|
292
|
-
|
|
217
|
+
#persistence;
|
|
218
|
+
constructor(databaseOrPersistence, modules, resources, services, privacyExecutor, supportNotifications, presenceOwnership, presenceShardCount, statusModules) {
|
|
293
219
|
this.resources = resources;
|
|
294
220
|
this.supportNotifications = supportNotifications;
|
|
295
221
|
this.presenceOwnership = presenceOwnership;
|
|
296
222
|
this.presenceShardCount = presenceShardCount;
|
|
223
|
+
this.#persistence =
|
|
224
|
+
"engine" in databaseOrPersistence
|
|
225
|
+
? databaseOrPersistence
|
|
226
|
+
: createPostgresControlPersistence(databaseOrPersistence);
|
|
297
227
|
this.#modules = new Map(modules.map((module) => [module.manifest.id, module]));
|
|
298
228
|
this.#dashboardModules = modules
|
|
299
229
|
.filter((module) => module.manifest.dashboard !== undefined)
|
|
@@ -306,6 +236,13 @@ export class BotControlService {
|
|
|
306
236
|
this.#services = services;
|
|
307
237
|
this.#privacyProviders = createPrivacyProviderRegistry(modules, privacyExecutor, this.#services);
|
|
308
238
|
}
|
|
239
|
+
async creatorOnboarding(input) {
|
|
240
|
+
return executeCreatorOnboarding(input, {
|
|
241
|
+
modules: this.#modules,
|
|
242
|
+
installations: this.#installations,
|
|
243
|
+
services: this.#services,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
309
246
|
async cleanupOAuthConsumer(input) {
|
|
310
247
|
const module = this.#modules.get(input.moduleId);
|
|
311
248
|
if (!module)
|
|
@@ -344,7 +281,7 @@ export class BotControlService {
|
|
|
344
281
|
.filter(({ state }) => state === "not_installed")
|
|
345
282
|
.map(({ guildId }) => guildId);
|
|
346
283
|
if (absent.length > 0) {
|
|
347
|
-
const repository =
|
|
284
|
+
const repository = this.#persistence.repositories.installations;
|
|
348
285
|
if (this.presenceOwnership)
|
|
349
286
|
await repository.adoptGuildsForReconciliation({
|
|
350
287
|
guildIds: absent,
|
|
@@ -439,8 +376,8 @@ export class BotControlService {
|
|
|
439
376
|
]);
|
|
440
377
|
const [resources, installedModules, storedLoggingPolicies, runtime, storedConfigurations, storedPermissions, availabilityStates,] = await Promise.all([
|
|
441
378
|
this.resources.getGuildResources(guildId),
|
|
442
|
-
|
|
443
|
-
|
|
379
|
+
this.#persistence.repositories.installations.listModules(guildId),
|
|
380
|
+
this.#persistence.repositories.loggingPolicies.listForGuild(guildId),
|
|
444
381
|
this.#inspectRuntimeCapabilities(),
|
|
445
382
|
this.#readConfigurations(guildId, moduleIds),
|
|
446
383
|
this.#readPermissionPolicies(guildId, permissionTargets),
|
|
@@ -516,7 +453,7 @@ export class BotControlService {
|
|
|
516
453
|
async getGuildAccessPolicy(input) {
|
|
517
454
|
const [actor, record] = await Promise.all([
|
|
518
455
|
this.resources.resolveActor(input.guildId, input.actorUserId),
|
|
519
|
-
|
|
456
|
+
this.#persistence.repositories.accessPolicies.get(input.guildId),
|
|
520
457
|
]);
|
|
521
458
|
const policy = record ?? DEFAULT_GUILD_ACCESS_POLICY;
|
|
522
459
|
return {
|
|
@@ -547,8 +484,8 @@ export class BotControlService {
|
|
|
547
484
|
];
|
|
548
485
|
if (roleIds.some((roleId) => !availableRoles.has(roleId)))
|
|
549
486
|
throw new BotControlValidationError("Dashboard access contains a Discord role that is no longer available");
|
|
550
|
-
const saved = await withTransaction(
|
|
551
|
-
const record = await
|
|
487
|
+
const saved = await this.#persistence.withTransaction(async (repositories) => {
|
|
488
|
+
const record = await repositories.accessPolicies.save({
|
|
552
489
|
guildId: input.guildId,
|
|
553
490
|
administratorRoleIds: [...input.policy.administratorRoleIds],
|
|
554
491
|
moderatorRoleIds: [...input.policy.moderatorRoleIds],
|
|
@@ -558,7 +495,7 @@ export class BotControlService {
|
|
|
558
495
|
expectedVersion: input.version === 0 ? null : BigInt(input.version),
|
|
559
496
|
updatedBy: input.actorUserId,
|
|
560
497
|
});
|
|
561
|
-
await
|
|
498
|
+
await repositories.audit.append({
|
|
562
499
|
guildId: input.guildId,
|
|
563
500
|
actorUserId: input.actorUserId,
|
|
564
501
|
action: "guild.access.updated",
|
|
@@ -590,14 +527,14 @@ export class BotControlService {
|
|
|
590
527
|
};
|
|
591
528
|
}
|
|
592
529
|
async #readGuildAccessPolicy(guildId) {
|
|
593
|
-
return ((await
|
|
530
|
+
return ((await this.#persistence.repositories.accessPolicies.get(guildId)) ??
|
|
594
531
|
DEFAULT_GUILD_ACCESS_POLICY);
|
|
595
532
|
}
|
|
596
533
|
async readPublicModuleProjection(input) {
|
|
597
534
|
const module = this.#requireModule(input.moduleId);
|
|
598
535
|
if (!module.publicProjection)
|
|
599
536
|
throw new BotControlNotFoundError("Public module projection was not found");
|
|
600
|
-
if (!(await
|
|
537
|
+
if (!(await this.#persistence.repositories.installations.isModuleEnabled(input.guildId, input.moduleId)))
|
|
601
538
|
throw new BotControlValidationError("This module is not enabled");
|
|
602
539
|
if (input.subjectUserId) {
|
|
603
540
|
if (!this.#services.has(HELYX_SERVICE_NAMES.discordResources))
|
|
@@ -775,9 +712,9 @@ export class BotControlService {
|
|
|
775
712
|
if (enabledChanged || !permissionPoliciesEqual(current.policy, target))
|
|
776
713
|
assertPermissionMutationAllowed(canMutatePermissionPolicy(actor, current.policy, target, guildAccess, rolePositions));
|
|
777
714
|
}
|
|
778
|
-
await withTransaction(
|
|
779
|
-
const policies =
|
|
780
|
-
const audit =
|
|
715
|
+
await this.#persistence.withTransaction(async (repositories) => {
|
|
716
|
+
const policies = repositories.permissionPolicies;
|
|
717
|
+
const audit = repositories.audit;
|
|
781
718
|
const savedModule = await policies.save({
|
|
782
719
|
guildId: input.guildId,
|
|
783
720
|
moduleId: input.moduleId,
|
|
@@ -799,6 +736,12 @@ export class BotControlService {
|
|
|
799
736
|
for (const command of commands) {
|
|
800
737
|
const requested = supplied.get(command.id);
|
|
801
738
|
const current = currentCommands.get(command.id);
|
|
739
|
+
const target = requested.enabled
|
|
740
|
+
? fromDashboardPolicy(requested.policy, current.policy)
|
|
741
|
+
: requestedModulePolicy;
|
|
742
|
+
const enabledChanged = requested.enabled === current.inherited;
|
|
743
|
+
if (!enabledChanged && permissionPoliciesEqual(current.policy, target))
|
|
744
|
+
continue;
|
|
802
745
|
if (requested.enabled) {
|
|
803
746
|
const saved = await policies.save({
|
|
804
747
|
guildId: input.guildId,
|
|
@@ -870,7 +813,7 @@ export class BotControlService {
|
|
|
870
813
|
if (!this.#modules.has("helyx.logging")) {
|
|
871
814
|
throw new BotControlNotFoundError("Logging is not installed");
|
|
872
815
|
}
|
|
873
|
-
if (!(await
|
|
816
|
+
if (!(await this.#persistence.repositories.installations.isModuleEnabled(input.guildId, "helyx.logging"))) {
|
|
874
817
|
throw new BotControlValidationError("Enable Logging before changing activity events");
|
|
875
818
|
}
|
|
876
819
|
const source = this.#requireModule(input.moduleId);
|
|
@@ -878,8 +821,8 @@ export class BotControlService {
|
|
|
878
821
|
if (!event) {
|
|
879
822
|
throw new BotControlNotFoundError("Logging event is not declared by this module");
|
|
880
823
|
}
|
|
881
|
-
const saved = await withTransaction(
|
|
882
|
-
const policy = await
|
|
824
|
+
const saved = await this.#persistence.withTransaction(async (repositories) => {
|
|
825
|
+
const policy = await repositories.loggingPolicies.save({
|
|
883
826
|
guildId: input.guildId,
|
|
884
827
|
sourceModuleId: input.moduleId,
|
|
885
828
|
eventId: input.eventId,
|
|
@@ -887,7 +830,7 @@ export class BotControlService {
|
|
|
887
830
|
expectedVersion: input.expectedVersion === 0 ? null : BigInt(input.expectedVersion),
|
|
888
831
|
updatedBy: input.actorUserId,
|
|
889
832
|
});
|
|
890
|
-
await
|
|
833
|
+
await repositories.audit.append({
|
|
891
834
|
guildId: input.guildId,
|
|
892
835
|
actorUserId: input.actorUserId,
|
|
893
836
|
action: "module.logging.updated",
|
|
@@ -917,7 +860,7 @@ export class BotControlService {
|
|
|
917
860
|
}
|
|
918
861
|
#dashboardActionControl() {
|
|
919
862
|
return {
|
|
920
|
-
|
|
863
|
+
installations: this.#persistence.repositories.installations,
|
|
921
864
|
services: this.#services,
|
|
922
865
|
requireDashboardModule: (moduleIdValue) => this.#requireDashboardModule(moduleIdValue),
|
|
923
866
|
requireModuleAccessible: (guildId, moduleIdValue) => this.#requireModuleAccessible(guildId, moduleIdValue),
|
|
@@ -1103,7 +1046,7 @@ export class BotControlService {
|
|
|
1103
1046
|
}
|
|
1104
1047
|
}
|
|
1105
1048
|
async #requireEnabledManagedResource(guildId, moduleIdValue) {
|
|
1106
|
-
if (!(await
|
|
1049
|
+
if (!(await this.#persistence.repositories.installations.isModuleEnabled(guildId, moduleIdValue)))
|
|
1107
1050
|
throw new BotControlValidationError("Enable this module before managing its resources");
|
|
1108
1051
|
}
|
|
1109
1052
|
async #managedResourceContext(input, module, operation, permissionId = managedResourcePermissionId(module, input.resourceType, operation, undefined, declaredManagedResourcePermission(module, input.resourceType, operation))) {
|
|
@@ -1309,6 +1252,7 @@ export async function createBotControlServer(input) {
|
|
|
1309
1252
|
return reply.code(503).send({ status: "unavailable" });
|
|
1310
1253
|
}
|
|
1311
1254
|
server.get("/health", (_request, reply) => readiness(reply));
|
|
1255
|
+
registerCreatorOnboardingControlRoute(server, input.service);
|
|
1312
1256
|
server.get("/v1/health", (_request, reply) => readiness(reply));
|
|
1313
1257
|
server.get("/v1/runtime-configuration", (_request, reply) => reply.header("Cache-Control", "no-store").send({
|
|
1314
1258
|
hostedModerationEnabled: input.runtimeConfiguration?.hostedModerationEnabled ?? false,
|
|
@@ -1716,22 +1660,30 @@ export function mapBotControlError(error) {
|
|
|
1716
1660
|
return { status: 404, message: error.message };
|
|
1717
1661
|
if (error instanceof BotControlForbiddenError)
|
|
1718
1662
|
return { status: 403, message: error.message };
|
|
1719
|
-
if (error instanceof OptimisticConcurrencyError
|
|
1663
|
+
if (error instanceof OptimisticConcurrencyError ||
|
|
1664
|
+
(error instanceof Error &&
|
|
1665
|
+
error.name === "DatabaseFailure" &&
|
|
1666
|
+
"kind" in error &&
|
|
1667
|
+
error.kind === "conflict"))
|
|
1720
1668
|
return {
|
|
1721
1669
|
status: 409,
|
|
1722
1670
|
message: "Configuration changed in another session. Reload and try again.",
|
|
1723
1671
|
};
|
|
1724
|
-
if (error instanceof GuildCommandRevisionConflictError
|
|
1672
|
+
if (error instanceof GuildCommandRevisionConflictError ||
|
|
1673
|
+
(error instanceof Error &&
|
|
1674
|
+
error.name === "GuildCommandRevisionConflictError"))
|
|
1725
1675
|
return {
|
|
1726
1676
|
status: 409,
|
|
1727
1677
|
message: "Command state changed in another session. Refresh and try again.",
|
|
1728
1678
|
};
|
|
1729
|
-
if (error instanceof GuildCommandActiveLeaseError
|
|
1679
|
+
if (error instanceof GuildCommandActiveLeaseError ||
|
|
1680
|
+
(error instanceof Error && error.name === "GuildCommandActiveLeaseError"))
|
|
1730
1681
|
return {
|
|
1731
1682
|
status: 409,
|
|
1732
1683
|
message: "A command build is already running. Wait for it to finish.",
|
|
1733
1684
|
};
|
|
1734
|
-
if (error instanceof GuildCommandSetupConflictError
|
|
1685
|
+
if (error instanceof GuildCommandSetupConflictError ||
|
|
1686
|
+
(error instanceof Error && error.name === "GuildCommandSetupConflictError"))
|
|
1735
1687
|
return {
|
|
1736
1688
|
status: 409,
|
|
1737
1689
|
message: "Command setup changed. Reload the page and try again.",
|
|
@@ -1739,6 +1691,10 @@ export function mapBotControlError(error) {
|
|
|
1739
1691
|
return undefined;
|
|
1740
1692
|
}
|
|
1741
1693
|
class BotControlValidationError extends Error {
|
|
1694
|
+
constructor(message) {
|
|
1695
|
+
super(message);
|
|
1696
|
+
this.name = "BotControlValidationError";
|
|
1697
|
+
}
|
|
1742
1698
|
}
|
|
1743
1699
|
class BotControlNotFoundError extends Error {
|
|
1744
1700
|
constructor(message = "Discord server is not available to Helyx") {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { AuditRepository, GuildCommandRepository, HostedServerSafetyRepository, InteractionSessionRepository, RateLimitRepository, type DatabasePool } from "@helyx/database";
|
|
2
|
+
import type { GuildCommandRepository as MysqlGuildCommandRepository, InteractionSessionRepository as MysqlInteractionSessionRepository, MysqlPool, RateLimitRepository as MysqlRateLimitRepository } from "@helyx/database-mysql";
|
|
3
|
+
import type { Logger } from "@helyx/sdk";
|
|
4
|
+
export interface CoreRetentionRepositories {
|
|
5
|
+
sessions: Pick<InteractionSessionRepository, "deleteExpired"> & Pick<MysqlInteractionSessionRepository, "deleteExpired">;
|
|
6
|
+
rateLimits: Pick<RateLimitRepository, "deleteExpired"> & Pick<MysqlRateLimitRepository, "deleteExpired">;
|
|
7
|
+
commands: Pick<GuildCommandRepository, "deleteExpired"> & Pick<MysqlGuildCommandRepository, "deleteExpired">;
|
|
8
|
+
verificationAudit?: Pick<AuditRepository, "deleteModuleEventsOlderThanMonths">;
|
|
9
|
+
hostedLeaveDeliveries?: Pick<HostedServerSafetyRepository, "deleteTerminalLeaveDeliveriesOlderThanMonths">;
|
|
10
|
+
}
|
|
11
|
+
export interface CoreRetentionCounts {
|
|
12
|
+
interactionSessions: number;
|
|
13
|
+
rateLimitWindows: number;
|
|
14
|
+
verificationAuditEvents: number;
|
|
15
|
+
commandRecords: number;
|
|
16
|
+
hostedLeaveDeliveries: number;
|
|
17
|
+
}
|
|
18
|
+
/** One cleanup pass; callers retain ownership of scheduling and error logging. */
|
|
19
|
+
export declare function cleanupExpiredCoreRecords(repositories: CoreRetentionRepositories, logger: Pick<Logger, "info">): Promise<CoreRetentionCounts>;
|
|
20
|
+
/** Hosted cleanup remains on by default, matching the PostgreSQL runtime. */
|
|
21
|
+
export declare function createPostgresCoreRetentionRepositories(database: DatabasePool, options?: {
|
|
22
|
+
hostedCleanup?: boolean;
|
|
23
|
+
}): CoreRetentionRepositories;
|
|
24
|
+
/** Ordinary self-host cleanup needs only the selected MySQL-compatible DB. */
|
|
25
|
+
export declare function createMysqlCoreRetentionRepositories(database: MysqlPool): Promise<CoreRetentionRepositories>;
|
|
26
|
+
//# sourceMappingURL=core-retention.d.ts.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { AuditRepository, GuildCommandRepository, HostedServerSafetyRepository, InteractionSessionRepository, RateLimitRepository, } from "@helyx/database";
|
|
2
|
+
/** One cleanup pass; callers retain ownership of scheduling and error logging. */
|
|
3
|
+
export async function cleanupExpiredCoreRecords(repositories, logger) {
|
|
4
|
+
const [sessions, rateLimits, verificationAudit, commandRecords, hostedLeaves,] = await Promise.all([
|
|
5
|
+
repositories.sessions.deleteExpired(),
|
|
6
|
+
repositories.rateLimits.deleteExpired(),
|
|
7
|
+
repositories.verificationAudit?.deleteModuleEventsOlderThanMonths("helyx.verification", 12) ?? 0,
|
|
8
|
+
repositories.commands.deleteExpired(12),
|
|
9
|
+
repositories.hostedLeaveDeliveries?.deleteTerminalLeaveDeliveriesOlderThanMonths(24) ?? 0,
|
|
10
|
+
]);
|
|
11
|
+
const counts = {
|
|
12
|
+
interactionSessions: sessions,
|
|
13
|
+
rateLimitWindows: rateLimits,
|
|
14
|
+
verificationAuditEvents: verificationAudit,
|
|
15
|
+
commandRecords: commandRecords.history +
|
|
16
|
+
commandRecords.idempotencyKeys +
|
|
17
|
+
commandRecords.creationLedger +
|
|
18
|
+
commandRecords.requests,
|
|
19
|
+
hostedLeaveDeliveries: hostedLeaves,
|
|
20
|
+
};
|
|
21
|
+
if (Object.values(counts).some((count) => count > 0)) {
|
|
22
|
+
logger.info({ event: "database.retention_cleaned", ...counts }, "Expired core records removed");
|
|
23
|
+
}
|
|
24
|
+
return counts;
|
|
25
|
+
}
|
|
26
|
+
/** Hosted cleanup remains on by default, matching the PostgreSQL runtime. */
|
|
27
|
+
export function createPostgresCoreRetentionRepositories(database, options = {}) {
|
|
28
|
+
return {
|
|
29
|
+
sessions: new InteractionSessionRepository(database),
|
|
30
|
+
rateLimits: new RateLimitRepository(database),
|
|
31
|
+
commands: new GuildCommandRepository(database),
|
|
32
|
+
...(options.hostedCleanup === false
|
|
33
|
+
? {}
|
|
34
|
+
: {
|
|
35
|
+
verificationAudit: new AuditRepository(database),
|
|
36
|
+
hostedLeaveDeliveries: new HostedServerSafetyRepository(database),
|
|
37
|
+
}),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/** Ordinary self-host cleanup needs only the selected MySQL-compatible DB. */
|
|
41
|
+
export async function createMysqlCoreRetentionRepositories(database) {
|
|
42
|
+
const { InteractionSessionRepository: MysqlSessions, RateLimitRepository: MysqlRateLimits, GuildCommandRepository: MysqlCommands, } = await import("@helyx/database-mysql");
|
|
43
|
+
return {
|
|
44
|
+
sessions: new MysqlSessions(database),
|
|
45
|
+
rateLimits: new MysqlRateLimits(database),
|
|
46
|
+
commands: new MysqlCommands(database),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=core-retention.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type CreatorGuildJoinService, type ModuleDefinition, type ServiceAccess } from "@helyx/sdk";
|
|
2
|
+
import { type Client } from "discord.js";
|
|
3
|
+
import type { CreatorInviteRepository } from "@helyx/database";
|
|
4
|
+
/** The only onboarding boundary which can add a member. Never supplies roles or other admission overrides. */
|
|
5
|
+
export declare class DiscordCreatorGuildJoinService implements CreatorGuildJoinService {
|
|
6
|
+
#private;
|
|
7
|
+
private readonly client;
|
|
8
|
+
private readonly services;
|
|
9
|
+
private readonly modules;
|
|
10
|
+
private readonly repository;
|
|
11
|
+
private readonly credentials;
|
|
12
|
+
constructor(client: Client, services: ServiceAccess, modules: readonly ModuleDefinition[], repository: CreatorInviteRepository, credentials: (input: Parameters<CreatorGuildJoinService["join"]>[0]) => Promise<{
|
|
13
|
+
accessToken: string;
|
|
14
|
+
applicationId: string;
|
|
15
|
+
}>);
|
|
16
|
+
inspect(input: {
|
|
17
|
+
guildId: string;
|
|
18
|
+
memberUserId?: string;
|
|
19
|
+
}): ReturnType<CreatorGuildJoinService["inspect"]>;
|
|
20
|
+
join(input: Parameters<CreatorGuildJoinService["join"]>[0]): ReturnType<CreatorGuildJoinService["join"]>;
|
|
21
|
+
private logJoined;
|
|
22
|
+
private enabled;
|
|
23
|
+
private readiness;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=creator-guild-join-service.d.ts.map
|