fix(Quoter): errors when quoting users with no profile picture (#837)

* fix(Quoter): errors when quoting users with no profile picture

* apply an actual fix

---------

Co-authored-by: thororen1234 <78185467+thororen1234@users.noreply.github.com>
This commit is contained in:
tralwdwd 2026-02-26 15:56:35 +00:00 • committed by GitHub
parent bf500c6993
commit 84378cbb82
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 9 additions and 13 deletions

View file

@ -51,6 +51,7 @@ export default definePlugin({ options: { myOption: { /* ... */ } } });
```
**Prefer declarative APIs** over manual registration:
- `flux: { EVENT_NAME(data) {} }` not manual FluxDispatcher subscribe
- `contextMenus: { "nav-id": fn }` not manual addContextMenuPatch
- `chatBarButton: { render, icon }` not addChatBarButton
@ -81,7 +82,6 @@ Flag these and suggest the fix:
| `cdn.discordapp.com/icons/...` | `IconUtils.getGuildIconURL(...)` | Same |
| `cdn.discordapp.com/banners/...` | `IconUtils.getUserBannerURL(...)` | Same |
| `cdn.discordapp.com/emojis/...` | `IconUtils.getEmojiURL(...)` | Same |
| `/assets/*.png` default avatars | `IconUtils.getDefaultAvatarURL(id)` | Same |
| `/api/v9/...` or `/users/@me` | `Constants.Endpoints.*` or `RestAPI` | Endpoints change |
| `@api/Styles` for classNameFactory | `@utils/css` | `@api/Styles` is deprecated |
| `any` for Discord objects | Import from `@vencord/discord-types` | Type safety |
@ -361,6 +361,7 @@ If a PR reimplements any of these, flag it. They already exist:
**@api/Commands:** `sendBotMessage`, `findOption`
**@webpack/common:**
- Stores: `UserStore`, `GuildStore`, `ChannelStore`, `GuildMemberStore`, `SelectedChannelStore`, `SelectedGuildStore`, `PresenceStore`, `RelationshipStore`, `MessageStore`, `EmojiStore`, `ThemeStore`, `PermissionStore`, `VoiceStateStore`, 30+ more
- Actions: `RestAPI`, `FluxDispatcher`, `MessageActions`, `NavigationRouter`, `ChannelRouter`, `ChannelActionCreators`, `SettingsRouter`
- Utils: `Constants` (`.Endpoints`), `SnowflakeUtils`, `Parser`, `PermissionsBits`, `moment`, `lodash`, `IconUtils`, `ColorUtils`, `ImageUtils`, `DateUtils`, `UsernameUtils`, `DisplayProfileUtils`

5
.rules
View file

@ -102,6 +102,7 @@
### Patch Examples
**Clean replacement:**
```js
find: "#{intl::PIN_MESSAGE}),icon:"
match: /#{intl::PIN_MESSAGE}\)/
@ -109,6 +110,7 @@ replace: "$self.getPinLabel(arguments[0]))"
```
**Appending:**
```js
find: "#{intl::VIEW_AS_ROLES_MENTIONS_WARNING}"
match: /#{intl::VIEW_AS_ROLES_MENTIONS_WARNING}.{0,100}(?=])/
@ -116,6 +118,7 @@ replace: "$&,$self.renderTooltip(arguments[0].guild)"
```
**Wrapping:**
```js
find: "#{intl::THREE_USERS_TYPING}"
match: /(?<="aria-atomic":!0,children:)\i/
@ -168,7 +171,6 @@ Use `definePluginSettings` from `@api/Settings`, not inline settings object.
From `@webpack/common`. **NEVER** hardcode `cdn.discordapp.com` URLs.
- `IconUtils.getUserAvatarURL(user, canAnimate?, size?)`
- `IconUtils.getDefaultAvatarURL(id)`
- `IconUtils.getUserBannerURL({ id, banner, canAnimate?, size })`
- `IconUtils.getGuildIconURL({ id, icon, size?, canAnimate? })`
- `IconUtils.getGuildBannerURL(guild, canAnimate?)`
@ -208,4 +210,3 @@ From `@webpack/common`. **NEVER** hardcode `cdn.discordapp.com` URLs.
- `"/api/v9"`, `"/users/@me"` ⟹ `Constants.Endpoints` or `RestAPI`
- `console.log/warn/error` ⟹ `Logger` from `@utils/Logger`
- `` `${a} ${b}` `` for class names ⟹ `classes(a, b)` from `@utils/misc`
- `"/assets/*.png"` for default avatars ⟹ `IconUtils.getDefaultAvatarURL(id)`

View file

@ -281,7 +281,7 @@ function resolvePendingAvatar(pendingChanges: PendingChanges | null): ImageInput
function normalizeImageValue(value: unknown): string | null {
if (typeof value === "string") return value;
if (value && typeof value === "object" && "imageUri" in value) {
const { imageUri } = value as { imageUri: unknown };
const { imageUri } = value as { imageUri: unknown; };
return typeof imageUri === "string" ? imageUri : null;
}
return null;

View file

@ -12,11 +12,11 @@ import { getCurrentChannel } from "@utils/discord";
import { ModalCloseButton, ModalContent, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
import definePlugin, { OptionType } from "@utils/types";
import { Message } from "@vencord/discord-types";
import { Button, Menu, TextInput, UploadHandler, useEffect, useState } from "@webpack/common";
import { Button, IconUtils, Menu, TextInput, UploadHandler, useEffect, useState } from "@webpack/common";
import { QuoteIcon } from "./components/QuoteIcon";
import { QuoteFont } from "./types";
import { createQuoteImage, ensureFontLoaded, generateFileNamePreview, getFileExtension, getMimeType, resetFontLoading, sizeUpgrade } from "./utils";
import { createQuoteImage, ensureFontLoaded, generateFileNamePreview, getFileExtension, getMimeType, resetFontLoading } from "./utils";
const settings = definePluginSettings({
quoteFont: {
@ -105,7 +105,7 @@ function QuoteModal({ message, ...props }: ModalProps & { message: Message; }) {
const generateImage = async () => {
const image = await createQuoteImage({
avatarUrl: sizeUpgrade(message.author.getAvatarURL()),
avatarUrl: IconUtils.getUserAvatarURL(message.author, true, 512),
quote: message.content,
grayScale: gray,
author: message.author,

View file

@ -21,12 +21,6 @@ interface CustomEmojiToken {
animated: boolean;
}
export function sizeUpgrade(url: string): string {
const u = new URL(url);
u.searchParams.set("size", "512");
return u.toString();
}
export function canvasToBlob(canvas: HTMLCanvasElement): Promise<Blob> {
return new Promise<Blob>((resolve, reject) => {
canvas.toBlob(blob => {