Discord.js v13 EMBED_FIELD_VALUE错误修复及代码修改求助
解决Discord机器人movieinfo命令的RangeError [EMBED_FIELD_VALUE]问题
错误原因
该错误是因为Discord的MessageEmbed要求所有字段值必须是非空字符串,你的代码中存在以下问题:
- 部分数字类型字段直接传入
addField,虽Discord.js会尝试自动转换,但存在潜在风险; - 仅通过falsy值判断字段是否存在,会漏掉值为0的合法场景(比如评分0分);
- 未处理空字符串类型的字段,直接传入会触发校验错误。
修复后的完整代码
const fetch = require('node-fetch'); module.exports = { name: 'movieinfo', description: 'Affiche des informations sur un film, une série, un anime ou un épisode.', category: '🎥 Films et séries', usage: '<titre du film, de la série, de l\'anime ou de l\'épisode>', async execute(message, args) { try { const apiKey = 'API KEY'; const query = args.join(' '); const response = await fetch(`https://api.themoviedb.org/3/search/multi?api_key=${apiKey}&language=fr-FR&query=${encodeURIComponent(query)}`); const data = await response.json(); const results = data.results; if (!results || results.length === 0) { message.channel.send(`Désolé, je n'ai pas trouvé d'informations pour "${query}".`); return; } const mediaTypes = results.map(result => result.media_type); const uniqueMediaTypes = [...new Set(mediaTypes)]; const mediaType = await askMediaType(message, uniqueMediaTypes, query); if (!mediaType) return; const filteredResults = results.filter(result => result.media_type === mediaType); const result = filteredResults[0]; if (!result) { message.channel.send(`Désolé, je n'ai pas trouvé de ${mediaType.toLowerCase()} pour "${query}".`); return; } let title, releaseDate, overview, posterUrl, startDate, endDate, year, rating, voteCount, contentScore, numberOfSeasons, numberOfEpisodes; if (mediaType === 'movie') { title = result.title; releaseDate = result.release_date; overview = result.overview || "Aucun synopsis disponible"; posterUrl = result.poster_path; year = releaseDate ? new Date(releaseDate).getFullYear() : null; rating = result.vote_average; voteCount = result.vote_count; contentScore = result.popularity; } else if (mediaType === 'tv' || mediaType === 'anime') { title = result.name; releaseDate = result.first_air_date; overview = result.overview || "Aucun synopsis disponible"; posterUrl = result.poster_path; startDate = result.first_air_date; endDate = result.last_air_date; year = startDate ? new Date(startDate).getFullYear() : null; rating = result.vote_average; voteCount = result.vote_count; contentScore = result.popularity; numberOfSeasons = result.number_of_seasons; numberOfEpisodes = result.number_of_episodes; } else if (mediaType === 'person') { title = result.name; releaseDate = null; overview = result.biography || "Aucune biographie disponible"; posterUrl = result.profile_path; } else { message.channel.send(`Désolé, je ne suis pas en mesure de fournir des informations pour "${query}".`); return; } const releaseYear = releaseDate ? ` (${new Date(releaseDate).getFullYear()})` : ''; const posterEmbed = posterUrl ? new Discord.MessageEmbed().setImage(`https://image.tmdb.org/t/p/original${posterUrl}`) : null; const infoEmbed = new Discord.MessageEmbed() .setTitle(`${title}${releaseYear}`) .setColor('#f8ecfc'); if (mediaType === 'movie' || mediaType === 'tv' || mediaType === 'anime') { if (year !== null && year !== undefined) { infoEmbed.addField('Année', year.toString(), true); } if (rating !== null && rating !== undefined) { infoEmbed.addField('Note des utilisateurs', `${rating}/10`, true); } if (contentScore !== null && contentScore !== undefined) { infoEmbed.addField('Score de contenu', `${contentScore.toFixed(1)}/100`, true); } if (mediaType === 'tv' || mediaType === 'anime') { if (numberOfSeasons !== null && numberOfSeasons !== undefined) { infoEmbed.addField('Nombre de saisons', numberOfSeasons.toString(), true); } if (numberOfEpisodes !== null && numberOfEpisodes !== undefined) { infoEmbed.addField('Nombre d\'épisodes', numberOfEpisodes.toString(), true); } if (startDate) { const endDateString = endDate ? ` - ${new Date(endDate).toLocaleDateString('fr-FR')}` : ''; infoEmbed.addField('Dates de diffusion', `${new Date(startDate).toLocaleDateString('fr-FR')}${endDateString}`, true); } infoEmbed.addField('Synopsis', overview); } } if (mediaType === 'person') { infoEmbed.addField('Biographie', overview); } message.channel.send(`Je vous ai trouvé plusieurs ${mediaType.toLowerCase()} correspondant à "${query}" :\n${filteredResults.map(result => result.title || result.name || 'Intitulé inconnu').join(', ')}`).then(() => { const embeds = [infoEmbed, posterEmbed].filter(embed => { if (!embed) return false; if (embed === infoEmbed) { return embed.title || embed.fields.length > 0; } return true; }); message.channel.send({ embeds }); }); } catch (error) { console.error(error); message.channel.send('Une erreur vient de se produire.'); } }, }; async function askMediaType(message, mediaTypes, query) { const mediaTypeString = mediaTypes.map((mediaType, index) => `${index + 1}. ${mediaType.toLowerCase()}`).join('\n'); const mediaTypeMessage = await message.channel.send(`J'ai trouvé plusieurs types de médias pour "${query}". Veuillez choisir un type de média en tapant le numéro correspondant :\n${mediaTypeString}`); const filter = m => m.author.id === message.author.id && /^\d+$/.test(m.content); try { const collected = await message.channel.awaitMessages({ filter, max: 1, time: 15000, errors: ['time'] }); const choice = parseInt(collected.first().content); if (choice < 1 || choice > mediaTypes.length) { message.channel.send(`Désolé, "${choice}" n'est pas un choix valide.`); return askMediaType(message, mediaTypes, query); } return mediaTypes[choice - 1]; } catch (err) { message.channel.send(`Temps écoulé, veuillez réessayer la commande.`); return null; } }
关键修改点
- 空字段默认值:给
overview设置默认文本,避免空字符串传入Embed; - 严格存在性校验:将
if (year)改为if (year !== null && year !== undefined),确保0值合法字段能正常显示; - 数字转字符串:年份、季数等数字字段通过
toString()转换为字符串,符合MessageEmbed要求; - Embed过滤优化:修改发送前的过滤逻辑,避免对数字字段调用
trim()导致的错误; - 超时异常处理:在
askMediaType中添加catch块,处理用户超时未输入的情况,防止机器人崩溃。
内容的提问来源于stack exchange,提问作者Mmm
相关产品推荐
相关产品推荐

