From b45535f4a38860dba9207b8ffbbc736e7804f26f Mon Sep 17 00:00:00 2001 From: shay <43248357+shayypy@users.noreply.github.com> Date: Mon, 19 Jun 2023 15:36:47 -0500 Subject: [PATCH 1/3] Load messages from Discord with webhook URL Closes #68 --- modules/editor/EditorManager.ts | 39 +++++++++ .../LoadClearMessageConfirmationModal.tsx | 81 +++++++++++++++++++ modules/editor/message/MessageEditor.tsx | 28 ++++++- 3 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 modules/editor/message/LoadClearMessageConfirmationModal.tsx diff --git a/modules/editor/EditorManager.ts b/modules/editor/EditorManager.ts index 9df1535b..b0f7a076 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 { MessageData } from "../message/state/data/MessageData" import { MessageModel } from "../message/state/models/MessageModel" import { WebhookModel } from "../webhook/WebhookModel" @@ -23,6 +24,44 @@ export const EditorManager = types self.messages.push(MessageModel.create()) }, + async getMessage(reference: string) { + for (const target of self.targets) { + const headers: Record = { + "Accept": "application/json", + "Accept-Language": "en", + } + + /* eslint-disable no-await-in-loop */ + + const [, url] = await target.getRoute(reference) + const response = await fetch(url, { method: "GET", headers }) + const data = await response.json() + + if (response.headers.get("X-RateLimit-Remaining") === "0") { + const retryAfter = + Number(response.headers.get("X-RateLimit-Reset-After") ?? 2) * 1000 + + console.log( + "Rate limited: delaying next request by", + retryAfter, + "milliseconds", + ) + + await delay(retryAfter) + } + + /* eslint-enable no-await-in-loop */ + + console.log("Reference fetched", data) + + if (response.ok) { + return data as MessageData + } + } + + return null + }, + async save() { for (const target of self.targets) { for (const message of self.messages) { diff --git a/modules/editor/message/LoadClearMessageConfirmationModal.tsx b/modules/editor/message/LoadClearMessageConfirmationModal.tsx new file mode 100644 index 00000000..66d1c0c2 --- /dev/null +++ b/modules/editor/message/LoadClearMessageConfirmationModal.tsx @@ -0,0 +1,81 @@ +import React, { useState } from "react" +import { PrimaryButton } from "../../../common/input/button/PrimaryButton" +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 { Markdown } from "../../markdown/Markdown" +import { messageOf } from "../../message/helpers/messageOf" +import type { MessageLike } from "../../message/state/models/MessageModel" +import type { EditorManagerLike } from "../EditorManager" +import { InputError } from "../../../common/input/error/InputError" + +export type LoadClearMessageConfirmationModalProps = { + editorManager: EditorManagerLike + message: MessageLike +} + +export function LoadClearMessageConfirmationModal( + props: LoadClearMessageConfirmationModalProps, +) { + const { editorManager, message } = props + + const modal = useRequiredContext(ModalContext) + + return ( + + + Clear & Load Message + modal.dismiss()} + /> + + + + + + modal.dismiss()}> + Cancel + + { + let data + try { + data = await editorManager.getMessage(message.reference) + } catch { + // Handle later + } + if (!data) { + return + } + + const newMessage = messageOf(data) + newMessage.reference = message.reference + + const index = editorManager.messages.indexOf(message) + const messages = [...editorManager.messages] + messages.splice(index, 1, newMessage as MessageLike) + editorManager.set("messages", messages) + + modal.dismiss() + }} + > + Load + + + + ) +} diff --git a/modules/editor/message/MessageEditor.tsx b/modules/editor/message/MessageEditor.tsx index 2ba5a61c..e3091588 100644 --- a/modules/editor/message/MessageEditor.tsx +++ b/modules/editor/message/MessageEditor.tsx @@ -18,6 +18,7 @@ import type { MessageLike } from "../../message/state/models/MessageModel" import type { DataEditorModalProps } from "../data/DataEditorModal" import { EditorManagerContext } from "../EditorManagerContext" import { EmbedEditor } from "./EmbedEditor" +import { LoadClearMessageConfirmationModal } from "./LoadClearMessageConfirmationModal" import { PrimaryContentEditor } from "./PrimaryContentEditor" const DataEditorModal = dynamic(async () => @@ -53,6 +54,16 @@ export function MessageEditor(props: MessageEditorProps) { render: () => , }) + const spawnLoadClearMessageModal = () => + modalManager.spawn({ + render: () => ( + + ), + }) + return useObserver(() => ( @@ -94,13 +105,24 @@ export function MessageEditor(props: MessageEditorProps) { placeholder="https://discord.com/channels/..." error={form.field("reference").error} {...form.field("reference").inputProps} - /> + > + { + spawnLoadClearMessageModal() + }} + > + Load + + From 993add707702382ac7de76af8269f3a5c1f8e89b Mon Sep 17 00:00:00 2001 From: shay <43248357+shayypy@users.noreply.github.com> Date: Mon, 19 Jun 2023 15:36:59 -0500 Subject: [PATCH 2/3] Visible error for failed message load --- .../editor/message/LoadClearMessageConfirmationModal.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/editor/message/LoadClearMessageConfirmationModal.tsx b/modules/editor/message/LoadClearMessageConfirmationModal.tsx index 66d1c0c2..6886e4d0 100644 --- a/modules/editor/message/LoadClearMessageConfirmationModal.tsx +++ b/modules/editor/message/LoadClearMessageConfirmationModal.tsx @@ -28,6 +28,8 @@ export function LoadClearMessageConfirmationModal( const modal = useRequiredContext(ModalContext) + const [error, setError] = useState(undefined); + return ( @@ -45,6 +47,7 @@ export function LoadClearMessageConfirmationModal( " Are you sure you want to continue? This action cannot be reverted." } /> + modal.dismiss()}> @@ -59,6 +62,9 @@ export function LoadClearMessageConfirmationModal( // Handle later } if (!data) { + setError( + "The message link could not be loaded. Make sure a correct webhook URL is provided.", + ); return } From fe55d2090a7e682a21122a85b1e5ac465edf2e2a Mon Sep 17 00:00:00 2001 From: shay <43248357+shayypy@users.noreply.github.com> Date: Mon, 19 Jun 2023 15:37:23 -0500 Subject: [PATCH 3/3] Format --- modules/editor/message/LoadClearMessageConfirmationModal.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/editor/message/LoadClearMessageConfirmationModal.tsx b/modules/editor/message/LoadClearMessageConfirmationModal.tsx index 6886e4d0..174f9dc2 100644 --- a/modules/editor/message/LoadClearMessageConfirmationModal.tsx +++ b/modules/editor/message/LoadClearMessageConfirmationModal.tsx @@ -28,7 +28,7 @@ export function LoadClearMessageConfirmationModal( const modal = useRequiredContext(ModalContext) - const [error, setError] = useState(undefined); + const [error, setError] = useState(undefined) return ( @@ -64,7 +64,7 @@ export function LoadClearMessageConfirmationModal( if (!data) { setError( "The message link could not be loaded. Make sure a correct webhook URL is provided.", - ); + ) return }