From ec5d403f5b2b874c6ef87b2c009549ac7b3c79e4 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 22 Apr 2026 19:37:45 +0100 Subject: [PATCH] refactor(discord): share channel action param parsing --- .../src/actions/handle-action.guild-admin.ts | 62 +++------------- .../discord/src/actions/handle-action.ts | 2 - .../discord/src/actions/runtime.guild.ts | 72 +++---------------- .../discord/src/actions/runtime.shared.ts | 57 ++++++++++++++- 4 files changed, 76 insertions(+), 117 deletions(-) diff --git a/extensions/discord/src/actions/handle-action.guild-admin.ts b/extensions/discord/src/actions/handle-action.guild-admin.ts index 867b20a5cbd..338bc76ae47 100644 --- a/extensions/discord/src/actions/handle-action.guild-admin.ts +++ b/extensions/discord/src/actions/handle-action.guild-admin.ts @@ -1,6 +1,5 @@ import type { AgentToolResult } from "@mariozechner/pi-agent-core"; import { - parseAvailableTags, readNumberParam, readStringArrayParam, readStringParam, @@ -12,6 +11,11 @@ import { isDiscordModerationAction, readDiscordModerationCommand, } from "./runtime.moderation-shared.js"; +import { + readDiscordChannelCreateParams, + readDiscordChannelEditParams, + readDiscordChannelMoveParams, +} from "./runtime.shared.js"; type Ctx = Pick< ChannelMessageActionContext, @@ -21,9 +25,8 @@ type Ctx = Pick< export async function tryHandleDiscordMessageActionGuildAdmin(params: { ctx: Ctx; resolveChannelId: () => string; - readParentIdParam: (params: Record) => string | null | undefined; }): Promise | undefined> { - const { ctx, resolveChannelId, readParentIdParam } = params; + const { ctx, resolveChannelId } = params; const { action, params: actionParams, cfg } = ctx; const accountId = ctx.accountId ?? readStringParam(actionParams, "accountId"); @@ -154,25 +157,11 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: { const guildId = readStringParam(actionParams, "guildId", { required: true, }); - const name = readStringParam(actionParams, "name", { required: true }); - const type = readNumberParam(actionParams, "type", { integer: true }); - const parentId = readParentIdParam(actionParams); - const topic = readStringParam(actionParams, "topic"); - const position = readNumberParam(actionParams, "position", { - integer: true, - }); - const nsfw = typeof actionParams.nsfw === "boolean" ? actionParams.nsfw : undefined; return await handleDiscordAction( { action: "channelCreate", accountId: accountId ?? undefined, - guildId, - name, - type: type ?? undefined, - parentId: parentId ?? undefined, - topic: topic ?? undefined, - position: position ?? undefined, - nsfw, + ...readDiscordChannelCreateParams({ ...actionParams, guildId }), }, cfg, ); @@ -182,37 +171,11 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: { const channelId = readStringParam(actionParams, "channelId", { required: true, }); - const name = readStringParam(actionParams, "name"); - const topic = readStringParam(actionParams, "topic"); - const position = readNumberParam(actionParams, "position", { - integer: true, - }); - const parentId = readParentIdParam(actionParams); - const nsfw = typeof actionParams.nsfw === "boolean" ? actionParams.nsfw : undefined; - const rateLimitPerUser = readNumberParam(actionParams, "rateLimitPerUser", { - integer: true, - }); - const archived = typeof actionParams.archived === "boolean" ? actionParams.archived : undefined; - const locked = typeof actionParams.locked === "boolean" ? actionParams.locked : undefined; - const autoArchiveDuration = readNumberParam(actionParams, "autoArchiveDuration", { - integer: true, - }); - const availableTags = parseAvailableTags(actionParams.availableTags); return await handleDiscordAction( { action: "channelEdit", accountId: accountId ?? undefined, - channelId, - name: name ?? undefined, - topic: topic ?? undefined, - position: position ?? undefined, - parentId: parentId === undefined ? undefined : parentId, - nsfw, - rateLimitPerUser: rateLimitPerUser ?? undefined, - archived, - locked, - autoArchiveDuration: autoArchiveDuration ?? undefined, - availableTags, + ...readDiscordChannelEditParams({ ...actionParams, channelId }), }, cfg, ); @@ -235,18 +198,11 @@ export async function tryHandleDiscordMessageActionGuildAdmin(params: { const channelId = readStringParam(actionParams, "channelId", { required: true, }); - const parentId = readParentIdParam(actionParams); - const position = readNumberParam(actionParams, "position", { - integer: true, - }); return await handleDiscordAction( { action: "channelMove", accountId: accountId ?? undefined, - guildId, - channelId, - parentId: parentId === undefined ? undefined : parentId, - position: position ?? undefined, + ...readDiscordChannelMoveParams({ ...actionParams, guildId, channelId }), }, cfg, ); diff --git a/extensions/discord/src/actions/handle-action.ts b/extensions/discord/src/actions/handle-action.ts index 18fb49b6735..fa79510eaa1 100644 --- a/extensions/discord/src/actions/handle-action.ts +++ b/extensions/discord/src/actions/handle-action.ts @@ -19,7 +19,6 @@ import { } from "../shared-interactive.js"; import { resolveDiscordChannelId } from "../targets.js"; import { tryHandleDiscordMessageActionGuildAdmin } from "./handle-action.guild-admin.js"; -import { readDiscordParentIdParam } from "./runtime.shared.js"; const providerId = "discord"; @@ -300,7 +299,6 @@ export async function handleDiscordMessageAction( const adminResult = await tryHandleDiscordMessageActionGuildAdmin({ ctx, resolveChannelId, - readParentIdParam: readDiscordParentIdParam, }); if (adminResult !== undefined) { return adminResult; diff --git a/extensions/discord/src/actions/runtime.guild.ts b/extensions/discord/src/actions/runtime.guild.ts index 2ea98fdfcf7..53fe666f9ce 100644 --- a/extensions/discord/src/actions/runtime.guild.ts +++ b/extensions/discord/src/actions/runtime.guild.ts @@ -4,7 +4,6 @@ import { getPresence } from "../monitor/presence-cache.js"; import { type ActionGate, jsonResult, - parseAvailableTags, readNumberParam, readStringArrayParam, readStringParam, @@ -32,7 +31,11 @@ import { uploadStickerDiscord, resolveEventCoverImage, } from "../send.js"; -import { readDiscordParentIdParam } from "./runtime.shared.js"; +import { + readDiscordChannelCreateParams, + readDiscordChannelEditParams, + readDiscordChannelMoveParams, +} from "./runtime.shared.js"; export const discordGuildActionRuntime = { addRoleDiscord, @@ -326,23 +329,8 @@ export async function handleDiscordGuildAction( if (!isActionEnabled("channels")) { throw new Error("Discord channel management is disabled."); } - const guildId = readStringParam(params, "guildId", { required: true }); - const name = readStringParam(params, "name", { required: true }); - const type = readNumberParam(params, "type", { integer: true }); - const parentId = readDiscordParentIdParam(params); - const topic = readStringParam(params, "topic"); - const position = readNumberParam(params, "position", { integer: true }); - const nsfw = params.nsfw as boolean | undefined; const channel = await discordGuildActionRuntime.createChannelDiscord( - { - guildId, - name, - type: type ?? undefined, - parentId: parentId ?? undefined, - topic: topic ?? undefined, - position: position ?? undefined, - nsfw, - }, + readDiscordChannelCreateParams(params), withOpts(), ); return jsonResult({ ok: true, channel }); @@ -351,37 +339,10 @@ export async function handleDiscordGuildAction( if (!isActionEnabled("channels")) { throw new Error("Discord channel management is disabled."); } - const channelId = readStringParam(params, "channelId", { - required: true, - }); - const name = readStringParam(params, "name"); - const topic = readStringParam(params, "topic"); - const position = readNumberParam(params, "position", { integer: true }); - const parentId = readDiscordParentIdParam(params); - const nsfw = params.nsfw as boolean | undefined; - const rateLimitPerUser = readNumberParam(params, "rateLimitPerUser", { - integer: true, - }); - const archived = typeof params.archived === "boolean" ? params.archived : undefined; - const locked = typeof params.locked === "boolean" ? params.locked : undefined; - const autoArchiveDuration = readNumberParam(params, "autoArchiveDuration", { - integer: true, - }); - const availableTags = parseAvailableTags(params.availableTags); - const editPayload = { - channelId, - name: name ?? undefined, - topic: topic ?? undefined, - position: position ?? undefined, - parentId, - nsfw, - rateLimitPerUser: rateLimitPerUser ?? undefined, - archived, - locked, - autoArchiveDuration: autoArchiveDuration ?? undefined, - availableTags, - }; - const channel = await discordGuildActionRuntime.editChannelDiscord(editPayload, withOpts()); + const channel = await discordGuildActionRuntime.editChannelDiscord( + readDiscordChannelEditParams(params), + withOpts(), + ); return jsonResult({ ok: true, channel }); } case "channelDelete": { @@ -398,19 +359,8 @@ export async function handleDiscordGuildAction( if (!isActionEnabled("channels")) { throw new Error("Discord channel management is disabled."); } - const guildId = readStringParam(params, "guildId", { required: true }); - const channelId = readStringParam(params, "channelId", { - required: true, - }); - const parentId = readDiscordParentIdParam(params); - const position = readNumberParam(params, "position", { integer: true }); await discordGuildActionRuntime.moveChannelDiscord( - { - guildId, - channelId, - parentId, - position: position ?? undefined, - }, + readDiscordChannelMoveParams(params), withOpts(), ); return jsonResult({ ok: true }); diff --git a/extensions/discord/src/actions/runtime.shared.ts b/extensions/discord/src/actions/runtime.shared.ts index c597fa38c4f..12e195d6001 100644 --- a/extensions/discord/src/actions/runtime.shared.ts +++ b/extensions/discord/src/actions/runtime.shared.ts @@ -1,4 +1,9 @@ -import { readStringParam } from "../runtime-api.js"; +import { parseAvailableTags, readNumberParam, readStringParam } from "../runtime-api.js"; +import type { + DiscordChannelCreate, + DiscordChannelEdit, + DiscordChannelMove, +} from "../send.types.js"; export function readDiscordParentIdParam( params: Record, @@ -11,3 +16,53 @@ export function readDiscordParentIdParam( } return readStringParam(params, "parentId"); } + +function readDiscordBooleanParam( + params: Record, + key: string, +): boolean | undefined { + return typeof params[key] === "boolean" ? params[key] : undefined; +} + +export function readDiscordChannelCreateParams( + params: Record, +): DiscordChannelCreate { + const parentId = readDiscordParentIdParam(params); + return { + guildId: readStringParam(params, "guildId", { required: true }), + name: readStringParam(params, "name", { required: true }), + type: readNumberParam(params, "type", { integer: true }) ?? undefined, + parentId: parentId ?? undefined, + topic: readStringParam(params, "topic") ?? undefined, + position: readNumberParam(params, "position", { integer: true }) ?? undefined, + nsfw: readDiscordBooleanParam(params, "nsfw"), + }; +} + +export function readDiscordChannelEditParams(params: Record): DiscordChannelEdit { + const parentId = readDiscordParentIdParam(params); + return { + channelId: readStringParam(params, "channelId", { required: true }), + name: readStringParam(params, "name") ?? undefined, + topic: readStringParam(params, "topic") ?? undefined, + position: readNumberParam(params, "position", { integer: true }) ?? undefined, + parentId: parentId === undefined ? undefined : parentId, + nsfw: readDiscordBooleanParam(params, "nsfw"), + rateLimitPerUser: readNumberParam(params, "rateLimitPerUser", { integer: true }) ?? undefined, + archived: readDiscordBooleanParam(params, "archived"), + locked: readDiscordBooleanParam(params, "locked"), + autoArchiveDuration: + readNumberParam(params, "autoArchiveDuration", { integer: true }) ?? undefined, + availableTags: parseAvailableTags(params.availableTags), + }; +} + +export function readDiscordChannelMoveParams(params: Record): DiscordChannelMove { + const parentId = readDiscordParentIdParam(params); + return { + guildId: readStringParam(params, "guildId", { required: true }), + channelId: readStringParam(params, "channelId", { required: true }), + parentId: parentId === undefined ? undefined : parentId, + position: readNumberParam(params, "position", { integer: true }) ?? undefined, + }; +}