diff --git a/.github/workflows/codeberg-mirror.yml b/.github/workflows/codeberg-mirror.yml index 647a43135..1b2266ee7 100644 --- a/.github/workflows/codeberg-mirror.yml +++ b/.github/workflows/codeberg-mirror.yml @@ -18,5 +18,5 @@ jobs: fetch-depth: 0 - uses: pixta-dev/repository-mirroring-action@674e65a7d483ca28dafaacba0d07351bdcc8bd75 # v1.1.1 with: - target_repo_url: "git@codeberg.org:Ven/cord.git" + target_repo_url: "git@codeberg.org:Vee/cord.git" ssh_private_key: ${{ secrets.CODEBERG_SSH_PRIVATE_KEY }} diff --git a/README.md b/README.md index 8611babd7..a43c9f834 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Vencord -[![Codeberg Mirror](https://img.shields.io/static/v1?style=for-the-badge&label=Codeberg%20Mirror&message=codeberg.org/Ven/cord&color=2185D0&logo=data:image/png;base64,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)](https://codeberg.org/Ven/cord) +[![Codeberg Mirror](https://img.shields.io/static/v1?style=for-the-badge&label=Codeberg%20Mirror&message=codeberg.org/Vee/cord&color=2185D0&logo=data:image/png;base64,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)](https://codeberg.org/Vee/cord) The cutest Discord client mod diff --git a/package.json b/package.json index 8e10f3bb2..0e1ae8cd5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vencord", "private": "true", - "version": "1.6.5", + "version": "1.6.6", "description": "The cutest Discord client mod", "homepage": "https://github.com/Vendicated/Vencord#readme", "bugs": { diff --git a/src/Vencord.ts b/src/Vencord.ts index 24a7681b7..29e965fa0 100644 --- a/src/Vencord.ts +++ b/src/Vencord.ts @@ -44,7 +44,7 @@ async function syncSettings() { // pre-check for local shared settings if ( Settings.cloud.authenticated && - await dsGet("Vencord_cloudSecret") === null // this has been enabled due to local settings share or some other bug + !await dsGet("Vencord_cloudSecret") // this has been enabled due to local settings share or some other bug ) { // show a notification letting them know and tell them how to fix it showNotification({ diff --git a/src/components/VencordSettings/UpdaterTab.tsx b/src/components/VencordSettings/UpdaterTab.tsx index 81433960f..0a5d1f149 100644 --- a/src/components/VencordSettings/UpdaterTab.tsx +++ b/src/components/VencordSettings/UpdaterTab.tsx @@ -81,9 +81,12 @@ function HashLink({ repo, hash, disabled = false }: { repo: string, hash: string function Changes({ updates, repo, repoPending }: CommonProps & { updates: typeof changes; }) { return ( - + {updates.map(({ hash, author, message }) => ( -
+
) : ( - {isOutdated ? `There are ${updates.length} Updates` : "Up to Date!"} + {isOutdated ? (updates.length === 1 ? "There is 1 Update" : `There are ${updates.length} Updates`) : "Up to Date!"} )} diff --git a/src/plugins/biggerStreamPreview/index.tsx b/src/plugins/biggerStreamPreview/index.tsx index acad564da..40bbe30a8 100644 --- a/src/plugins/biggerStreamPreview/index.tsx +++ b/src/plugins/biggerStreamPreview/index.tsx @@ -82,7 +82,7 @@ export const streamContextPatch: NavContextMenuPatchCallback = (children, { stre }; export const userContextPatch: NavContextMenuPatchCallback = (children, { user }: UserContextProps) => { - return addViewStreamContext(children, { userId: user.id }); + if (user) return addViewStreamContext(children, { userId: user.id }); }; export default definePlugin({ diff --git a/src/plugins/copyUserURLs/index.tsx b/src/plugins/copyUserURLs/index.tsx index e3c336fb2..9f69674cf 100644 --- a/src/plugins/copyUserURLs/index.tsx +++ b/src/plugins/copyUserURLs/index.tsx @@ -30,6 +30,8 @@ interface UserContextProps { } const UserContextMenuPatch: NavContextMenuPatchCallback = (children, { user }: UserContextProps) => () => { + if (!user) return; + children.push( - - - You can also access Decor decorations from the { - e.preventDefault(); - closeAllModals(); - FluxDispatcher.dispatch({ type: "USER_SETTINGS_MODAL_SET_SECTION", section: "Profile Customization" }); - }} - >Profiles page. - -
; - } - } -}); export default definePlugin({ name: "Decor", description: "Create and use your own custom avatar decorations, or pick your favorite from the presets.", diff --git a/src/plugins/decor/settings.tsx b/src/plugins/decor/settings.tsx new file mode 100644 index 000000000..0d3628cc6 --- /dev/null +++ b/src/plugins/decor/settings.tsx @@ -0,0 +1,47 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2023 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { definePluginSettings } from "@api/Settings"; +import { Link } from "@components/Link"; +import { Margins } from "@utils/margins"; +import { classes } from "@utils/misc"; +import { closeAllModals } from "@utils/modal"; +import { OptionType } from "@utils/types"; +import { FluxDispatcher, Forms } from "@webpack/common"; + +import DecorSection from "./ui/components/DecorSection"; + +export const settings = definePluginSettings({ + changeDecoration: { + type: OptionType.COMPONENT, + description: "Change your avatar decoration", + component() { + if (!Vencord.Plugins.plugins.Decor.started) return + Enable Decor and restart your client to change your avatar decoration. + ; + + return
+ + + You can also access Decor decorations from the { + e.preventDefault(); + closeAllModals(); + FluxDispatcher.dispatch({ type: "USER_SETTINGS_MODAL_SET_SECTION", section: "Profile Customization" }); + }} + >Profiles page. + +
; + } + }, + agreedToGuidelines: { + type: OptionType.BOOLEAN, + description: "Agreed to guidelines", + hidden: true, + default: false + } +}); diff --git a/src/plugins/decor/ui/components/index.ts b/src/plugins/decor/ui/components/index.ts index 8f39a10ee..8fe41fc92 100644 --- a/src/plugins/decor/ui/components/index.ts +++ b/src/plugins/decor/ui/components/index.ts @@ -19,7 +19,7 @@ export let DecorationGridItem: DecorationGridItemComponent; export const setDecorationGridItem = v => DecorationGridItem = v; export const AvatarDecorationModalPreview = LazyComponentWebpack(() => { - const component = findComponentByCode("AvatarDecorationModalPreview"); + const component = findComponentByCode(".shopPreviewBanner"); return React.memo(component); }); diff --git a/src/plugins/decor/ui/index.ts b/src/plugins/decor/ui/index.ts index 52b169d77..0ead602e2 100644 --- a/src/plugins/decor/ui/index.ts +++ b/src/plugins/decor/ui/index.ts @@ -5,9 +5,10 @@ */ import { classNameFactory } from "@api/Styles"; -import { extractAndLoadChunksLazy } from "@webpack"; +import { extractAndLoadChunksLazy, findByPropsLazy } from "@webpack"; export const cl = classNameFactory("vc-decor-"); +export const DecorationModalStyles = findByPropsLazy("modalFooterShopButton"); export const requireAvatarDecorationModal = extractAndLoadChunksLazy(["openAvatarDecorationModal:"]); export const requireCreateStickerModal = extractAndLoadChunksLazy(["stickerInspected]:"]); diff --git a/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx b/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx index bed007174..5fbe165ce 100644 --- a/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx +++ b/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx @@ -4,12 +4,13 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import ErrorBoundary from "@components/ErrorBoundary"; import { Flex } from "@components/Flex"; import { openInviteModal } from "@utils/discord"; import { Margins } from "@utils/margins"; import { classes } from "@utils/misc"; -import { closeAllModals, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalRoot, ModalSize, openModal } from "@utils/modal"; -import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; +import { closeAllModals, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal"; +import { findComponentByCodeLazy } from "@webpack"; import { Alerts, Button, FluxDispatcher, Forms, GuildStore, NavigationRouter, Parser, Text, Tooltip, useEffect, UserStore, UserUtils, useState } from "@webpack/common"; import { User } from "discord-types/general"; @@ -18,16 +19,17 @@ import { GUILD_ID, INVITE_KEY } from "../../lib/constants"; import { useAuthorizationStore } from "../../lib/stores/AuthorizationStore"; import { useCurrentUserDecorationsStore } from "../../lib/stores/CurrentUserDecorationsStore"; import { decorationToAvatarDecoration } from "../../lib/utils/decoration"; -import { cl, requireAvatarDecorationModal } from "../"; +import { settings } from "../../settings"; +import { cl, DecorationModalStyles, requireAvatarDecorationModal } from "../"; import { AvatarDecorationModalPreview } from "../components"; import DecorationGridCreate from "../components/DecorationGridCreate"; import DecorationGridNone from "../components/DecorationGridNone"; import DecorDecorationGridDecoration from "../components/DecorDecorationGridDecoration"; import SectionedGridList from "../components/SectionedGridList"; import { openCreateDecorationModal } from "./CreateDecorationModal"; +import { openGuidelinesModal } from "./GuidelinesModal"; const UserSummaryItem = findComponentByCodeLazy("defaultRenderUser", "showDefaultAvatarsForNullUsers"); -const DecorationModalStyles = findByPropsLazy("modalFooterShopButton"); function usePresets() { const [presets, setPresets] = useState([]); @@ -83,7 +85,7 @@ function SectionHeader({ section }: { section: Section; }) {
; } -export default function ChangeDecorationModal(props: any) { +function ChangeDecorationModal(props: ModalProps) { // undefined = not trying, null = none, Decoration = selected const [tryingDecoration, setTryingDecoration] = useState(undefined); const isTryingDecoration = typeof tryingDecoration !== "undefined"; @@ -116,6 +118,7 @@ export default function ChangeDecorationModal(props: any) { const data = [ { title: "Your Decorations", + subtitle: "You can delete your own decorations by right clicking on them.", sectionKey: "ownDecorations", items: ["none", ...ownDecorations, "create"] }, @@ -148,60 +151,62 @@ export default function ChangeDecorationModal(props: any) { className={cl("change-decoration-modal-content")} scrollbarType="none" > - { - if (typeof item === "string") { - switch (item) { - case "none": - return setTryingDecoration(null)} - />; - case "create": - return - {tooltipProps => + { + if (typeof item === "string") { + switch (item) { + case "none": + return setTryingDecoration(null)} + />; + case "create": + return + {tooltipProps => { }} + />} + ; + } + } else { + return + {tooltipProps => ( + { }} - />} - ; + className={cl("change-decoration-modal-decoration")} + onSelect={item.reviewed !== false ? () => setTryingDecoration(item) : () => { }} + isSelected={activeSelectedDecoration?.hash === item.hash} + decoration={item} + /> + )} + ; } - } else { - return - {tooltipProps => ( - setTryingDecoration(item) : () => { }} - isSelected={activeSelectedDecoration?.hash === item.hash} - decoration={item} - /> - )} - ; - } - }} - getItemKey={item => typeof item === "string" ? item : item.hash} - getSectionKey={section => section.sectionKey} - renderSectionHeader={section => } - sections={data} - /> -
- typeof item === "string" ? item : item.hash} + getSectionKey={section => section.sectionKey} + renderSectionHeader={section => } + sections={data} /> - {isActiveDecorationPreset && Part of the {activeDecorationPreset.name} Preset} - {typeof activeSelectedDecoration === "object" && - - {activeSelectedDecoration?.alt} - - } - {activeDecorationHasAuthor && Created by {Parser.parse(`<@${activeSelectedDecoration.authorId}>`)}} -
+
+ + {isActiveDecorationPreset && Part of the {activeDecorationPreset.name} Preset} + {typeof activeSelectedDecoration === "object" && + + {activeSelectedDecoration?.alt} + + } + {activeDecorationHasAuthor && Created by {Parser.parse(`<@${activeSelectedDecoration.authorId}>`)}} +
+
diff --git a/src/plugins/decor/ui/modals/CreateDecorationModal.tsx b/src/plugins/decor/ui/modals/CreateDecorationModal.tsx index a5937b0dd..0dcf855ef 100644 --- a/src/plugins/decor/ui/modals/CreateDecorationModal.tsx +++ b/src/plugins/decor/ui/modals/CreateDecorationModal.tsx @@ -4,23 +4,23 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import ErrorBoundary from "@components/ErrorBoundary"; import { Link } from "@components/Link"; import { openInviteModal } from "@utils/discord"; import { Margins } from "@utils/margins"; -import { closeAllModals, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalRoot, ModalSize, openModal } from "@utils/modal"; +import { closeAllModals, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal"; import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; import { Button, FluxDispatcher, Forms, GuildStore, NavigationRouter, Text, TextInput, useEffect, useMemo, UserStore, useState } from "@webpack/common"; import { GUILD_ID, INVITE_KEY, RAW_SKU_ID } from "../../lib/constants"; import { useCurrentUserDecorationsStore } from "../../lib/stores/CurrentUserDecorationsStore"; -import { cl, requireAvatarDecorationModal, requireCreateStickerModal } from "../"; +import { cl, DecorationModalStyles, requireAvatarDecorationModal, requireCreateStickerModal } from "../"; import { AvatarDecorationModalPreview } from "../components"; - -const DecorationModalStyles = findByPropsLazy("modalFooterShopButton"); - const FileUpload = findComponentByCodeLazy("fileUploadInput,"); +const { default: HelpMessage, HelpMessageTypes } = findByPropsLazy("HelpMessageTypes"); + function useObjectURL(object: Blob | MediaSource | null) { const [url, setUrl] = useState(null); @@ -39,7 +39,7 @@ function useObjectURL(object: Blob | MediaSource | null) { return url; } -export default function CreateDecorationModal(props) { +function CreateDecorationModal(props: ModalProps) { const [name, setName] = useState(""); const [file, setFile] = useState(null); const [submitting, setSubmitting] = useState(false); @@ -75,65 +75,69 @@ export default function CreateDecorationModal(props) { className={cl("create-decoration-modal-content")} scrollbarType="none" > -
-
- {error !== null && {error.message}} - - + + Make sure your decoration does not violate + the guidelines + before submitting it. + +
+
+ {error !== null && {error.message}} + + + + File should be APNG or PNG. + + + + + + This name will be used when referring to this decoration. + + +
+
+ - - File should be APNG or PNG. - - - - - - This name will be used when referring to this decoration. - - +
-
- -
-
- - Make sure your decoration does not violate - the guidelines - before creating your decoration. -
You can receive updates on your decoration's review by joining { - e.preventDefault(); - if (!GuildStore.getGuild(GUILD_ID)) { - const inviteAccepted = await openInviteModal(INVITE_KEY); - if (inviteAccepted) { + +
You can receive updates on your decoration's review by joining { + e.preventDefault(); + if (!GuildStore.getGuild(GUILD_ID)) { + const inviteAccepted = await openInviteModal(INVITE_KEY); + if (inviteAccepted) { + closeAllModals(); + FluxDispatcher.dispatch({ type: "LAYER_POP_ALL" }); + } + } else { closeAllModals(); FluxDispatcher.dispatch({ type: "LAYER_POP_ALL" }); + NavigationRouter.transitionToGuild(GUILD_ID); } - } else { - closeAllModals(); - FluxDispatcher.dispatch({ type: "LAYER_POP_ALL" }); - NavigationRouter.transitionToGuild(GUILD_ID); - } - }} - > - Decor's Discord server - . -
+ }} + > + Decor's Discord server + . +
+ + + + ; +} + +export const openGuidelinesModal = () => + requireAvatarDecorationModal().then(() => openModal(props => )); diff --git a/src/plugins/decor/ui/styles.css b/src/plugins/decor/ui/styles.css index ff10c82fa..9730efb7e 100644 --- a/src/plugins/decor/ui/styles.css +++ b/src/plugins/decor/ui/styles.css @@ -8,7 +8,7 @@ display: flex; border-radius: 5px 5px 0 0; padding: 0 16px; - gap: 4px + gap: 4px; } .vc-decor-change-decoration-modal-preview { @@ -72,7 +72,7 @@ .vc-decor-sectioned-grid-list-grid { display: flex; flex-wrap: wrap; - gap: 8px + gap: 8px; } .vc-decor-section-remove-margin { diff --git a/src/plugins/fixCodeblockGap/index.ts b/src/plugins/fixCodeblockGap/index.ts new file mode 100644 index 000000000..133409959 --- /dev/null +++ b/src/plugins/fixCodeblockGap/index.ts @@ -0,0 +1,35 @@ +/* + * Vencord, a modification for Discord's desktop app + * Copyright (c) 2023 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 { Devs } from "@utils/constants"; +import definePlugin from "@utils/types"; + +export default definePlugin({ + name: "FixCodeblockGap", + description: "Removes the gap between codeblocks and text below it", + authors: [Devs.Grzesiek11], + patches: [ + { + find: ".default.Messages.DELETED_ROLE_PLACEHOLDER", + replacement: { + match: String.raw`/^${"```"}(?:([a-z0-9_+\-.#]+?)\n)?\n*([^\n][^]*?)\n*${"```"}`, + replace: "$&\\n?", + }, + }, + ], +}); diff --git a/src/plugins/reverseImageSearch/index.tsx b/src/plugins/reverseImageSearch/index.tsx index 811e7ff08..6c5f3e729 100644 --- a/src/plugins/reverseImageSearch/index.tsx +++ b/src/plugins/reverseImageSearch/index.tsx @@ -36,62 +36,68 @@ function search(src: string, engine: string) { open(engine + encodeURIComponent(src), "_blank"); } -const imageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => () => { - if (!props) return; - const { reverseImageSearchType, itemHref, itemSrc } = props; +function makeSearchItem(src: string) { + return ( + + {Object.keys(Engines).map((engine, i) => { + const key = "search-image-" + engine; + return ( + + = 3 // Do not round Google, Yandex & SauceNAO + ? "50%" + : void 0 + }} + aria-hidden="true" + height={16} + width={16} + src={new URL("/favicon.ico", Engines[engine]).toString().replace("lens.", "")} + /> + {engine} + + } + action={() => search(src, Engines[engine])} + /> + ); + })} + + + All + + } + action={() => Object.values(Engines).forEach(e => search(src, e))} + /> + + ); +} - if (!reverseImageSearchType || reverseImageSearchType !== "img") return; +const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => () => { + if (props?.reverseImageSearchType !== "img") return; - const src = itemHref ?? itemSrc; + const src = props.itemHref ?? props.itemSrc; const group = findGroupChildrenByChildId("copy-link", children); - if (group) { - group.push(( - - {Object.keys(Engines).map((engine, i) => { - const key = "search-image-" + engine; - return ( - - = 3 // Do not round Google, Yandex & SauceNAO - ? "50%" - : void 0 - }} - aria-hidden="true" - height={16} - width={16} - src={new URL("/favicon.ico", Engines[engine]).toString().replace("lens.", "")} - /> - {engine} - - } - action={() => search(src, Engines[engine])} - /> - ); - })} - - - All - - } - action={() => Object.values(Engines).forEach(e => search(src, e))} - /> - - )); - } + group?.push(makeSearchItem(src)); +}; + +const imageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => () => { + if (!props?.src) return; + + const group = findGroupChildrenByChildId("copy-native-link", children) ?? children; + group.push(makeSearchItem(props.src)); }; export default definePlugin({ @@ -111,10 +117,12 @@ export default definePlugin({ ], start() { - addContextMenuPatch("message", imageContextMenuPatch); + addContextMenuPatch("message", messageContextMenuPatch); + addContextMenuPatch("image-context", imageContextMenuPatch); }, stop() { - removeContextMenuPatch("message", imageContextMenuPatch); + removeContextMenuPatch("message", messageContextMenuPatch); + removeContextMenuPatch("image-context", imageContextMenuPatch); } }); diff --git a/src/plugins/sendTimestamps/index.tsx b/src/plugins/sendTimestamps/index.tsx index 7904545c8..6d488add6 100644 --- a/src/plugins/sendTimestamps/index.tsx +++ b/src/plugins/sendTimestamps/index.tsx @@ -19,14 +19,23 @@ import "./styles.css"; import { addPreSendListener, removePreSendListener } from "@api/MessageEvents"; +import { definePluginSettings } from "@api/Settings"; import { classNameFactory } from "@api/Styles"; import { Devs } from "@utils/constants"; import { getTheme, insertTextIntoChatInputBox, Theme } from "@utils/discord"; import { Margins } from "@utils/margins"; import { closeModal, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, openModal } from "@utils/modal"; -import definePlugin from "@utils/types"; +import definePlugin, { OptionType } from "@utils/types"; import { Button, ButtonLooks, ButtonWrapperClasses, Forms, Parser, Select, Tooltip, useMemo, useState } from "@webpack/common"; +const settings = definePluginSettings({ + replaceMessageContents: { + description: "Replace timestamps in message contents", + type: OptionType.BOOLEAN, + default: true, + }, +}); + function parseTime(time: string) { const cleanTime = time.slice(1, -1).replace(/(\d)(AM|PM)$/i, "$1 $2"); @@ -116,9 +125,11 @@ function PickerModal({ rootProps, close }: { rootProps: ModalProps, close(): voi export default definePlugin({ name: "SendTimestamps", description: "Send timestamps easily via chat box button & text shortcuts. Read the extended description!", - authors: [Devs.Ven, Devs.Tyler], + authors: [Devs.Ven, Devs.Tyler, Devs.Grzesiek11], dependencies: ["MessageEventsAPI"], + settings: settings, + patches: [ { find: "ChannelTextAreaButtons", @@ -131,7 +142,9 @@ export default definePlugin({ start() { this.listener = addPreSendListener((_, msg) => { - msg.content = msg.content.replace(/`\d{1,2}:\d{2} ?(?:AM|PM)?`/gi, parseTime); + if (settings.store.replaceMessageContents) { + msg.content = msg.content.replace(/`\d{1,2}:\d{2} ?(?:AM|PM)?`/gi, parseTime); + } }); }, diff --git a/src/plugins/textReplace/index.tsx b/src/plugins/textReplace/index.tsx index 5d66d2265..416ce83fb 100644 --- a/src/plugins/textReplace/index.tsx +++ b/src/plugins/textReplace/index.tsx @@ -213,7 +213,7 @@ function applyRules(content: string): string { if (stringRules) { for (const rule of stringRules) { - if (!rule.find || !rule.replace) continue; + if (!rule.find) continue; if (rule.onlyIfIncludes && !content.includes(rule.onlyIfIncludes)) continue; content = ` ${content} `.replaceAll(rule.find, rule.replace.replaceAll("\\n", "\n")).replace(/^\s|\s$/g, ""); @@ -222,7 +222,7 @@ function applyRules(content: string): string { if (regexRules) { for (const rule of regexRules) { - if (!rule.find || !rule.replace) continue; + if (!rule.find) continue; if (rule.onlyIfIncludes && !content.includes(rule.onlyIfIncludes)) continue; try { diff --git a/src/plugins/urbanDictionary/README.md b/src/plugins/urbanDictionary/README.md new file mode 100644 index 000000000..e065456a3 --- /dev/null +++ b/src/plugins/urbanDictionary/README.md @@ -0,0 +1,13 @@ +# Urban Dictionary + +Use /urban slash command to search for a definition for a word on [Urban Dictionary](https://www.urbandictionary.com/). + +## Preview + +![preview](https://i.imgur.com/1zwzj38.png) + +## Usage + +- Enable this plugin +- Set plugin settings as desired +- Type /urban and start getting definitions right into your Discord client. diff --git a/src/plugins/urbanDictionary/index.ts b/src/plugins/urbanDictionary/index.ts index 840fe5cb6..89dcdcba4 100644 --- a/src/plugins/urbanDictionary/index.ts +++ b/src/plugins/urbanDictionary/index.ts @@ -18,14 +18,24 @@ import { ApplicationCommandOptionType, sendBotMessage } from "@api/Commands"; import { ApplicationCommandInputType } from "@api/Commands/types"; +import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; -import definePlugin from "@utils/types"; +import definePlugin, { OptionType } from "@utils/types"; + +const settings = definePluginSettings({ + resultsAmount: { + type: OptionType.NUMBER, + description: "The amount of results you want to get (more gives better results, but is slower)", + default: 10 + } +}); export default definePlugin({ name: "UrbanDictionary", description: "Search for a word on Urban Dictionary via /urban slash command", authors: [Devs.jewdev], dependencies: ["CommandsAPI"], + settings, commands: [ { name: "urban", @@ -41,12 +51,16 @@ export default definePlugin({ ], execute: async (args, ctx) => { try { - const query = encodeURIComponent(args[0].value); - const { list: [definition] } = await (await fetch(`https://api.urbandictionary.com/v0/define?term=${query}`)).json(); + const query: string = encodeURIComponent(args[0].value); + const { list } = await fetch(`https://api.urbandictionary.com/v0/define?term=${query}&per_page=${settings.store.resultsAmount}`).then(response => response.json()); - if (!definition) + if (!list.length) return void sendBotMessage(ctx.channel.id, { content: "No results found." }); + const definition = list.reduce((prev, curr) => { + return prev.thumbs_up > curr.thumbs_up ? prev : curr; + }); + const linkify = (text: string) => text .replaceAll("\r\n", "\n") .replace(/([*>_`~\\])/gsi, "\\$1") diff --git a/src/plugins/vencordToolbox/index.tsx b/src/plugins/vencordToolbox/index.tsx index 2b0ce14e6..0a805a0d2 100644 --- a/src/plugins/vencordToolbox/index.tsx +++ b/src/plugins/vencordToolbox/index.tsx @@ -33,7 +33,7 @@ function VencordPopout(onClose: () => void) { const pluginEntries = [] as ReactNode[]; for (const plugin of Object.values(Vencord.Plugins.plugins)) { - if (plugin.toolboxActions) { + if (plugin.toolboxActions && Vencord.Plugins.isPluginEnabled(plugin.name)) { pluginEntries.push( ); // iife so #__PURE__ works correctly