fix: strip query params from asset URLs before filesystem lookup
All checks were successful
Deploy to Production / test (push) Successful in 36s
All checks were successful
Deploy to Production / test (push) Successful in 36s
Icon URLs stored with cache-busting query params (e.g. ?v=123) caused existsSync to fail, preventing Discord attachment fallback and leaving unresolvable localhost URLs as thumbnails. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,7 +18,7 @@ import { join } from "path";
|
|||||||
import { existsSync } from "fs";
|
import { existsSync } from "fs";
|
||||||
import { LootType, EffectType } from "@shared/lib/constants";
|
import { LootType, EffectType } from "@shared/lib/constants";
|
||||||
import type { LootTableItem } from "@shared/lib/types";
|
import type { LootTableItem } from "@shared/lib/types";
|
||||||
import { getRarityConfig, defaultName } from "@shared/lib/rarity";
|
import { getRarityConfig, defaultName, stripQuery } from "@shared/lib/rarity";
|
||||||
|
|
||||||
export function getShopListingMessage(
|
export function getShopListingMessage(
|
||||||
item: {
|
item: {
|
||||||
@@ -40,7 +40,7 @@ export function getShopListingMessage(
|
|||||||
|
|
||||||
// Handle local icon
|
// Handle local icon
|
||||||
if (item.iconUrl && isLocalAssetUrl(item.iconUrl)) {
|
if (item.iconUrl && isLocalAssetUrl(item.iconUrl)) {
|
||||||
const iconPath = join(process.cwd(), "bot/assets/graphics", item.iconUrl.replace(/^\/?assets\//, ""));
|
const iconPath = join(process.cwd(), "bot/assets/graphics", stripQuery(item.iconUrl).replace(/^\/?assets\//, ""));
|
||||||
if (existsSync(iconPath)) {
|
if (existsSync(iconPath)) {
|
||||||
const iconName = defaultName(item.iconUrl);
|
const iconName = defaultName(item.iconUrl);
|
||||||
files.push(new AttachmentBuilder(iconPath, { name: iconName }));
|
files.push(new AttachmentBuilder(iconPath, { name: iconName }));
|
||||||
@@ -53,7 +53,7 @@ export function getShopListingMessage(
|
|||||||
if (item.imageUrl === item.iconUrl && thumbnailUrl?.startsWith("attachment://")) {
|
if (item.imageUrl === item.iconUrl && thumbnailUrl?.startsWith("attachment://")) {
|
||||||
displayImageUrl = thumbnailUrl;
|
displayImageUrl = thumbnailUrl;
|
||||||
} else {
|
} else {
|
||||||
const imagePath = join(process.cwd(), "bot/assets/graphics", item.imageUrl.replace(/^\/?assets\//, ""));
|
const imagePath = join(process.cwd(), "bot/assets/graphics", stripQuery(item.imageUrl).replace(/^\/?assets\//, ""));
|
||||||
if (existsSync(imagePath)) {
|
if (existsSync(imagePath)) {
|
||||||
const imageName = defaultName(item.imageUrl);
|
const imageName = defaultName(item.imageUrl);
|
||||||
if (!files.find(f => f.name === imageName)) {
|
if (!files.find(f => f.name === imageName)) {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import {
|
|||||||
MessageFlags,
|
MessageFlags,
|
||||||
} from "discord.js";
|
} from "discord.js";
|
||||||
import { resolveAssetUrl, isLocalAssetUrl } from "@shared/lib/assets";
|
import { resolveAssetUrl, isLocalAssetUrl } from "@shared/lib/assets";
|
||||||
import { getRarityConfig, defaultName } from "@shared/lib/rarity";
|
import { getRarityConfig, defaultName, stripQuery } from "@shared/lib/rarity";
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
import { existsSync } from "fs";
|
import { existsSync } from "fs";
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ export function getLootboxResultMessage(
|
|||||||
const iconSource = lootResult.rewardType === "ITEM" ? lootResult.item?.iconUrl : item?.iconUrl;
|
const iconSource = lootResult.rewardType === "ITEM" ? lootResult.item?.iconUrl : item?.iconUrl;
|
||||||
if (iconSource) {
|
if (iconSource) {
|
||||||
if (isLocalAssetUrl(iconSource)) {
|
if (isLocalAssetUrl(iconSource)) {
|
||||||
const iconPath = join(process.cwd(), "bot/assets/graphics", iconSource.replace(/^\/?assets\//, ""));
|
const iconPath = join(process.cwd(), "bot/assets/graphics", stripQuery(iconSource).replace(/^\/?assets\//, ""));
|
||||||
if (existsSync(iconPath)) {
|
if (existsSync(iconPath)) {
|
||||||
const iconName = defaultName(iconSource);
|
const iconName = defaultName(iconSource);
|
||||||
files.push(new AttachmentBuilder(iconPath, { name: iconName }));
|
files.push(new AttachmentBuilder(iconPath, { name: iconName }));
|
||||||
@@ -150,7 +150,7 @@ export function getLootboxResultMessage(
|
|||||||
if (imgSource && imgSource !== iconSrc) {
|
if (imgSource && imgSource !== iconSrc) {
|
||||||
let displayImageUrl: string | null = null;
|
let displayImageUrl: string | null = null;
|
||||||
if (isLocalAssetUrl(imgSource)) {
|
if (isLocalAssetUrl(imgSource)) {
|
||||||
const imagePath = join(process.cwd(), "bot/assets/graphics", imgSource.replace(/^\/?assets\//, ""));
|
const imagePath = join(process.cwd(), "bot/assets/graphics", stripQuery(imgSource).replace(/^\/?assets\//, ""));
|
||||||
if (existsSync(imagePath)) {
|
if (existsSync(imagePath)) {
|
||||||
const imageName = defaultName(imgSource);
|
const imageName = defaultName(imgSource);
|
||||||
if (!files.find(f => f.name === imageName)) {
|
if (!files.find(f => f.name === imageName)) {
|
||||||
|
|||||||
@@ -18,5 +18,11 @@ export function getRarityConfig(rarity: string): { color: number; emoji: string;
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function defaultName(path: string): string {
|
export function defaultName(path: string): string {
|
||||||
return path.split("/").pop() || "image.png";
|
return stripQuery(path).split("/").pop() || "image.png";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Strip query parameters from a URL/path (e.g. "foo.png?v=123" → "foo.png") */
|
||||||
|
export function stripQuery(url: string): string {
|
||||||
|
const idx = url.indexOf("?");
|
||||||
|
return idx === -1 ? url : url.slice(0, idx);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user