diff options
-rw-r--r-- | src/plugins/pronoundb/components/PronounsChatComponent.tsx | 6 | ||||
-rw-r--r-- | src/plugins/pronoundb/components/PronounsProfileWrapper.tsx | 6 | ||||
-rw-r--r-- | src/plugins/pronoundb/index.ts | 59 | ||||
-rw-r--r-- | src/plugins/pronoundb/pronoundbUtils.ts | 32 |
4 files changed, 95 insertions, 8 deletions
diff --git a/src/plugins/pronoundb/components/PronounsChatComponent.tsx b/src/plugins/pronoundb/components/PronounsChatComponent.tsx index ce67754..7aaea92 100644 --- a/src/plugins/pronoundb/components/PronounsChatComponent.tsx +++ b/src/plugins/pronoundb/components/PronounsChatComponent.tsx @@ -1,6 +1,6 @@ /* * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Vendicated and contributors + * Copyright (c) 2022-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 @@ -22,7 +22,7 @@ import { findByPropsLazy } from "@webpack"; import { UserStore } from "@webpack/common"; import { Message } from "discord-types/general"; -import { fetchPronouns, formatPronouns } from "../pronoundbUtils"; +import { findPronouns, formatPronouns } from "../pronoundbUtils"; import { PronounMapping } from "../types"; const styles: Record<string, string> = findByPropsLazy("timestampInline"); @@ -39,7 +39,7 @@ export default function PronounsChatComponentWrapper({ message }: { message: Mes } function PronounsChatComponent({ message }: { message: Message; }) { - const [result, , isPending] = useAwaiter(() => fetchPronouns(message.author.id), { + const [result, , isPending] = useAwaiter(() => findPronouns(message.author.id), { fallbackValue: null, onError: e => console.error("Fetching pronouns failed: ", e) }); diff --git a/src/plugins/pronoundb/components/PronounsProfileWrapper.tsx b/src/plugins/pronoundb/components/PronounsProfileWrapper.tsx index 79fce23..69a9e85 100644 --- a/src/plugins/pronoundb/components/PronounsProfileWrapper.tsx +++ b/src/plugins/pronoundb/components/PronounsProfileWrapper.tsx @@ -1,6 +1,6 @@ /* * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Vendicated and contributors + * Copyright (c) 2022-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 @@ -20,7 +20,7 @@ import { Settings } from "@api/settings"; import { useAwaiter } from "@utils/misc"; import { UserStore } from "@webpack/common"; -import { fetchPronouns, formatPronouns } from "../pronoundbUtils"; +import { findPronouns, formatPronouns } from "../pronoundbUtils"; import { PronounMapping, UserProfilePronounsProps, UserProfileProps } from "../types"; export default function PronounsProfileWrapper(PronounsComponent: React.ElementType<UserProfilePronounsProps>, props: UserProfilePronounsProps, profileProps: UserProfileProps) { @@ -45,7 +45,7 @@ function ProfilePronouns( leProps: UserProfilePronounsProps; } ) { - const [result, , isPending] = useAwaiter(() => fetchPronouns(userId), { + const [result, , isPending] = useAwaiter(() => findPronouns(userId), { fallbackValue: null, onError: e => console.error("Fetching pronouns failed: ", e), }); diff --git a/src/plugins/pronoundb/index.ts b/src/plugins/pronoundb/index.ts index c848110..87fb902 100644 --- a/src/plugins/pronoundb/index.ts +++ b/src/plugins/pronoundb/index.ts @@ -1,6 +1,6 @@ /* * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Vendicated and contributors + * Copyright (c) 2022-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 @@ -16,12 +16,15 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ +import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, sendBotMessage } from "@api/Commands"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import PronounsAboutComponent from "./components/PronounsAboutComponent"; import PronounsChatComponent from "./components/PronounsChatComponent"; import PronounsProfileWrapper from "./components/PronounsProfileWrapper"; +import { formatPronouns, getLocalPronounOverride, setLocalPronounOverride } from "./pronoundbUtils"; +import { PronounCode, PronounMapping } from "./types"; export enum PronounsFormat { Lowercase = "LOWERCASE", @@ -81,6 +84,60 @@ export default definePlugin({ default: true } }, + + commands: [ + { + description: "Set local pronouns for a person", + name: "setpronouns", + options: [ + { + description: "The user for which you want to set the local pronoun override", + name: "user", + displayName: "User", + type: ApplicationCommandOptionType.USER, + required: true, + }, + { + name: "pronouns", + displayName: "Pronouns", + type: ApplicationCommandOptionType.STRING, + description: "What pronouns should I display for this user.", + required: false, + choices: [ + ...Object.keys(PronounMapping).map(id => ({ + label: PronounMapping[id], + value: id, + name: PronounMapping[id], + })), + { + label: "Clear local override", + name: "Clear local override", + value: "clear", + } + ], + } + ], + inputType: ApplicationCommandInputType.BOT, + async execute(args, ctx) { + const user = findOption<string>(args, "user")!!; + const overrideWith = findOption<string>(args, "pronouns", "view"); + const currentOverride = await getLocalPronounOverride(user); + const currentOverrideText = currentOverride ? formatPronouns(currentOverride) : "No override"; + if (overrideWith === "view") { + sendBotMessage(ctx.channel.id, { content: `Current pronoun override for <@${user}>: ${currentOverrideText}` }); + return; + } + if (overrideWith !== currentOverride) { + const asPronounCode = overrideWith === "clear" ? null : overrideWith as PronounCode; + await setLocalPronounOverride(user, asPronounCode); + sendBotMessage(ctx.channel.id, { content: `Changed pronoun override for <@${user}> from ${currentOverrideText} to ${asPronounCode ? formatPronouns(asPronounCode) : "No override"}` }); + return; + } + sendBotMessage(ctx.channel.id, { content: `Pronoun override for <@${user}> is alredy ${currentOverrideText}` }); + }, + }, + ], + settingsAboutComponent: PronounsAboutComponent, // Re-export the components on the plugin object so it is easily accessible in patches PronounsChatComponent, diff --git a/src/plugins/pronoundb/pronoundbUtils.ts b/src/plugins/pronoundb/pronoundbUtils.ts index afeea95..2eff47a 100644 --- a/src/plugins/pronoundb/pronoundbUtils.ts +++ b/src/plugins/pronoundb/pronoundbUtils.ts @@ -1,6 +1,6 @@ /* * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Vendicated and contributors + * Copyright (c) 2022-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 @@ -16,6 +16,7 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ +import * as DataStore from "@api/DataStore"; import { Settings } from "@api/settings"; import { VENCORD_USER_AGENT } from "@utils/constants"; import { debounce } from "@utils/debounce"; @@ -23,6 +24,15 @@ import { debounce } from "@utils/debounce"; import { PronounsFormat } from "."; import { PronounCode, PronounMapping, PronounsResponse } from "./types"; + +let pronounDBStore: DataStore.UseStore | undefined; + +function getPronounDbStore(): DataStore.UseStore { + if (!pronounDBStore) + pronounDBStore = DataStore.createStore("VencordPronounData", "LocalPronounDBOverrides"); + return pronounDBStore; +} + // A map of cached pronouns so the same request isn't sent twice const cache: Record<string, PronounCode> = {}; // A map of ids and callbacks that should be triggered on fetch @@ -39,6 +49,26 @@ const bulkFetch = debounce(async () => { } }); +// Find the pronouns for a discord id, first looking for local override then fetching pronoundb. +export async function findPronouns(id: string): Promise<PronounCode> { + return (await getLocalPronounOverride(id)) ?? await fetchPronouns(id); +} + +export function setLocalPronounOverride(id: string, newOverride: PronounCode | null): Promise<void> { + if (newOverride == null) { + return DataStore.del(id, getPronounDbStore()); + } else { + return DataStore.set(id, newOverride, getPronounDbStore()); + } +} + +export async function getLocalPronounOverride(id: string): Promise<PronounCode | null> { + const localValue = await DataStore.get(id, getPronounDbStore()); + if (localValue in PronounMapping) + return localValue as PronounCode; + return null; +} + // Fetches the pronouns for one id, returning a promise that resolves if it was cached, or once the request is completed export function fetchPronouns(id: string): Promise<PronounCode> { return new Promise(res => { |