PronounDB: Source pronouns from both PronounDB & Discord (#1301)
* PronounDB: Source pronouns from both PronounDB & Discord * jdsjdsajjasiofigvjodsjigfdjiogegjnegjnersjn
This commit is contained in:
		
							parent
							
								
									7e8397a4da
								
							
						
					
					
						commit
						e4162e7bd5
					
				
					 3 changed files with 60 additions and 22 deletions
				
			
		| 
						 | 
					@ -52,7 +52,7 @@ export default definePlugin({
 | 
				
			||||||
            find: ".userTagNoNickname",
 | 
					            find: ".userTagNoNickname",
 | 
				
			||||||
            replacement: {
 | 
					            replacement: {
 | 
				
			||||||
                match: /=(\i)\.pronouns/,
 | 
					                match: /=(\i)\.pronouns/,
 | 
				
			||||||
                replace: "=$self.useProfilePronouns($1.user.id)"
 | 
					                replace: "=$self.useProfilePronouns($1.user.id,$1.pronouns)"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        // Patch the profile modal username header to use our pronoun hook instead of Discord's pronouns
 | 
					        // Patch the profile modal username header to use our pronoun hook instead of Discord's pronouns
 | 
				
			||||||
| 
						 | 
					@ -60,7 +60,7 @@ export default definePlugin({
 | 
				
			||||||
            find: ".USER_PROFILE_ACTIVITY",
 | 
					            find: ".USER_PROFILE_ACTIVITY",
 | 
				
			||||||
            replacement: {
 | 
					            replacement: {
 | 
				
			||||||
                match: /\).showPronouns/,
 | 
					                match: /\).showPronouns/,
 | 
				
			||||||
                replace: ").showPronouns||true;const vcPronounce=$self.useProfilePronouns(arguments[0].user.id);if(arguments[0].displayProfile)arguments[0].displayProfile.pronouns=vcPronounce"
 | 
					                replace: ").showPronouns||true;const vcPronounce=$self.useProfilePronouns(arguments[0].user.id,arguments[0].displayProfile?.pronouns);if(arguments[0].displayProfile&&vcPronounce)arguments[0].displayProfile.pronouns=vcPronounce"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,17 +19,26 @@
 | 
				
			||||||
import { Settings } from "@api/Settings";
 | 
					import { Settings } from "@api/Settings";
 | 
				
			||||||
import { VENCORD_USER_AGENT } from "@utils/constants";
 | 
					import { VENCORD_USER_AGENT } from "@utils/constants";
 | 
				
			||||||
import { debounce } from "@utils/debounce";
 | 
					import { debounce } from "@utils/debounce";
 | 
				
			||||||
 | 
					import { getCurrentChannel } from "@utils/discord";
 | 
				
			||||||
import { useAwaiter } from "@utils/react";
 | 
					import { useAwaiter } from "@utils/react";
 | 
				
			||||||
 | 
					import { findStoreLazy } from "@webpack";
 | 
				
			||||||
import { UserStore } from "@webpack/common";
 | 
					import { UserStore } from "@webpack/common";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { settings } from "./settings";
 | 
					import { settings } from "./settings";
 | 
				
			||||||
import { PronounCode, PronounMapping, PronounsResponse } from "./types";
 | 
					import { PronounCode, PronounMapping, PronounsResponse } from "./types";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const UserProfileStore = findStoreLazy("UserProfileStore");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const enum PronounsFormat {
 | 
					export const enum PronounsFormat {
 | 
				
			||||||
    Lowercase = "LOWERCASE",
 | 
					    Lowercase = "LOWERCASE",
 | 
				
			||||||
    Capitalized = "CAPITALIZED"
 | 
					    Capitalized = "CAPITALIZED"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const enum PronounSource {
 | 
				
			||||||
 | 
					    PreferPDB,
 | 
				
			||||||
 | 
					    PreferDiscord
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// A map of cached pronouns so the same request isn't sent twice
 | 
					// A map of cached pronouns so the same request isn't sent twice
 | 
				
			||||||
const cache: Record<string, PronounCode> = {};
 | 
					const cache: Record<string, PronounCode> = {};
 | 
				
			||||||
// A map of ids and callbacks that should be triggered on fetch
 | 
					// A map of ids and callbacks that should be triggered on fetch
 | 
				
			||||||
| 
						 | 
					@ -46,21 +55,29 @@ const bulkFetch = debounce(async () => {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function useFormattedPronouns(id: string): string | null {
 | 
					function getDiscordPronouns(id: string) {
 | 
				
			||||||
    const [result] = useAwaiter(() => fetchPronouns(id), {
 | 
					    return (
 | 
				
			||||||
        fallbackValue: getCachedPronouns(id),
 | 
					        UserProfileStore.getGuildMemberProfile(id, getCurrentChannel()?.guild_id)?.pronouns
 | 
				
			||||||
 | 
					        || UserProfileStore.getUserProfile(id)?.pronouns
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function useFormattedPronouns(id: string, discordPronouns: string = getDiscordPronouns(id)): string | null {
 | 
				
			||||||
 | 
					    const [result] = useAwaiter(() => fetchPronouns(id, discordPronouns), {
 | 
				
			||||||
 | 
					        fallbackValue: getCachedPronouns(id, discordPronouns),
 | 
				
			||||||
        onError: e => console.error("Fetching pronouns failed: ", e)
 | 
					        onError: e => console.error("Fetching pronouns failed: ", e)
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // If the result is present and not "unspecified", and there is a mapping for the code, then return the mappings
 | 
					    if (result && result !== "unspecified")
 | 
				
			||||||
    if (result && result !== "unspecified" && PronounMapping[result])
 | 
					        return Object.hasOwn(PronounMapping, result)
 | 
				
			||||||
        return formatPronouns(result);
 | 
					            ? formatPronouns(result) // PronounDB
 | 
				
			||||||
 | 
					            : result; // Discord
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return null;
 | 
					    return null;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function useProfilePronouns(id: string) {
 | 
					export function useProfilePronouns(id: string, discordPronouns: string) {
 | 
				
			||||||
    const pronouns = useFormattedPronouns(id);
 | 
					    const pronouns = useFormattedPronouns(id, discordPronouns);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!settings.store.showInProfile) return null;
 | 
					    if (!settings.store.showInProfile) return null;
 | 
				
			||||||
    if (!settings.store.showSelf && id === UserStore.getCurrentUser().id) return null;
 | 
					    if (!settings.store.showSelf && id === UserStore.getCurrentUser().id) return null;
 | 
				
			||||||
| 
						 | 
					@ -70,22 +87,28 @@ export function useProfilePronouns(id: string) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Gets the cached pronouns, if you're too impatient for a promise!
 | 
					// Gets the cached pronouns, if you're too impatient for a promise!
 | 
				
			||||||
export function getCachedPronouns(id: string): PronounCode | null {
 | 
					export function getCachedPronouns(id: string, discordPronouns: string): string | null {
 | 
				
			||||||
    return cache[id] ?? null;
 | 
					    if (settings.store.pronounSource === PronounSource.PreferDiscord && discordPronouns)
 | 
				
			||||||
 | 
					        return discordPronouns;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const cached = cache[id];
 | 
				
			||||||
 | 
					    if (cached && cached !== "unspecified") return cached;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return discordPronouns || cached || null;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Fetches the pronouns for one id, returning a promise that resolves if it was cached, or once the request is completed
 | 
					// 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> {
 | 
					export function fetchPronouns(id: string, discordPronouns: string): Promise<string> {
 | 
				
			||||||
    return new Promise(res => {
 | 
					    return new Promise(res => {
 | 
				
			||||||
        // If cached, return the cached pronouns
 | 
					        const cached = getCachedPronouns(id, discordPronouns);
 | 
				
			||||||
        if (id in cache) res(getCachedPronouns(id)!);
 | 
					        if (cached) return res(cached);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // If there is already a request added, then just add this callback to it
 | 
					        // If there is already a request added, then just add this callback to it
 | 
				
			||||||
        else if (id in requestQueue) requestQueue[id].push(res);
 | 
					        if (id in requestQueue) return requestQueue[id].push(res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // If not already added, then add it and call the debounced function to make sure the request gets executed
 | 
					        // If not already added, then add it and call the debounced function to make sure the request gets executed
 | 
				
			||||||
        else {
 | 
					 | 
				
			||||||
        requestQueue[id] = [res];
 | 
					        requestQueue[id] = [res];
 | 
				
			||||||
        bulkFetch();
 | 
					        bulkFetch();
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -116,7 +139,7 @@ async function bulkFetchPronouns(ids: string[]): Promise<PronounsResponse> {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function formatPronouns(pronouns: PronounCode): string {
 | 
					export function formatPronouns(pronouns: string): string {
 | 
				
			||||||
    const { pronounsFormat } = Settings.plugins.PronounDB as { pronounsFormat: PronounsFormat, enabled: boolean; };
 | 
					    const { pronounsFormat } = Settings.plugins.PronounDB as { pronounsFormat: PronounsFormat, enabled: boolean; };
 | 
				
			||||||
    // For capitalized pronouns, just return the mapping (it is by default capitalized)
 | 
					    // For capitalized pronouns, just return the mapping (it is by default capitalized)
 | 
				
			||||||
    if (pronounsFormat === PronounsFormat.Capitalized) return PronounMapping[pronouns];
 | 
					    if (pronounsFormat === PronounsFormat.Capitalized) return PronounMapping[pronouns];
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,7 @@
 | 
				
			||||||
import { definePluginSettings } from "@api/Settings";
 | 
					import { definePluginSettings } from "@api/Settings";
 | 
				
			||||||
import { OptionType } from "@utils/types";
 | 
					import { OptionType } from "@utils/types";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { PronounsFormat } from "./pronoundbUtils";
 | 
					import { PronounsFormat, PronounSource } from "./pronoundbUtils";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const settings = definePluginSettings({
 | 
					export const settings = definePluginSettings({
 | 
				
			||||||
    pronounsFormat: {
 | 
					    pronounsFormat: {
 | 
				
			||||||
| 
						 | 
					@ -37,6 +37,21 @@ export const settings = definePluginSettings({
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    pronounSource: {
 | 
				
			||||||
 | 
					        type: OptionType.SELECT,
 | 
				
			||||||
 | 
					        description: "Where to source pronouns from",
 | 
				
			||||||
 | 
					        options: [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                label: "Prefer PronounDB, fall back to Discord",
 | 
				
			||||||
 | 
					                value: PronounSource.PreferPDB,
 | 
				
			||||||
 | 
					                default: true
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                label: "Prefer Discord, fall back to PronounDB (might lead to inconsistency between pronouns in chat and profile)",
 | 
				
			||||||
 | 
					                value: PronounSource.PreferDiscord
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    showSelf: {
 | 
					    showSelf: {
 | 
				
			||||||
        type: OptionType.BOOLEAN,
 | 
					        type: OptionType.BOOLEAN,
 | 
				
			||||||
        description: "Enable or disable showing pronouns for the current user",
 | 
					        description: "Enable or disable showing pronouns for the current user",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue