Skip to content

Commit b3b7f7d

Browse files
committed
Fix bug were some frames did not want to generate
1 parent 7b71e70 commit b3b7f7d

3 files changed

Lines changed: 42 additions & 21 deletions

File tree

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"typescript-eslint": "^8.52.0"
3030
},
3131
"dependencies": {
32-
"canvas": "^3.2.0",
32+
"canvas": "^3.2.3",
3333
"cors": "^2.8.5",
3434
"dotenv": "^17.2.3",
3535
"express": "^5.2.0",

src/helpers/generateFrame.ts

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
process.env.FONTCONFIG_PATH = "/dev/null";
12
import { createCanvas, Image, loadImage, registerFont } from "canvas";
23
import path from "path";
34
import { fetchGuildConfig } from "../models/guildSchema";
@@ -41,30 +42,28 @@ export const generateFrame = async (
4142
ctx.fillStyle = hexColor;
4243
ctx.fillRect(0, 0, width, height);
4344

44-
const fileBuffer = fs.readFileSync(framePath);
45-
if (!fileBuffer) return null;
46-
47-
//Loads frame
48-
await loadImage(fileBuffer).then((img: Image) =>
49-
ctx.drawImage(img, 0, 0, width, height),
50-
);
45+
const bgImg = await safeLoadImage(framePath);
46+
if (bgImg) ctx.drawImage(bgImg, 0, 0, width, height);
5147

5248
//loads avatar
5349
if (memberAvatar) {
5450
const pngAvatar = memberAvatar.replace(/\.webp(\?.*)?$/, ".png$1");
55-
await loadImage(pngAvatar).then((img: Image) =>
56-
ctx.drawImage(img, width / 2 - 125, 80, 250, 250),
57-
);
51+
const avatarImg = await safeLoadImage(pngAvatar);
52+
if (avatarImg) {
53+
ctx.drawImage(avatarImg, width / 2 - 125, 80, 250, 250);
54+
}
5855
}
5956

57+
const fallbackFont = '"Sansumu", "Arial"';
58+
6059
//writes name
61-
ctx.font = "50pt Sansumu";
60+
ctx.font = `50pt ${fallbackFont}`;
6261
ctx.textAlign = "center";
6362
ctx.fillStyle = "#FFFFFF";
6463
ctx.fillText(name, width / 2, 400);
6564

6665
//writes level
67-
ctx.font = "40pt Sansumu";
66+
ctx.font = `40pt ${fallbackFont}`;
6867
ctx.fillText(`Level: ${level}`, width / 2, 470);
6968

7069
//renders xp bar
@@ -77,14 +76,13 @@ export const generateFrame = async (
7776
roundRect(ctx, 65, 500, bar, 40, 20, true, false);
7877

7978
//writes xp amount
80-
ctx.font = "40pt Sansumu";
79+
ctx.font = `40pt ${fallbackFont}`;
8180
ctx.fillText(`${xpPercentage}%`, width / 2, 600);
8281

8382
//loads foreground frame if there is one
8483
if (foregroundFramePath != null) {
85-
await loadImage(foregroundFramePath).then((img: Image) =>
86-
ctx.drawImage(img, 0, 0, width, height),
87-
);
84+
const fgImg = await safeLoadImage(foregroundFramePath);
85+
if (fgImg) ctx.drawImage(fgImg, 0, 0, width, height);
8886
}
8987

9088
//returns the image
@@ -143,3 +141,26 @@ export const roundRect = (
143141
ctx.stroke();
144142
}
145143
};
144+
145+
const safeLoadImage = async (source: string): Promise<Image | null> => {
146+
try {
147+
// If it's a URL (Avatar or hosted frame)
148+
if (source.startsWith("http://") || source.startsWith("https://")) {
149+
const response = await fetch(source);
150+
if (!response.ok) return null;
151+
const arrayBuffer = await response.arrayBuffer();
152+
return await loadImage(Buffer.from(arrayBuffer));
153+
}
154+
155+
// If it's a local file path
156+
if (fs.existsSync(source)) {
157+
const fileBuffer = fs.readFileSync(source);
158+
return await loadImage(fileBuffer);
159+
}
160+
161+
return null;
162+
} catch (error) {
163+
console.error(`Failed to load image from ${source}:`, error);
164+
return null;
165+
}
166+
};

0 commit comments

Comments
 (0)