Channel.messages.fetch(id) giving mixed results

My bot uses the embed fields to match an Array from the embed to their character stats. On Desktop this issue doesn't seem to happen. When testing the submit command from mobile the statRoll message is giving me 2 different values. Sometimes the embeds are there and sometimes they are gone. Everything else looks to be the same. Correct response (no errors):
{
channelId: "984143582027972681",
guildId: "984143580241211412",
id: "1152294200927334420",
createdTimestamp: 1694798746092,
type: 0,
system: false,
content: "<@1080207865861644328> rolled stats...",
author: {
id: "261302296103747584",
bot: true,
system: false,
flags: {
bitfield: 65536,
},
username: "Avrae",
globalName: null,
discriminator: "6944",
avatar: "b4926b52f7f1c966e01e25f0b33253f1",
banner: null,
accentColor: null,
avatarDecoration: null,
},
pinned: false,
tts: false,
nonce: null,
embeds: [
{
data: {
type: "rich",
title: "Generating Random Stats",
description: "**Server Settings:**\n● Minimum of 72\n● Maximum of 86\n● At least 2 over 14\n● At least 1 under 12",
color: 15036310,
fields: [
{
name: "Stats",
value: "**Stat 1:** 4d6kh3 (~~**1**~~, **6**, 3, **6**) = `15`\n**Stat 2:** 4d6kh3 (~~2~~, **6**, 4, **6**) = `16`\n**Stat 3:** 4d6kh3 (2, 5, ~~2~~, 3) = `10`\n**Stat 4:** 4d6kh3 (**6**, ~~3~~, 4, 5) = `15`\n**Stat 5:** 4d6kh3 (3, **6**, **6**, ~~2~~) = `15`\n**Stat 6:** 4d6kh3 (2, **6**, 3, ~~2~~) = `11`\n-----\nTotal = `82`",
inline: true,
},
],
},
},
],
components: [
],
attachments: {
},
stickers: {
},
position: null,
roleSubscriptionData: null,
editedTimestamp: null,
reactions: {
message: [Circular],
},
mentions: {
everyone: false,
users: {
},
roles: {
},
_members: null,
_channels: null,
_parsedUsers: null,
crosspostedChannels: {
},
repliedUser: null,
},
webhookId: null,
groupActivityApplication: null,
applicationId: null,
activity: null,
flags: {
bitfield: 0,
},
reference: null,
interaction: null,
}
{
channelId: "984143582027972681",
guildId: "984143580241211412",
id: "1152294200927334420",
createdTimestamp: 1694798746092,
type: 0,
system: false,
content: "<@1080207865861644328> rolled stats...",
author: {
id: "261302296103747584",
bot: true,
system: false,
flags: {
bitfield: 65536,
},
username: "Avrae",
globalName: null,
discriminator: "6944",
avatar: "b4926b52f7f1c966e01e25f0b33253f1",
banner: null,
accentColor: null,
avatarDecoration: null,
},
pinned: false,
tts: false,
nonce: null,
embeds: [
{
data: {
type: "rich",
title: "Generating Random Stats",
description: "**Server Settings:**\n● Minimum of 72\n● Maximum of 86\n● At least 2 over 14\n● At least 1 under 12",
color: 15036310,
fields: [
{
name: "Stats",
value: "**Stat 1:** 4d6kh3 (~~**1**~~, **6**, 3, **6**) = `15`\n**Stat 2:** 4d6kh3 (~~2~~, **6**, 4, **6**) = `16`\n**Stat 3:** 4d6kh3 (2, 5, ~~2~~, 3) = `10`\n**Stat 4:** 4d6kh3 (**6**, ~~3~~, 4, 5) = `15`\n**Stat 5:** 4d6kh3 (3, **6**, **6**, ~~2~~) = `15`\n**Stat 6:** 4d6kh3 (2, **6**, 3, ~~2~~) = `11`\n-----\nTotal = `82`",
inline: true,
},
],
},
},
],
components: [
],
attachments: {
},
stickers: {
},
position: null,
roleSubscriptionData: null,
editedTimestamp: null,
reactions: {
message: [Circular],
},
mentions: {
everyone: false,
users: {
},
roles: {
},
_members: null,
_channels: null,
_parsedUsers: null,
crosspostedChannels: {
},
repliedUser: null,
},
webhookId: null,
groupActivityApplication: null,
applicationId: null,
activity: null,
flags: {
bitfield: 0,
},
reference: null,
interaction: null,
}
Embeds missing:
{
channelId: "984143582027972681",
guildId: "984143580241211412",
id: "1152294200927334420",
createdTimestamp: 1694798746092,
type: 0,
system: false,
content: "<@1080207865861644328> rolled stats...",
author: {
id: "261302296103747584",
bot: true,
system: false,
flags: {
bitfield: 65536,
},
username: "Avrae",
globalName: null,
discriminator: "6944",
avatar: "b4926b52f7f1c966e01e25f0b33253f1",
banner: null,
accentColor: null,
avatarDecoration: null,
},
pinned: false,
tts: false,
nonce: null,
embeds: [
],
components: [
],
attachments: {
},
stickers: {
},
position: null,
roleSubscriptionData: null,
editedTimestamp: null,
reactions: {
message: [Circular],
},
mentions: {
everyone: false,
users: {
},
roles: {
},
_members: null,
_channels: null,
_parsedUsers: null,
crosspostedChannels: {
},
repliedUser: null,
},
webhookId: null,
groupActivityApplication: null,
applicationId: null,
activity: null,
flags: {
bitfield: 0,
},
reference: null,
interaction: null,
}
{
channelId: "984143582027972681",
guildId: "984143580241211412",
id: "1152294200927334420",
createdTimestamp: 1694798746092,
type: 0,
system: false,
content: "<@1080207865861644328> rolled stats...",
author: {
id: "261302296103747584",
bot: true,
system: false,
flags: {
bitfield: 65536,
},
username: "Avrae",
globalName: null,
discriminator: "6944",
avatar: "b4926b52f7f1c966e01e25f0b33253f1",
banner: null,
accentColor: null,
avatarDecoration: null,
},
pinned: false,
tts: false,
nonce: null,
embeds: [
],
components: [
],
attachments: {
},
stickers: {
},
position: null,
roleSubscriptionData: null,
editedTimestamp: null,
reactions: {
message: [Circular],
},
mentions: {
everyone: false,
users: {
},
roles: {
},
_members: null,
_channels: null,
_parsedUsers: null,
crosspostedChannels: {
},
repliedUser: null,
},
webhookId: null,
groupActivityApplication: null,
applicationId: null,
activity: null,
flags: {
bitfield: 0,
},
reference: null,
interaction: null,
}
6 Replies
d.js toolkit
d.js toolkit9mo ago
- What's your exact discord.js npm list discord.js and node node -v version? - Not a discord.js issue? Check out #other-js-ts. - Consider reading #how-to-get-help to improve your question! - Explain what exactly your issue is. - Post the full error stack trace, not just the top part! - Show your code! - Issue solved? Press the button! - Marked as resolved by staff
Deleted User
Deleted User9mo ago
Do you have MessageContent intent enabled?
WhacK
WhacK9mo ago
Yes. The message always comes through on the desktop client but when testing on mobile sometimes Message.embeds is empty when there’s definitely an embed
WhacK
WhacK9mo ago
No description
Deleted User
Deleted User9mo ago
I am unsure what's happening here, will just leave it for someone proficient to assist you.
WhacK
WhacK9mo ago
const message = await channel.messages.fetch(msgId).catch((e) => null)
const message = await channel.messages.fetch(msgId).catch((e) => null)
Let me paste it all for you It’s another bots message sent in a predetermined channel called stat-rolls Slash Command:
public async chatInputSubmitCharacter(interaction: Command.ChatInputCommandInteraction) {
if (interaction.user.bot) return;
await interaction.deferReply({ ephemeral: true });

try {
const { options: args, channel: intChannel, user, guild } = interaction;
const channel = <TextChannel>guild.channels.cache.get(this.characterApprovalChannelId);
const statChannel = <TextChannel>guild.channels.cache.get(this.statRollChannelId);

const sheetUrl = args.getString('sheeturl');
if (isNullish(sheetUrl)) {
throw new Error('Please enter an sheet url to import');
}

//attempt to get ddb data from provided url
const urlSections = sheetUrl.split('/').reverse();
let raw: IBeyondData;
for (let section of urlSections) {
if (section && isNumber(section)) {
try {
raw = (await getBeyondData(section)).data;
} catch (error) {
throw new Error('Error trying to get DDB sheet:' + error.message);
}
}
}

if (raw === null) {
throw new Error('Unable to extract sheet information, please provide a public link.');
}

if (isNullishOrEmpty(raw.inventory)) {
throw new Error('Please complete your character inventory.');
}

let statRollMsg: Message<boolean>;
if (raw.configuration.abilityScoreType === StatGenerationMethodEnum.RolledStats) {
statRollMsg = await fetchMessageByLink(args.getString('staturl')).catch((e) =>
Promise.reject(`Please enter the link to the correct message in <#${this.statRollChannelId}>`)
);
}

const charData = await container.character.parseCharacterData(raw);

const reviewedData = container.character.reviewStatConformity(
raw.configuration.abilityScoreType,
charData,
isNullishOrEmpty(statRollMsg) ? null : statRollMsg.embeds.pop().fields
);

const submissionEmbed = await container.character.createApprovalEmbed(interaction, reviewedData, raw);

const approvalRow = new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setCustomId(`${CharaterCustomIds.Approve}_${interaction.user.id}_${charData.id}`)
.setStyle(ButtonStyle.Success)
.setLabel('Approve'),
new ButtonBuilder()
.setCustomId(`${CharaterCustomIds.Reject}_${interaction.user.id}_${charData.id}`)
.setStyle(ButtonStyle.Danger)
.setLabel('Reject')
);

await channel.send({
content: `Hey ${guild.roles.cache.get(AdminRoles.VANGUARD_ROLE)} and ${guild.roles.cache.get(AdminRoles.WARDEN_ROLE)}`,
embeds: [submissionEmbed],
components: [approvalRow]
});

const cached = await container.redis.insert(RedisKeys.Submission, `${interaction.user.id}:${charData.id}`, raw);
if (!cached) {
throw new Error('Unable to save submission.');
}

return interaction.editReply("Thanks! You're submission has been submitted. You will be notified upon review.");
} catch (error: any) {
console.error(error);
return interaction.reply({
content: error.message || 'An unexpected error occurred. If the problem persists, please contact a Code Weaver.',
ephemeral: true
});
}
}
public async chatInputSubmitCharacter(interaction: Command.ChatInputCommandInteraction) {
if (interaction.user.bot) return;
await interaction.deferReply({ ephemeral: true });

try {
const { options: args, channel: intChannel, user, guild } = interaction;
const channel = <TextChannel>guild.channels.cache.get(this.characterApprovalChannelId);
const statChannel = <TextChannel>guild.channels.cache.get(this.statRollChannelId);

const sheetUrl = args.getString('sheeturl');
if (isNullish(sheetUrl)) {
throw new Error('Please enter an sheet url to import');
}

//attempt to get ddb data from provided url
const urlSections = sheetUrl.split('/').reverse();
let raw: IBeyondData;
for (let section of urlSections) {
if (section && isNumber(section)) {
try {
raw = (await getBeyondData(section)).data;
} catch (error) {
throw new Error('Error trying to get DDB sheet:' + error.message);
}
}
}

if (raw === null) {
throw new Error('Unable to extract sheet information, please provide a public link.');
}

if (isNullishOrEmpty(raw.inventory)) {
throw new Error('Please complete your character inventory.');
}

let statRollMsg: Message<boolean>;
if (raw.configuration.abilityScoreType === StatGenerationMethodEnum.RolledStats) {
statRollMsg = await fetchMessageByLink(args.getString('staturl')).catch((e) =>
Promise.reject(`Please enter the link to the correct message in <#${this.statRollChannelId}>`)
);
}

const charData = await container.character.parseCharacterData(raw);

const reviewedData = container.character.reviewStatConformity(
raw.configuration.abilityScoreType,
charData,
isNullishOrEmpty(statRollMsg) ? null : statRollMsg.embeds.pop().fields
);

const submissionEmbed = await container.character.createApprovalEmbed(interaction, reviewedData, raw);

const approvalRow = new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setCustomId(`${CharaterCustomIds.Approve}_${interaction.user.id}_${charData.id}`)
.setStyle(ButtonStyle.Success)
.setLabel('Approve'),
new ButtonBuilder()
.setCustomId(`${CharaterCustomIds.Reject}_${interaction.user.id}_${charData.id}`)
.setStyle(ButtonStyle.Danger)
.setLabel('Reject')
);

await channel.send({
content: `Hey ${guild.roles.cache.get(AdminRoles.VANGUARD_ROLE)} and ${guild.roles.cache.get(AdminRoles.WARDEN_ROLE)}`,
embeds: [submissionEmbed],
components: [approvalRow]
});

const cached = await container.redis.insert(RedisKeys.Submission, `${interaction.user.id}:${charData.id}`, raw);
if (!cached) {
throw new Error('Unable to save submission.');
}

return interaction.editReply("Thanks! You're submission has been submitted. You will be notified upon review.");
} catch (error: any) {
console.error(error);
return interaction.reply({
content: error.message || 'An unexpected error occurred. If the problem persists, please contact a Code Weaver.',
ephemeral: true
});
}
}
Get messageId from discord link:
export async function fetchMessageByLink(messageLink: string) {
const [guildId, channelId, messageId] = messageLink.split('/');
const { client, _config } = container;

if (guildId !== _config.guildId) {
return Promise.reject('This can only be used in Engrimoore');
}

const channel = await client.guilds.cache
.get(guildId)
.channels.fetch(channelId)
.catch((e) => Promise.reject(e));

if (channel.isTextBased()) {
const message = await channel.messages.fetch(messageId).catch((e) => Promise.reject(e));

if (isNullish(message)) {
return Promise.reject('Unable to fetch message by url');
}
return message;
}

return Promise.reject('Must be run in an Engrimoore Text Channel.');
}
export async function fetchMessageByLink(messageLink: string) {
const [guildId, channelId, messageId] = messageLink.split('/');
const { client, _config } = container;

if (guildId !== _config.guildId) {
return Promise.reject('This can only be used in Engrimoore');
}

const channel = await client.guilds.cache
.get(guildId)
.channels.fetch(channelId)
.catch((e) => Promise.reject(e));

if (channel.isTextBased()) {
const message = await channel.messages.fetch(messageId).catch((e) => Promise.reject(e));

if (isNullish(message)) {
return Promise.reject('Unable to fetch message by url');
}
return message;
}

return Promise.reject('Must be run in an Engrimoore Text Channel.');
}
I hard code the ID in my database, I am definitely getting the right message just sometime embeds are there and sometimes not I didn't know that about channels I'll change that back originally I didn't fetch changed that last night Is the Avrae D&D bot. It takes a commands !rollstats and generates an embed with the array of stats my bot is only for running my d&d westmarch not made for all servers I'm thinking it may edit it because that might be why sometimes they are there and sometimes not ok let me double check rn not edited Yes
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildEmojisAndStickers,
GatewayIntentBits.GuildVoiceStates,
GatewayIntentBits.GuildWebhooks,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.GuildMessageReactions,
GatewayIntentBits.DirectMessages,
GatewayIntentBits.DirectMessageReactions
],
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildEmojisAndStickers,
GatewayIntentBits.GuildVoiceStates,
GatewayIntentBits.GuildWebhooks,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.GuildMessageReactions,
GatewayIntentBits.DirectMessages,
GatewayIntentBits.DirectMessageReactions
],
export const CLIENT_OPTIONS: ClientOptions = {
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildEmojisAndStickers,
GatewayIntentBits.GuildVoiceStates,
GatewayIntentBits.GuildWebhooks,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.GuildMessageReactions,
GatewayIntentBits.DirectMessages,
GatewayIntentBits.DirectMessageReactions
],
allowedMentions: { users: [], roles: [] },
presence: {
activities: [{ name: 'over Engrimoore!', type: ActivityType.Watching }]
},
defaultPrefix: PREFIX,
disableMentionPrefix: true,
caseInsensitiveCommands: true,
logger: { level: PROD ? LogLevel.Info : LogLevel.Debug },
partials: [Partials.Channel],
loadMessageCommandListeners: true,
tasks: {
bull: {
connection: { ...parseRedisOptions() , db: envParseInteger('REDIS_DB')},
}
}
// sweepers: {
// ...Options.defaultSweeperSettings,
// messages: {
// interval: minutes.toSeconds(3),
// lifetime: minutes.toSeconds(15)
// }
// }
};
export const CLIENT_OPTIONS: ClientOptions = {
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildEmojisAndStickers,
GatewayIntentBits.GuildVoiceStates,
GatewayIntentBits.GuildWebhooks,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.GuildMessageReactions,
GatewayIntentBits.DirectMessages,
GatewayIntentBits.DirectMessageReactions
],
allowedMentions: { users: [], roles: [] },
presence: {
activities: [{ name: 'over Engrimoore!', type: ActivityType.Watching }]
},
defaultPrefix: PREFIX,
disableMentionPrefix: true,
caseInsensitiveCommands: true,
logger: { level: PROD ? LogLevel.Info : LogLevel.Debug },
partials: [Partials.Channel],
loadMessageCommandListeners: true,
tasks: {
bull: {
connection: { ...parseRedisOptions() , db: envParseInteger('REDIS_DB')},
}
}
// sweepers: {
// ...Options.defaultSweeperSettings,
// messages: {
// interval: minutes.toSeconds(3),
// lifetime: minutes.toSeconds(15)
// }
// }
};
I use the sapphire framework so if I do message.embeds[0] it should stop soing that? I didn't realize that was mutating it but now that you say that it make sense. Trying teach myself how to do this ok that's why all the examples read as accessing them. I thought I was being clever thank you