Spent too much time trying to fix main thread offload crash
This commit is contained in:
2
app.js
2
app.js
@@ -3,7 +3,7 @@ import express from "express";
|
|||||||
import {Logger} from "./wwwroot/core/logging/logger.js";
|
import {Logger} from "./wwwroot/core/logging/logger.js";
|
||||||
import {launch} from "./bot.js";
|
import {launch} from "./bot.js";
|
||||||
|
|
||||||
//await launch();
|
await launch();
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
|
|||||||
36
bot.js
36
bot.js
@@ -2,6 +2,7 @@ import {data} from "./wwwroot/core/appData.js";
|
|||||||
import JsonManager from "./wwwroot/core/utils/jsonManager.js";
|
import JsonManager from "./wwwroot/core/utils/jsonManager.js";
|
||||||
import {Logger} from "./wwwroot/core/logging/logger.js";
|
import {Logger} from "./wwwroot/core/logging/logger.js";
|
||||||
import {launchWorker} from "./wwwroot/core/namecards/workerLauncher.js";
|
import {launchWorker} from "./wwwroot/core/namecards/workerLauncher.js";
|
||||||
|
import {AttachmentBuilder} from "discord.js";
|
||||||
|
|
||||||
const launch = async () => {
|
const launch = async () => {
|
||||||
try{
|
try{
|
||||||
@@ -18,16 +19,37 @@ const launch = async () => {
|
|||||||
await data.sender.send(data.socialChannelID, message)
|
await data.sender.send(data.socialChannelID, message)
|
||||||
});
|
});
|
||||||
|
|
||||||
data.client.once('clientReady', async () => {
|
/*data.client.once('clientReady', async () => {
|
||||||
await data.sender.send(data.updateChannelID, "I'm now online ! ✅")
|
await data.sender.send(data.updateChannelID, "I'm now online ! ✅")
|
||||||
console.log(`✅ Logged in as ${data.client.user.tag}`);
|
console.log(`✅ Logged in as ${data.client.user.tag}`);
|
||||||
});
|
});*/
|
||||||
|
|
||||||
data.client.on('messageCreate', (message) => {
|
data.client.on('messageCreate', async (message) => {
|
||||||
const isGuildOwner = message.guild && message.author.id === message.guild.ownerId;
|
const isGuildOwner = message.guild && message.author.id === message.guild.ownerId;
|
||||||
if (message.content === '/login' && isGuildOwner) {
|
if (message.content === '/login' && isGuildOwner) {
|
||||||
message.reply(data.instagramTokenManager.getOauthUrl());
|
message.reply(data.instagramTokenManager.getOauthUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (message.content === '/name-card-test') {
|
||||||
|
try {
|
||||||
|
const member = message.member;
|
||||||
|
const avatarUrl = message.author.displayAvatarURL({ extension: 'png', size: 512 });
|
||||||
|
const username = member.displayName;
|
||||||
|
|
||||||
|
const result = await launchWorker({
|
||||||
|
templatePath: data.nameCardTemplate,
|
||||||
|
avatarURL: avatarUrl,
|
||||||
|
username: username,
|
||||||
|
});
|
||||||
|
|
||||||
|
const attachment = new AttachmentBuilder(Buffer.from(result.result), { name: 'namecard.png' });
|
||||||
|
const channel = await message.guild.channels.fetch(data.welcomeChannelID);
|
||||||
|
await channel.send({ content: `Welcome ${username}!`, files: [attachment] });
|
||||||
|
console.log('Name card sent!');
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to generate/send name card:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
data.client.on('guildMemberAdd', async member => {
|
data.client.on('guildMemberAdd', async member => {
|
||||||
@@ -37,7 +59,9 @@ const launch = async () => {
|
|||||||
avatarURL: member.user.avatarURL,
|
avatarURL: member.user.avatarURL,
|
||||||
displayName: member.user.displayName,
|
displayName: member.user.displayName,
|
||||||
}).then(buffer => {
|
}).then(buffer => {
|
||||||
//Send name card here...
|
const attachment = new AttachmentBuilder(buffer, { name: 'namecard.png' });
|
||||||
|
const channel = member.guild.channels.cache.get(data.welcomeChannelID);
|
||||||
|
channel.send({ files: [attachment] });
|
||||||
console.log('Name card sent!');
|
console.log('Name card sent!');
|
||||||
}).catch(console.error);
|
}).catch(console.error);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -45,7 +69,7 @@ const launch = async () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on('SIGINT', async () => {
|
/*process.on('SIGINT', async () => {
|
||||||
try {
|
try {
|
||||||
await data.sender.send(data.updateChannelID, "I'm shutting down, now. Bye! 👋")
|
await data.sender.send(data.updateChannelID, "I'm shutting down, now. Bye! 👋")
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -54,7 +78,7 @@ const launch = async () => {
|
|||||||
await data.client.destroy();
|
await data.client.destroy();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
});
|
});*/
|
||||||
|
|
||||||
await data.client.login(process.env.DISCORD_TOKEN);
|
await data.client.login(process.env.DISCORD_TOKEN);
|
||||||
data.instagramPoller.start(600000);
|
data.instagramPoller.start(600000);
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 559 KiB After Width: | Height: | Size: 556 KiB |
@@ -22,6 +22,7 @@ const instagramSecret = process.env.INSTAGRAM_CLIENT_SECRET;
|
|||||||
|
|
||||||
const updateChannelID = process.env.BOT_UPDATE_CHANNEL_ID;
|
const updateChannelID = process.env.BOT_UPDATE_CHANNEL_ID;
|
||||||
const socialChannelID = process.env.SOCIAL_CHANNEL_ID
|
const socialChannelID = process.env.SOCIAL_CHANNEL_ID
|
||||||
|
const welcomeChannelID = process.env.WELCOME_CHANNEL_ID
|
||||||
|
|
||||||
const filePath = ".instagram_client_tokens.json";
|
const filePath = ".instagram_client_tokens.json";
|
||||||
|
|
||||||
@@ -39,12 +40,12 @@ export const data = {
|
|||||||
instagramPoller,
|
instagramPoller,
|
||||||
updateChannelID,
|
updateChannelID,
|
||||||
socialChannelID,
|
socialChannelID,
|
||||||
|
welcomeChannelID,
|
||||||
instagramTokenManager,
|
instagramTokenManager,
|
||||||
nameCardTemplate
|
nameCardTemplate
|
||||||
//tiktokTokenManager
|
//tiktokTokenManager
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
const tiktokTokenManager = new TikTokTokenManager(
|
const tiktokTokenManager = new TikTokTokenManager(
|
||||||
{filepath : ".tiktok_client_tokens.json", clientKey : "", clientSecret : ""}
|
{filepath : ".tiktok_client_tokens.json", clientKey : "", clientSecret : ""}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { createCanvas, loadImage, registerFont } from "canvas";
|
|||||||
export class NameCardCreator {
|
export class NameCardCreator {
|
||||||
constructor(templatePath) {
|
constructor(templatePath) {
|
||||||
this.templatePath = templatePath;
|
this.templatePath = templatePath;
|
||||||
this.loadFont("./wwwroot/assets/fonts/Fredoka/static/Fredoka-Bold.ttf")
|
this.loadFont("./wwwroot/assets/fonts/Fredoka/static/Fredoka-Bold.ttf");
|
||||||
}
|
}
|
||||||
|
|
||||||
loadFont(fontPath) {
|
loadFont(fontPath) {
|
||||||
@@ -13,27 +13,31 @@ export class NameCardCreator {
|
|||||||
if (!fs.existsSync(fullPath)) {
|
if (!fs.existsSync(fullPath)) {
|
||||||
throw new Error(`Font file not found at ${fullPath}`);
|
throw new Error(`Font file not found at ${fullPath}`);
|
||||||
}
|
}
|
||||||
registerFont(fullPath, {family: "Fredoka Bold"});
|
registerFont(fullPath, { family: "Fredoka Bold" });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crée la carte de bienvenue entièrement via Canvas
|
*
|
||||||
|
* @param avatarPath
|
||||||
|
* @param name
|
||||||
|
* @returns {Promise<Buffer>}
|
||||||
*/
|
*/
|
||||||
async getWelcomeCard(avatarPath, name) {
|
async getWelcomeCard(avatarPath, name) {
|
||||||
|
let canvas, ctx, smallCanvas, smallCtx;
|
||||||
try {
|
try {
|
||||||
const canvasWidth = 3000;
|
const canvasWidth = 3000;
|
||||||
const canvasHeight = 1000;
|
const canvasHeight = 1000;
|
||||||
const canvas = createCanvas(canvasWidth, canvasHeight);
|
canvas = createCanvas(canvasWidth, canvasHeight);
|
||||||
const ctx = canvas.getContext("2d");
|
ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
const template = await loadImage(this.templatePath);
|
const template = await loadImage(this.templatePath);
|
||||||
ctx.drawImage(template, 0, 0, canvasWidth, canvasHeight);
|
ctx.drawImage(template, 0, 0, canvasWidth, canvasHeight);
|
||||||
|
|
||||||
const avatarSize = 675;
|
const avatarSize = 675;
|
||||||
const avatar = await loadImage(avatarPath);
|
const avatar = await loadImage(avatarPath);
|
||||||
|
|
||||||
const avatarX = 225;
|
const avatarX = 225;
|
||||||
const avatarY = (canvasHeight - avatarSize) / 2;
|
const avatarY = (canvasHeight - avatarSize) / 2;
|
||||||
|
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.arc(
|
ctx.arc(
|
||||||
@@ -63,11 +67,10 @@ export class NameCardCreator {
|
|||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
|
|
||||||
const messageX = avatarX + 1525;
|
const messageX = avatarX + 1525;
|
||||||
const messageY = (canvasHeight / 2)+75;
|
const messageY = (canvasHeight / 2) + 75;
|
||||||
ctx.fillStyle = "#ede6e6";
|
ctx.fillStyle = "#ede6e6";
|
||||||
ctx.textAlign = "center";
|
ctx.textAlign = "center";
|
||||||
ctx.textBaseline = "middle";
|
ctx.textBaseline = "middle";
|
||||||
|
|
||||||
ctx.font = '115px "Fredoka Bold"';
|
ctx.font = '115px "Fredoka Bold"';
|
||||||
|
|
||||||
const lines = [`Welcome ${name}, to the`, "Spicy Jail ~"];
|
const lines = [`Welcome ${name}, to the`, "Spicy Jail ~"];
|
||||||
@@ -78,31 +81,24 @@ export class NameCardCreator {
|
|||||||
ctx.fillText(line, messageX, startY + i * lineHeight);
|
ctx.fillText(line, messageX, startY + i * lineHeight);
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = this.scallDown(canvas, 1500, 500)
|
smallCanvas = createCanvas(1500, 500);
|
||||||
|
smallCtx = smallCanvas.getContext("2d");
|
||||||
|
smallCtx.drawImage(canvas, 0, 0, 1500, 500);
|
||||||
|
|
||||||
fs.writeFileSync("./tests/result/namecard.png", result);
|
return smallCanvas.toBuffer();
|
||||||
console.log("✅ Name card created: namecard.png");
|
|
||||||
return result;
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Error creating name card:", err);
|
console.error("Error creating name card:", err);
|
||||||
throw err;
|
throw err;
|
||||||
|
} finally {
|
||||||
|
canvas.width = 0;
|
||||||
|
canvas.height = 0;
|
||||||
|
smallCanvas.width = 0;
|
||||||
|
smallCanvas.height = 0;
|
||||||
|
|
||||||
|
canvas = null;
|
||||||
|
smallCanvas = null;
|
||||||
|
ctx = null;
|
||||||
|
smallCtx = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param target
|
|
||||||
* @param width
|
|
||||||
* @param height
|
|
||||||
* @returns {Buffer}
|
|
||||||
*/
|
|
||||||
scallDown(target, width, height) {
|
|
||||||
const smallCanvas = createCanvas(width, height);
|
|
||||||
const smallCtx = smallCanvas.getContext('2d');
|
|
||||||
|
|
||||||
smallCtx.drawImage(target, 0, 0, width, height);
|
|
||||||
return smallCanvas.toBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,20 +8,9 @@ parentPort.on("message", async (data) => {
|
|||||||
const creator = new NameCardCreator(templatePath);
|
const creator = new NameCardCreator(templatePath);
|
||||||
const buffer = await creator.getWelcomeCard(avatarURL, username);
|
const buffer = await creator.getWelcomeCard(avatarURL, username);
|
||||||
|
|
||||||
parentPort.postMessage({ result: buffer });
|
parentPort.postMessage({ result: buffer }, [buffer.buffer]);
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
parentPort.postMessage({ error: err.message });
|
parentPort.postMessage({ error: err.message });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/*(async () => {
|
|
||||||
try {
|
|
||||||
const { creator, avatarURL, userName } = workerData;
|
|
||||||
|
|
||||||
const buffer = await creator.getWelcomeCard(avatarURL, userName);
|
|
||||||
|
|
||||||
parentPort.postMessage(buffer); // return the buffer to main thread
|
|
||||||
} catch (err) {
|
|
||||||
parentPort.postMessage({ error: err.message });
|
|
||||||
}
|
|
||||||
})();*/
|
|
||||||
@@ -1,31 +1,44 @@
|
|||||||
import path from "path";
|
import path from "path";
|
||||||
import { Worker } from 'worker_threads';
|
import { Worker } from 'worker_threads';
|
||||||
import {Logger} from "../logging/logger.js";
|
import { fileURLToPath } from 'url';
|
||||||
|
|
||||||
function launchWorker({templatePath, avatarURL, username}) {
|
/**
|
||||||
|
*
|
||||||
|
* @param templatePath
|
||||||
|
* @param avatarURL
|
||||||
|
* @param username
|
||||||
|
* @returns {Promise<unknown>}
|
||||||
|
*/
|
||||||
|
function launchWorker({ templatePath, avatarURL, username }) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const workerFile = path.resolve('./wwwroot/core/namecards/nameCardWorker.js');
|
|
||||||
|
const filename = fileURLToPath(import.meta.url);
|
||||||
|
const dirname = path.dirname(filename);
|
||||||
|
const workerFile = path.join(dirname, 'nameCardWorker.js');
|
||||||
|
|
||||||
const worker = new Worker(workerFile);
|
const worker = new Worker(workerFile);
|
||||||
|
|
||||||
worker.postMessage({templatePath, avatarURL, username});
|
worker.postMessage({ templatePath, avatarURL, username });
|
||||||
|
|
||||||
worker.on('message', (result) => {
|
worker.once('message', async (result) => {
|
||||||
|
console.log("worker terminated");
|
||||||
resolve(result);
|
resolve(result);
|
||||||
worker.terminate()
|
|
||||||
.catch(err => Logger.error("Unable to terminate worker", err.message));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
worker.on('error', (err) => {
|
worker.once('error', async (err) => {
|
||||||
reject(err);
|
reject(err);
|
||||||
worker.terminate()
|
|
||||||
.catch(err => Logger.error("Unable to terminate worker", err.message));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
worker.on('exit', (code) => {
|
worker.once('exit', async (code) => {
|
||||||
if (code !== 0) reject(new Error(`Worker stopped with code ${code}`));
|
if (code === 0) {
|
||||||
|
console.log('Worker exited cleanly.');
|
||||||
|
} else {
|
||||||
|
console.warn('Worker exited with error code:', code);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export {launchWorker}
|
export {launchWorker}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user