Created
April 26, 2026 19:47
-
-
Save MajorTazer/c1a9397eb3b6e8b58e547b751cd10425 to your computer and use it in GitHub Desktop.
A custom Vencord plugin to split 2000+ character messages into chunks of 2000. Supports code blocks spanning more than 2000 characters.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * Vencord, a Discord client mod | |
| * Copyright (c) 2026 Vendicated and contributors | |
| * SPDX-License-Identifier: GPL-3.0-or-later | |
| */ | |
| import { addMessagePreSendListener, removeMessagePreSendListener } from "@api/MessageEvents"; | |
| import { Devs } from "@utils/constants"; | |
| import definePlugin from "@utils/types"; | |
| import { findByProps } from "@webpack"; | |
| const MAX_CHARS = 2000; | |
| let listener: any; | |
| let MessageActions: any; | |
| function splitMessage(content: string): string[] { | |
| const MAX = Math.floor(MAX_CHARS * (39 / 40)); | |
| content = content.replace(/\t/g, " "); | |
| const chunks: string[] = []; | |
| let current = ""; | |
| const words = content.split(/( |\n)/); | |
| for (const word of words) { | |
| if ((current + word).length > MAX) { | |
| if (current) chunks.push(current); | |
| current = word; | |
| } else { | |
| current += word; | |
| } | |
| } | |
| if (current) chunks.push(current); | |
| let openBlockFence: string | null = null; | |
| for (let j = 0; j < chunks.length; j++) { | |
| if (openBlockFence !== null) { | |
| chunks[j] = openBlockFence + "\n" + chunks[j]; | |
| } | |
| const fences = [...chunks[j].matchAll(/`{3,}[\S]*/gm)]; | |
| let insideBlock = false; | |
| let lastFence: string | null = null; | |
| for (const fence of fences) { | |
| if (!insideBlock) { | |
| insideBlock = true; | |
| lastFence = fence[0]; | |
| } else { | |
| insideBlock = false; | |
| lastFence = null; | |
| } | |
| } | |
| if (insideBlock && j < chunks.length - 1) { | |
| chunks[j] += "\n```"; | |
| openBlockFence = lastFence ?? "```"; | |
| } else { | |
| openBlockFence = null; | |
| } | |
| } | |
| return chunks.filter(c => c.trim()); | |
| } | |
| export default definePlugin({ | |
| name: "SplitLargeMessages", | |
| description: "Splits messages over 2000 characters into multiple messages.", | |
| authors: [Devs.KingWaffleIII], | |
| dependencies: ["MessageEventsAPI"], | |
| start() { | |
| MessageActions = findByProps("sendMessage", "editMessage"); | |
| listener = addMessagePreSendListener((channelId, msg) => { | |
| if (msg.content.length <= MAX_CHARS) return; | |
| const { content } = msg; | |
| msg.content = "\u200b"; | |
| const chunks = splitMessage(content); | |
| setTimeout(async () => { | |
| for (const chunk of chunks) { | |
| await MessageActions.sendMessage( | |
| channelId, | |
| { content: chunk, tts: false, invalidEmojis: [], validNonShortcutEmojis: [] }, | |
| true, | |
| {} | |
| ); | |
| await new Promise(r => setTimeout(r, 1000)); | |
| } | |
| }, 100); | |
| }); | |
| }, | |
| stop() { | |
| removeMessagePreSendListener(listener); | |
| }, | |
| patches: [ | |
| { | |
| find: "nq=2e3,nX=4e3", | |
| replacement: { | |
| match: /nq=2e3,nX=4e3/, | |
| replace: "nq=999999,nX=999999" | |
| } | |
| } | |
| ] | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment