diff --git a/modules/editor/EditorManager.ts b/modules/editor/EditorManager.ts index b0f7a076..3ed91f18 100644 --- a/modules/editor/EditorManager.ts +++ b/modules/editor/EditorManager.ts @@ -2,6 +2,7 @@ import { Instance, SnapshotOrInstance, types } from "mobx-state-tree" import { delay } from "../../common/state/delay" +import type { DiscordError } from "../../types/DiscordError" import type { MessageData } from "../message/state/data/MessageData" import { MessageModel } from "../message/state/models/MessageModel" import { WebhookModel } from "../webhook/WebhookModel" @@ -63,6 +64,7 @@ export const EditorManager = types }, async save() { + const errors: DiscordError[] = [] for (const target of self.targets) { for (const message of self.messages) { const headers: Record = { @@ -98,10 +100,17 @@ export const EditorManager = types /* eslint-enable no-await-in-loop */ + if (!response.ok) { + errors.push(data as DiscordError) + } + console.log("Target executed", data) } } + if (errors.length > 0) { + throw new Error(JSON.stringify(errors)) + } return null }, diff --git a/modules/editor/webhook/DiscordErrorsModal.tsx b/modules/editor/webhook/DiscordErrorsModal.tsx new file mode 100644 index 00000000..c96eca89 --- /dev/null +++ b/modules/editor/webhook/DiscordErrorsModal.tsx @@ -0,0 +1,76 @@ +import React from "react" +import { SecondaryButton } from "../../../common/input/button/SecondaryButton" +import { ModalAction } from "../../../common/modal/layout/ModalAction" +import { ModalBody } from "../../../common/modal/layout/ModalBody" +import { ModalContainer } from "../../../common/modal/layout/ModalContainer" +import { ModalFooter } from "../../../common/modal/layout/ModalFooter" +import { ModalHeader } from "../../../common/modal/layout/ModalHeader" +import { ModalTitle } from "../../../common/modal/layout/ModalTitle" +import { ModalContext } from "../../../common/modal/ModalContext" +import { useRequiredContext } from "../../../common/state/useRequiredContext" +import { remove } from "../../../icons/remove" +import type { CodedError, DiscordError } from "../../../types/DiscordError" +import { Markdown } from "../../markdown/Markdown" + +export type DiscordErrorsModalProps = { + errors: DiscordError[] +} + +export function DiscordErrorsModal(props: DiscordErrorsModalProps) { + const { errors } = props + + const modal = useRequiredContext(ModalContext) + + const flattened = errors.map(discordError => { + const flattenErrorObject = (d: DiscordError["errors"], key?: string) => { + const items: string[][] = [] + for (const [k, v] of Object.entries(d!)) { + const newKey = key ? `${key}.${k}` : k + + if (typeof v === "object" && !Array.isArray(v) && v != null) { + // eslint-disable-next-line no-underscore-dangle + const codedErrors = (v as { _errors?: CodedError[] })._errors + if (!codedErrors) { + items.push( + ...flattenErrorObject(v as DiscordError["errors"], newKey), + ) + } else { + items.push([newKey, codedErrors.map(e => e.message).join(", ")]) + } + } else { + items.push([newKey, String(v)]) + } + } + + return items + } + if (discordError.errors) { + const items = flattenErrorObject(discordError.errors) + return items.map(([k, v]) => `In \`${k}\`: ${v}`) + } + return [discordError.message] + })[0] + + return ( + + + Discord Error + modal.dismiss()} + /> + + + + + + modal.dismiss()}>Close + + + ) +} diff --git a/modules/editor/webhook/WebhookControls.tsx b/modules/editor/webhook/WebhookControls.tsx index e71f0ef7..f124119a 100644 --- a/modules/editor/webhook/WebhookControls.tsx +++ b/modules/editor/webhook/WebhookControls.tsx @@ -12,6 +12,7 @@ import { useRequiredContext } from "../../../common/state/useRequiredContext" import { remove } from "../../../icons/remove" import type { EditorFormState } from "../../message/state/editorForm" import { EditorManagerContext } from "../EditorManagerContext" +import { DiscordErrorsModal } from "./DiscordErrorsModal" import { NetworkErrorModal } from "./NetworkErrorModal" const InputAction = styled(IconButton)` @@ -40,10 +41,18 @@ export function WebhookControls(props: WebhookControlsProps) { try { await form.save() - } catch { - modalManager.spawn({ - render: () => , - }) + } catch (error) { + if (error instanceof TypeError) { + modalManager.spawn({ + render: () => , + }) + } else { + modalManager.spawn({ + render: () => ( + + ), + }) + } } setSubmitting(false) diff --git a/types/DiscordError.ts b/types/DiscordError.ts new file mode 100644 index 00000000..5b07dd98 --- /dev/null +++ b/types/DiscordError.ts @@ -0,0 +1,11 @@ +// >= v8 +export type DiscordError = { + code: number + message: string + errors?: Record +} + +export type CodedError = { + code: string + message: string +}