import { DISCORD_GUILD_SCHEMA, DISCORD_PROVIDER_GUILD_SCHEMA, DISCORD_PROVIDER_USER_SCHEMA, DISCORD_USER_SCHEMA, toDiscordGuild, toDiscordUser, } from "@automate.ax/integration-contracts/discord" import * as z from "zod" import { defineAction } from "../../../automation/actions" import { getDiscordApi } from "../lib/api" /** Retrieves the connected Discord bot user. */ export const getCurrentDiscordBot = defineAction("Get current Discord bot") .describe( "Retrieves the user identity represented by the connected bot token.", ) .account("discord") .input(z.object({})) .output(DISCORD_USER_SCHEMA) .retry({ replaySafety: "safe" }) .handler(async ({ account }) => toDiscordUser( await getDiscordApi(account.secret).request("users/@me", { responseSchema: DISCORD_PROVIDER_USER_SCHEMA, }), ), ) /** Lists Discord servers where the connected bot is installed. */ export const listDiscordGuilds = defineAction("List Discord servers") .describe("Lists servers where the connected bot is currently installed.") .account("discord") .input( z .object({ after: z.string().regex(/^\d+$/).optional(), before: z.string().regex(/^\d+$/).optional(), limit: z.number().int().min(1).max(200).prefault(100), }) .refine(({ after, before }) => !(after && before), { message: "Use either after or before, not both.", }), ) .output(DISCORD_GUILD_SCHEMA.array()) .retry({ replaySafety: "safe" }) .handler(async ({ account, input }) => ( await getDiscordApi(account.secret).request("users/@me/guilds", { query: input, responseSchema: DISCORD_PROVIDER_GUILD_SCHEMA.array(), }) ).map(toDiscordGuild), ) /** Retrieves one Discord server visible to the connected bot. */ export const getDiscordGuild = defineAction("Get Discord server") .describe("Retrieves one server by its Discord snowflake ID.") .account("discord") .input( z.object({ guildId: z.string().regex(/^\d+$/), withCounts: z.boolean().prefault(false), }), ) .output(DISCORD_GUILD_SCHEMA) .retry({ replaySafety: "safe" }) .handler(async ({ account, input }) => toDiscordGuild( await getDiscordApi(account.secret).request(`guilds/${input.guildId}`, { query: { with_counts: input.withCounts }, responseSchema: DISCORD_PROVIDER_GUILD_SCHEMA, }), ), ) /** Updates a Discord server's core settings. */ export const updateDiscordGuild = defineAction("Update Discord server") .describe("Updates a server's name and common moderation settings.") .account("discord") .input( z.object({ afkChannelId: z.string().regex(/^\d+$/).nullable().optional(), afkTimeout: z.enum(["60", "300", "900", "1800", "3600"]).optional(), defaultMessageNotifications: z.enum(["all", "mentions"]).optional(), explicitContentFilter: z.enum(["disabled", "members", "all"]).optional(), guildId: z.string().regex(/^\d+$/), name: z.string().trim().min(2).max(100).optional(), reason: z.string().max(512).optional(), systemChannelId: z.string().regex(/^\d+$/).nullable().optional(), verificationLevel: z .enum(["none", "low", "medium", "high", "highest"]) .optional(), }), ) .output(DISCORD_GUILD_SCHEMA) .retry({ replaySafety: "safe" }) .handler(async ({ account, input }) => { const notificationLevels = { all: 0, mentions: 1 } as const const contentFilters = { all: 2, disabled: 0, members: 1 } as const const verificationLevels = { high: 3, highest: 4, low: 1, medium: 2, none: 0, } as const return toDiscordGuild( await getDiscordApi(account.secret).request(`guilds/${input.guildId}`, { body: { afk_channel_id: input.afkChannelId, afk_timeout: input.afkTimeout === undefined ? undefined : Number(input.afkTimeout), default_message_notifications: input.defaultMessageNotifications === undefined ? undefined : notificationLevels[input.defaultMessageNotifications], explicit_content_filter: input.explicitContentFilter === undefined ? undefined : contentFilters[input.explicitContentFilter], name: input.name, system_channel_id: input.systemChannelId, verification_level: input.verificationLevel === undefined ? undefined : verificationLevels[input.verificationLevel], }, method: "PATCH", reason: input.reason, responseSchema: DISCORD_PROVIDER_GUILD_SCHEMA, }), ) })