From 98d90756393ccd5708b7ada18ebf67e7775d2f50 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Sat, 31 May 2025 11:56:29 -0400 Subject: [PATCH 1/4] Fix Double Plugins --- src/plugins/moreCommands/index.tsx | 332 ----------------------------- src/plugins/moreKaomoji/index.ts | 216 ------------------- src/plugins/moyai/index.ts | 177 --------------- 3 files changed, 725 deletions(-) delete mode 100644 src/plugins/moreCommands/index.tsx delete mode 100644 src/plugins/moreKaomoji/index.ts delete mode 100644 src/plugins/moyai/index.ts diff --git a/src/plugins/moreCommands/index.tsx b/src/plugins/moreCommands/index.tsx deleted file mode 100644 index c167fe2f..00000000 --- a/src/plugins/moreCommands/index.tsx +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Vendicated, Samu and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . -*/ - -import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, OptionalMessageOption, RequiredMessageOption, sendBotMessage } from "@api/Commands"; -import { Devs } from "@utils/constants"; -import definePlugin from "@utils/types"; - - -function mock(input: string): string { - let output = ""; - for (let i = 0; i < input.length; i++) { - output += i % 2 ? input[i].toUpperCase() : input[i].toLowerCase(); - } - return output; -} - -export default definePlugin({ - name: "MoreCommands", - description: "Echo, Lenny, Mock, and More", - authors: [Devs.Arjix, Devs.echo, Devs.Samu], - commands: [ - { - name: "echo", - description: "Sends a message as Clyde (locally)", - options: [OptionalMessageOption], - inputType: ApplicationCommandInputType.BOT, - execute: (opts, ctx) => { - const content = findOption(opts, "message", ""); - - sendBotMessage(ctx.channel.id, { content }); - }, - }, - { - name: "lenny", - description: "Sends a lenny face", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " ( ͡° ͜ʖ ͡°)" - }), - }, - { - name: "mock", - description: "mOcK PeOpLe", - options: [RequiredMessageOption], - execute: opts => ({ - content: mock(findOption(opts, "message", "")) - }), - }, - { - name: "reverse", - description: "Reverses the input message", - options: [RequiredMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "").split("").reverse().join("") - }), - }, - { - name: "uppercase", - description: "Converts the message to uppercase", - options: [RequiredMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "").toUpperCase() - }), - }, - { - name: "lowercase", - description: "Converts the message to lowercase", - options: [RequiredMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "").toLowerCase() - }), - }, - { - name: "wordcount", - description: "Counts the number of words in a message", - options: [RequiredMessageOption], - inputType: ApplicationCommandInputType.BOT, - execute: (opts, ctx) => { - const message = findOption(opts, "message", ""); - const wordCount = message.trim().split(/\s+/).length; - sendBotMessage(ctx.channel.id, { - content: `The message contains ${wordCount} words.` - }); - }, - }, - { - name: "ping", - description: "Pings the bot to check if it's responding", - options: [], - inputType: ApplicationCommandInputType.BOT, - execute: (opts, ctx) => { - sendBotMessage(ctx.channel.id, { - content: "Pong!" - }); - }, - }, - { - name: "rolldice", - description: "Roll a die with the specified number of sides", - options: [RequiredMessageOption], - execute: opts => { - const sides = parseInt(findOption(opts, "message", "6")); - const roll = Math.floor(Math.random() * sides) + 1; - return { - content: `You rolled a ${roll}!` - }; - }, - }, - { - name: "flipcoin", - description: "Flips a coin and returns heads or tails", - options: [], - execute: (opts, ctx) => { - const flip = Math.random() < 0.5 ? "Heads" : "Tails"; - return { - content: `The coin landed on: ${flip}` - }; - }, - }, - { - name: "ask", - description: "Ask a yes/no question and get an answer", - options: [RequiredMessageOption], - execute: opts => { - const question = findOption(opts, "message", ""); - const responses = [ - "Yes", "No", "Maybe", "Ask again later", "Definitely not", "It is certain" - ]; - const response = responses[Math.floor(Math.random() * responses.length)]; - return { - content: `${question} - ${response}` - }; - }, - }, - { - name: "randomcat", - description: "Get a random cat picture", - options: [], - execute: (opts, ctx) => { - return (async () => { - try { - const response = await fetch("https://api.thecatapi.com/v1/images/search"); - if (!response.ok) throw new Error("Failed to fetch cat image"); - const data = await response.json(); - return { - content: data[0].url - }; - } catch (err) { - sendBotMessage(ctx.channel.id, { - content: "Sorry, couldn't fetch a cat picture right now 😿" - }); - } - })(); - }, - }, - { - name: "randomdog", - description: "Get a random ddog picture", - options: [], - execute: (opts, ctx) => { - return (async () => { - try { - const response = await fetch("https://api.thedogapi.com/v1/images/search"); - if (!response.ok) throw new Error("Failed to fetch dog image"); - const data = await response.json(); - return { - content: data[0].url - }; - } catch (err) { - sendBotMessage(ctx.channel.id, { - content: "Sorry, couldn't fetch a cat picture right now 🐶" - }); - } - })(); - }, - }, - { - name: "randomnumber", - description: "Generates a random number between two values", - options: [ - { - name: "min", - description: "Minimum value", - type: ApplicationCommandOptionType.INTEGER, - required: true - }, - { - name: "max", - description: "Maximum value", - type: ApplicationCommandOptionType.INTEGER, - required: true - } - ], - execute: opts => { - const min = parseInt(findOption(opts, "min", "0")); - const max = parseInt(findOption(opts, "max", "100")); - const number = Math.floor(Math.random() * (max - min + 1)) + min; - return { - content: `Random number between ${min} and ${max}: ${number}` - }; - } - }, - { - name: "countdown", - description: "Starts a countdown from a specified number", - options: [ - { - name: "number", - description: "Number to countdown from (max 10)", - type: ApplicationCommandOptionType.INTEGER, - required: true - } - ], - inputType: ApplicationCommandInputType.BOT, - execute: async (opts, ctx) => { - const number = Math.min(parseInt(findOption(opts, "number", "5")), 10); - if (isNaN(number) || number < 1) { - sendBotMessage(ctx.channel.id, { - content: "Please provide a valid number between 1 and 10!" - }); - return; - } - sendBotMessage(ctx.channel.id, { - content: `Starting countdown from ${number}...` - }); - for (let i = number; i >= 0; i--) { - await new Promise(resolve => setTimeout(resolve, 1000)); - sendBotMessage(ctx.channel.id, { - content: i === 0 ? "🎉 Go! 🎉" : `${i}...` - }); - } - }, - }, - { - name: "choose", - description: "Randomly chooses from provided options", - options: [ - { - name: "choices", - description: "Comma-separated list of choices", - type: ApplicationCommandOptionType.STRING, - required: true - } - ], - execute: opts => { - const choices = findOption(opts, "choices", "").split(",").map(c => c.trim()); - const choice = choices[Math.floor(Math.random() * choices.length)]; - return { - content: `I choose: ${choice}` - }; - } - }, - { - name: "systeminfo", - description: "Shows system information", - options: [], - execute: async (opts, ctx) => { - try { - const { userAgent, hardwareConcurrency, onLine, languages } = navigator; - const { width, height, colorDepth } = window.screen; - const { deviceMemory, connection }: { deviceMemory: any, connection: any; } = navigator as any; - const platform = userAgent.includes("Windows") ? "Windows" : - userAgent.includes("Mac") ? "MacOS" : - userAgent.includes("Linux") ? "Linux" : "Unknown"; - const isMobile = /Mobile|Android|iPhone/i.test(userAgent); - const deviceType = isMobile ? "Mobile" : "Desktop"; - const browserInfo = userAgent.match(/(?:chrome|firefox|safari|edge|opr)\/?\s*(\d+)/i)?.[0] || "Unknown"; - const networkInfo = connection ? `${connection.effectiveType || "Unknown"}` : "Unknown"; - const info = [ - `> **Platform**: ${platform}`, - `> **Device Type**: ${deviceType}`, - `> **Browser**: ${browserInfo}`, - `> **CPU Cores**: ${hardwareConcurrency || "N/A"}`, - `> **Memory**: ${deviceMemory ? `${deviceMemory}GB` : "N/A"}`, - `> **Screen**: ${width}x${height} (${colorDepth}bit)`, - `> **Languages**: ${languages?.join(", ")}`, - `> **Network**: ${networkInfo} (${onLine ? "Online" : "Offline"})` - ].join("\n"); - return { content: info }; - } catch (err) { - sendBotMessage(ctx.channel.id, { content: "Failed to fetch system information" }); - } - }, - }, - { - name: "getUptime", - description: "Returns the system uptime", - execute: async (opts, ctx) => { - const uptime = performance.now() / 1000; - const uptimeInfo = `> **System Uptime**: ${Math.floor(uptime / 60)} minutes`; - return { content: uptimeInfo }; - }, - }, - { - name: "getTime", - description: "Returns the current server time", - execute: async (opts, ctx) => { - const currentTime = new Date().toLocaleString(); - return { content: `> **Current Time**: ${currentTime}` }; - }, - }, - { - name: "getLocation", - description: "Returns the user's approximate location based on IP", - execute: async (opts, ctx) => { - try { - const response = await fetch("https://ipapi.co/json/"); - const data = await response.json(); - const locationInfo = `> **Country**: ${data.country_name}\n> **Region**: ${data.region}\n> **City**: ${data.city}`; - return { content: locationInfo }; - } catch (err) { - sendBotMessage(ctx.channel.id, { content: "Failed to fetch location information" }); - } - }, - } - ] -}); diff --git a/src/plugins/moreKaomoji/index.ts b/src/plugins/moreKaomoji/index.ts deleted file mode 100644 index 986b1f33..00000000 --- a/src/plugins/moreKaomoji/index.ts +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . -*/ - -import { findOption, OptionalMessageOption } from "@api/Commands"; -import { Devs, EquicordDevs } from "@utils/constants"; -import definePlugin from "@utils/types"; - -export default definePlugin({ - name: "MoreKaomoji", - description: "Adds more Kaomoji to discord. ヽ(´▽`)/", - authors: [Devs.JacobTm, EquicordDevs.voidbbg], - commands: [ - { - name: "dissatisfaction", - description: " >﹏<", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + " >﹏<", - }), - }, - { - name: "smug", - description: "ಠ_ಠ", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "ಠ_ಠ", - }), - }, - { - name: "happy", - description: "ヽ(´▽`)/", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "ヽ(´▽`)/", - }), - }, - { - name: "crying", - description: "ಥ_ಥ", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "ಥ_ಥ", - }), - }, - { - name: "angry", - description: "ヽ(`Д´)ノ", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "ヽ(`Д´)ノ", - }), - }, - { - name: "anger", - description: "ヽ(o`皿′o)ノ", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "ヽ(o`皿′o)ノ", - }), - }, - { - name: "joy", - description: "<( ̄︶ ̄)>", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "<( ̄︶ ̄)>", - }), - }, - { - name: "blush", - description: "૮ ˶ᵔ ᵕ ᵔ˶ ა", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "૮ ˶ᵔ ᵕ ᵔ˶ ა", - }), - }, - { - name: "confused", - description: "(•ิ_•ิ)?", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "(•ิ_•ิ)?", - }), - }, - { - name: "sleeping", - description: "(ᴗ_ᴗ)", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "(ᴗ_ᴗ)", - }), - }, - { - name: "laughing", - description: "o(≧▽≦)o", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "o(≧▽≦)o", - }), - }, - /* - even more kaomoji - */ - { - name: "giving", - description: "(ノ◕ヮ◕)ノ*:・゚✧", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "(ノ◕ヮ◕)ノ*:・゚✧", - }), - }, - { - name: "peace", - description: "✌(◕‿-)✌", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "✌(◕‿-)✌", - }), - }, - { - name: "ending1", - description: "Ꮺ ָ࣪ ۰ ͙⊹", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "Ꮺ ָ࣪ ۰ ͙⊹", - }), - }, - { - name: "uwu", - description: "(>⩊<)", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "(>⩊<)", - }), - }, - { - name: "comfy", - description: "(─‿‿─)♡", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "(─‿‿─)♡", - }), - }, - { - name: "lovehappy", - description: "(*≧ω≦*)", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "(*≧ω≦*)", - }), - }, - { - name: "loveee", - description: "(⁄ ⁄>⁄ ▽ ⁄<⁄ ⁄)", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "(⁄ ⁄>⁄ ▽ ⁄<⁄ ⁄)", - }), - }, - { - name: "give", - description: "(ノ= ⩊ = )ノ", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "(ノ= ⩊ = )ノ", - }), - }, - { - name: "lovegive", - description: "ღゝ◡╹)ノ♡", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "ღゝ◡╹)ノ♡", - }), - }, - { - name: "music", - description: "( ̄▽ ̄)/♫•¨•.¸¸♪", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "( ̄▽ ̄)/♫•¨•.¸¸♪", - }), - }, - { - name: "stars", - description: ".𖥔 ݁ ˖๋ ࣭ ⭑", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + ".𖥔 ݁ ˖๋ ࣭ ⭑", - }), - }, - { - name: "lovegiving", - description: "⸜(。˃ ᵕ ˂ )⸝♡", - options: [OptionalMessageOption], - execute: opts => ({ - content: findOption(opts, "message", "") + " " + "⸜(。˃ ᵕ ˂ )⸝♡", - }), - } - ] -}); diff --git a/src/plugins/moyai/index.ts b/src/plugins/moyai/index.ts deleted file mode 100644 index 9d095c47..00000000 --- a/src/plugins/moyai/index.ts +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . -*/ - -import { definePluginSettings } from "@api/Settings"; -import { makeRange } from "@components/PluginSettings/components/SettingSliderComponent"; -import { Devs } from "@utils/constants"; -import { sleep } from "@utils/misc"; -import definePlugin, { OptionType } from "@utils/types"; -import { RelationshipStore, SelectedChannelStore, UserStore } from "@webpack/common"; -import { Message, ReactionEmoji } from "discord-types/general"; - -interface IMessageCreate { - type: "MESSAGE_CREATE"; - optimistic: boolean; - isPushNotification: boolean; - channelId: string; - message: Message; -} - -interface IReactionAdd { - type: "MESSAGE_REACTION_ADD"; - optimistic: boolean; - channelId: string; - messageId: string; - messageAuthorId: string; - userId: "195136840355807232"; - emoji: ReactionEmoji; -} - -interface IVoiceChannelEffectSendEvent { - type: string; - emoji?: ReactionEmoji; // Just in case... - channelId: string; - userId: string; - animationType: number; - animationId: number; -} - -const MOYAI = "🗿"; -const MOYAI_URL = - "https://github.com/Equicord/Equibored/raw/main/sounds/moyai/moyai.mp3"; -const MOYAI_URL_HD = - "https://github.com/Equicord/Equibored/raw/main/sounds/moyai/moyai.wav"; - -const settings = definePluginSettings({ - volume: { - description: "Volume of the 🗿🗿🗿", - type: OptionType.SLIDER, - markers: makeRange(0, 1, 0.1), - default: 0.5, - stickToMarkers: false - }, - quality: { - description: "Quality of the 🗿🗿🗿", - type: OptionType.SELECT, - options: [ - { label: "Normal", value: "Normal", default: true }, - { label: "HD", value: "HD" } - ], - }, - triggerWhenUnfocused: { - description: "Trigger the 🗿 even when the window is unfocused", - type: OptionType.BOOLEAN, - default: true - }, - ignoreBots: { - description: "Ignore bots", - type: OptionType.BOOLEAN, - default: true - }, - ignoreBlocked: { - description: "Ignore blocked users", - type: OptionType.BOOLEAN, - default: true - } -}); - -export default definePlugin({ - name: "Moyai", - authors: [Devs.Megu, Devs.Nuckyz], - description: "🗿🗿🗿🗿🗿🗿🗿🗿", - settings, - - flux: { - async MESSAGE_CREATE({ optimistic, type, message, channelId }: IMessageCreate) { - if (optimistic || type !== "MESSAGE_CREATE") return; - if (message.state === "SENDING") return; - if (settings.store.ignoreBots && message.author?.bot) return; - if (settings.store.ignoreBlocked && RelationshipStore.isBlocked(message.author?.id)) return; - if (!message.content) return; - if (channelId !== SelectedChannelStore.getChannelId()) return; - - const moyaiCount = getMoyaiCount(message.content); - - for (let i = 0; i < moyaiCount; i++) { - boom(); - await sleep(300); - } - }, - - MESSAGE_REACTION_ADD({ optimistic, type, channelId, userId, messageAuthorId, emoji }: IReactionAdd) { - if (optimistic || type !== "MESSAGE_REACTION_ADD") return; - if (settings.store.ignoreBots && UserStore.getUser(userId)?.bot) return; - if (settings.store.ignoreBlocked && RelationshipStore.isBlocked(messageAuthorId)) return; - if (channelId !== SelectedChannelStore.getChannelId()) return; - - const name = emoji.name.toLowerCase(); - if (name !== MOYAI && !name.includes("moyai") && !name.includes("moai")) return; - - boom(); - }, - - VOICE_CHANNEL_EFFECT_SEND({ emoji }: IVoiceChannelEffectSendEvent) { - if (!emoji?.name) return; - const name = emoji.name.toLowerCase(); - if (name !== MOYAI && !name.includes("moyai") && !name.includes("moai")) return; - - boom(); - } - } -}); - -function countOccurrences(sourceString: string, subString: string) { - let i = 0; - let lastIdx = 0; - while ((lastIdx = sourceString.indexOf(subString, lastIdx) + 1) !== 0) - i++; - - return i; -} - -function countMatches(sourceString: string, pattern: RegExp) { - if (!pattern.global) - throw new Error("pattern must be global"); - - let i = 0; - while (pattern.test(sourceString)) - i++; - - return i; -} - -const customMoyaiRe = //gi; - -function getMoyaiCount(message: string) { - const count = countOccurrences(message, MOYAI) - + countMatches(message, customMoyaiRe); - - return Math.min(count, 10); -} - -function boom() { - if (!settings.store.triggerWhenUnfocused && !document.hasFocus()) return; - const audioElement = document.createElement("audio"); - - audioElement.src = settings.store.quality === "HD" - ? MOYAI_URL_HD - : MOYAI_URL; - - audioElement.volume = settings.store.volume; - audioElement.play(); -} From dc24a32d6a23ccd639650b6489a13d9ac9e28d0a Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Sat, 31 May 2025 12:07:51 -0400 Subject: [PATCH 2/4] Fix GithubRepos Button Setting Context --- src/api/Settings.ts | 2 +- src/equicordplugins/githubRepos/index.tsx | 2 +- src/plugins/noBlockedMessages/index.ts | 2 +- src/plugins/platformIndicators/index.tsx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/api/Settings.ts b/src/api/Settings.ts index e4dc21c5..adc15401 100644 --- a/src/api/Settings.ts +++ b/src/api/Settings.ts @@ -236,7 +236,7 @@ export function migratePluginSettings(name: string, ...oldNames: string[]) { } } -export function migratePluginSetting(pluginName: string, oldSetting: string, newSetting: string) { +export function migratePluginSetting(pluginName: string, newSetting: string, oldSetting: string) { const settings = SettingsStore.plain.plugins[pluginName]; if (!settings) return; diff --git a/src/equicordplugins/githubRepos/index.tsx b/src/equicordplugins/githubRepos/index.tsx index 65eccb64..9d8595c2 100644 --- a/src/equicordplugins/githubRepos/index.tsx +++ b/src/equicordplugins/githubRepos/index.tsx @@ -30,7 +30,7 @@ export const settings = definePluginSettings({ }, showInMiniProfile: { type: OptionType.BOOLEAN, - description: "Only show a button in the mini profile", + description: "Show full ui in the mini profile instead of just a button", default: true }, }); diff --git a/src/plugins/noBlockedMessages/index.ts b/src/plugins/noBlockedMessages/index.ts index 0d19726c..d4d7b3f9 100644 --- a/src/plugins/noBlockedMessages/index.ts +++ b/src/plugins/noBlockedMessages/index.ts @@ -33,7 +33,7 @@ interface MessageDeleteProps { } // Remove this migration once enough time has passed -migratePluginSetting("NoBlockedMessages", "ignoreBlockedMessages", "ignoreMessages"); +migratePluginSetting("NoBlockedMessages", "ignoreMessages", "ignoreBlockedMessages"); const settings = definePluginSettings({ ignoreMessages: { description: "Completely ignores incoming messages from blocked and ignored (if enabled) users", diff --git a/src/plugins/platformIndicators/index.tsx b/src/plugins/platformIndicators/index.tsx index 2ecae517..afe0ad44 100644 --- a/src/plugins/platformIndicators/index.tsx +++ b/src/plugins/platformIndicators/index.tsx @@ -201,7 +201,7 @@ function toggleMessageDecorators(enabled: boolean) { } } -migratePluginSetting("PlatformIndicators", "badges", "profiles"); +migratePluginSetting("PlatformIndicators", "profiles", "badges"); const settings = definePluginSettings({ list: { type: OptionType.BOOLEAN, From 7a0df3bcf0d47d55959b73eedeefd261dcbf42bb Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Sat, 31 May 2025 22:11:59 -0400 Subject: [PATCH 3/4] MessageFetchTimer --- README.md | 1 + .../messageFetchTimer/index.tsx | 170 ++++++++++++++++++ src/utils/constants.ts | 4 + 3 files changed, 175 insertions(+) create mode 100644 src/equicordplugins/messageFetchTimer/index.tsx diff --git a/README.md b/README.md index 3bfac801..f9f7103e 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,7 @@ You can join our [discord server](https://discord.gg/5Xh2W87egW) for commits, ch - Meow by Samwich - MessageBurst by port - MessageColors by Hen +- MessageFetchTimer by GroupXyz - MessageLinkTooltip by Kyuuhachi - MessageLoggerEnhanced by Aria - MessageTranslate by Samwich diff --git a/src/equicordplugins/messageFetchTimer/index.tsx b/src/equicordplugins/messageFetchTimer/index.tsx new file mode 100644 index 00000000..40a6a7bf --- /dev/null +++ b/src/equicordplugins/messageFetchTimer/index.tsx @@ -0,0 +1,170 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { ChatBarButton, ChatBarButtonFactory } from "@api/ChatButtons"; +import { definePluginSettings } from "@api/Settings"; +import { EquicordDevs } from "@utils/constants"; +import { getCurrentChannel } from "@utils/discord"; +import definePlugin, { OptionType } from "@utils/types"; +import { FluxDispatcher, React } from "@webpack/common"; + +interface FetchTiming { + channelId: string; + startTime: number; + endTime?: number; + duration?: number; + timestamp?: Date; +} + +let currentFetch: FetchTiming | null = null; +let currentChannelId: string | null = null; +const channelTimings: Map = new Map(); + +const settings = definePluginSettings({ + showIcon: { + type: OptionType.BOOLEAN, + description: "Show fetch time icon in message bar", + default: true, + }, + showMs: { + type: OptionType.BOOLEAN, + description: "Show milliseconds in timing", + default: true, + }, + iconColor: { + type: OptionType.STRING, + description: "Icon color (CSS color value)", + default: "#00d166", + } +}); + +const FetchTimeButton: ChatBarButtonFactory = ({ isMainChat }) => { + const { showMs, iconColor } = settings.use(["showMs", "iconColor"]); + + if (!isMainChat || !settings.store.showIcon || !currentChannelId) { + return null; + } + + const channelData = channelTimings.get(currentChannelId); + if (!channelData) { + return null; + } + + const { time, timestamp } = channelData; + const displayTime = showMs ? `${Math.round(time)}ms` : `${Math.round(time / 1000)}s`; + + if (!showMs && Math.round(time / 1000) === 0) { + return null; + } + + const timeAgo = formatTimeAgo(timestamp); + + return ( + { }} + > +
+ + + + + {displayTime} + +
+
+ ); +}; + +function formatTimeAgo(timestamp: Date): string { + const now = new Date(); + const diff = now.getTime() - timestamp.getTime(); + const seconds = Math.floor(diff / 1000); + const minutes = Math.floor(seconds / 60); + const hours = Math.floor(minutes / 60); + const days = Math.floor(hours / 24); + + if (days > 0) { + return `${days} day${days > 1 ? "s" : ""} ago`; + } else if (hours > 0) { + return `${hours} hour${hours > 1 ? "s" : ""} ago`; + } else if (minutes > 0) { + return `${minutes} minute${minutes > 1 ? "s" : ""} ago`; + } else { + return "just now"; + } +} + +function handleChannelSelect(data: any) { + if (data.channelId && data.channelId !== currentChannelId) { + currentChannelId = data.channelId; + currentFetch = { + channelId: data.channelId, + startTime: performance.now() + }; + } +} + +function handleMessageLoad(data: any) { + if (!currentFetch || data.channelId !== currentFetch.channelId) return; + + const existing = channelTimings.get(currentFetch.channelId); + if (existing) return; + + const endTime = performance.now(); + const duration = endTime - currentFetch.startTime; + + channelTimings.set(currentFetch.channelId, { + time: duration, + timestamp: new Date() + }); + + currentFetch = null; +} + + +export default definePlugin({ + name: "MessageFetchTimer", + description: "Shows how long it took to fetch messages for the current channel", + authors: [EquicordDevs.GroupXyz], + settings, + + start() { + FluxDispatcher.subscribe("CHANNEL_SELECT", handleChannelSelect); + FluxDispatcher.subscribe("LOAD_MESSAGES_SUCCESS", handleMessageLoad); + FluxDispatcher.subscribe("MESSAGE_CREATE", handleMessageLoad); + + const currentChannel = getCurrentChannel(); + if (currentChannel) { + currentChannelId = currentChannel.id; + } + }, + + stop() { + FluxDispatcher.unsubscribe("CHANNEL_SELECT", handleChannelSelect); + FluxDispatcher.unsubscribe("LOAD_MESSAGES_SUCCESS", handleMessageLoad); + FluxDispatcher.unsubscribe("MESSAGE_CREATE", handleMessageLoad); + + currentFetch = null; + channelTimings.clear(); + currentChannelId = null; + }, + + renderChatBarButton: FetchTimeButton, +}); diff --git a/src/utils/constants.ts b/src/utils/constants.ts index bf4dd6a9..27d163af 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -1078,6 +1078,10 @@ export const EquicordDevs = Object.freeze({ name: "bbgaming25k", id: 851222385528274964n, }, + GroupXyz: { + name: "GroupXyz", + id: 950033410229944331n + }, } satisfies Record); // iife so #__PURE__ works correctly From 88c03c79bc289bdd0fb5744614344408974ba545 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Sun, 1 Jun 2025 10:40:11 -0400 Subject: [PATCH 4/4] ShowConnections Open Xbox Connection --- src/plugins/showConnections/index.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/plugins/showConnections/index.tsx b/src/plugins/showConnections/index.tsx index f99c0be9..4a3dc028 100644 --- a/src/plugins/showConnections/index.tsx +++ b/src/plugins/showConnections/index.tsx @@ -151,7 +151,13 @@ function CompactConnectionComponent({ connection, theme }: { connection: Connect :