I have a bot which responds to the !stock
command.
When a user types !stock
, the user message is deleted & an embed is sent to the channel with an image as an attachment.
This image is uniquely generated via Puppeteer (using an HTML string that I build based on some Mongo data I retrieve from a database).
Here is my code:
const config = require('../config');
const {
doesGivenUserHaveGivenRole,
generateStockImage
} = require('../utils');
module.exports = {
name: 'stock',
description: 'Use to post the latest stock levels',
guildOnly: true,
async execute(message, args) {
// don't allow arguments
if (args && args.length > 0) return;
// ignore if we're not an admin
if (!doesGivenUserHaveGivenRole(message, message.author.id, config.ADMIN_ROLE_ID)) return;
// delete the author's message
message.delete();
// generate a new HTML string & return an embed to send to the channel
const generatedStockImage = await generateStockImage();
// send that message
message.channel.send(generatedStockImage).then(message => {
// then every minute
setInterval(async () => {
// get the image again
const generatedEdit = await generateStockImage();
// edit the original message with the new image (simple, right?)
message.edit(generatedEdit);
}, 60000);
});
}
};
The generateStockImage
function looks like this:
const generateStockImage = async () => {
// check if the image already exists
if (fs.existsSync('./image.png')) {
// if it does
fs.unlink('./image.png', (err) => {
if (err) {
console.error(err)
return;
}
// remove it, as we want to generate a new one for sure
console.log('removed');
});
}
// get my data from MongoDB
const stock = await getStock();
console.log(stock[0].stock);
let html = `<!DOCTYPE html><html><head><style>body{background-color: black; color: white;width: 870px;height: 225px;}table{font-family: arial, sans-serif; border-collapse: collapse;}td, th{border: 1px solid #dddddd; padding: 4px; text-align: center;}.denomination{text-align: centre; font-size: 14px;margin: 0px 0px 10px 0px;}.amount{font-size: 35px;}.container{display: flex;}.table{margin: 0px 5px 0px 0px; width: 100%;}.green{color: #2ecc71;}.yellow{color: #f1c40f;}.red{color: #c45563;}.icon{width:20px;height:20px;padding-right:3px}</style></head><body><div class="container"> `;
stock.forEach(code => {
let colour;
if (code.stock >= 100) {
colour = 'green';
}
if (code.stock <= 50) {
colour = 'yellow';
}
if (code.stock === 0) {
colour = 'red';
}
html += `<!-- some html code I generate dynamically based on stock (above) ${code.something} -->`;
});
// close my html
html += `</div></body></html>`;
// create a new puppeteer browser
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({
width: 880,
height: 235,
deviceScaleFactor: 1,
});
await page.setContent(html);
await page.screenshot({ path: './image.png' }); // take a screenshot of the page we generated
await browser.close();
// wait for 8 seconds (to make sure the image is written to file first)
await sleep(8000);
const buffer = fs.readFileSync('./image.png');
const attachment = new Discord.MessageAttachment(buffer, 'image.png');
const embedToReturn = {
embed: {
color: '#4287f5',
title: 'Current Stock',
files: [attachment],
image: {
url: 'attachment://image.png'
},
timestamp: new Date(),
footer: {
text: 'My Bot Name',
icon_url: 'https://i.imgur.com/myBotLogo.png',
}
}
}
console.log(embedToReturn);
return embedToReturn; // return the new embed value
}
My code successfully generates a new image, based on the database data, and saves it to the project root.
I can open the file & see that it is in fact a newly generated image, based on the data I receive from MongoDB.
This image is then successfully posted the first time the command is ran, but does not update on subsequent 'edits'.
The issue I am facing is that the generated image does not get updated in my embed.
When the message.edit
event gets triggered, it appears that it does not use generatedEdit
.
The image remains exactly the same, even though the embed has a new timestamp & the (edited)
text on the message itself.
It successfully 'edits' the message every minute, but just doesn't show me the latest generated image (even though that image is in my project root, and I can see that it has been updated).
I have a feeling it's the following line that's causing the issues:const attachment = new Discord.MessageAttachment(buffer, 'image.png');
Is this something to do with the discord cache? What am I doing wrong?
console.log
ing thegeneratedEdit
right before you edit the message to make sure that it is the right image that you are trying to send? – Levi_OP