Discord机器人Weather命令输入有效城市仍触发错误求助
问题排查与解决办法
核心错误原因
- Dotenv未正确初始化:仅导入
dotenv但未调用config(),导致环境变量WEATHER_API_KEY无法被读取,API请求因密钥无效被拒绝。 - MessageEmbed参数错误:
execute函数的第二个参数并非MessageEmbed,该类需要从discord.js或@discordjs/builders手动导入,而非通过函数参数获取。 - URL参数未编码:直接拼接城市名到URL中,若城市名含特殊字符(如空格)会导致请求格式错误。
- 错误信息被隐藏:
catch块仅返回通用提示,无法得知API请求的具体失败原因,阻碍排查。
分步修复代码
1. 正确加载环境变量
修改dotenv导入方式,确保环境变量被读取:
require('dotenv').config(); // 新增:加载.env文件 const { WEATHER_API_KEY } = process.env; // 从process.env获取密钥
2. 导入MessageEmbed
在文件顶部添加MessageEmbed的导入语句:
const { SlashCommandBuilder } = require('@discordjs/builders'); const { MessageEmbed } = require('discord.js'); // 新增:导入MessageEmbed require('dotenv').config(); const { WEATHER_API_KEY } = process.env; const axios = require('axios');
3. 编码URL参数
对城市名进行URL编码,避免特殊字符导致的请求错误:
const target = interaction.options.getString('location'); const encodedTarget = encodeURIComponent(target); // 编码城市名 axios.get(`https://api.openweathermap.org/data/2.5/weather?q=${encodedTarget}&units=metric&appid=${WEATHER_API_KEY}`)
4. 输出详细错误信息
修改catch块,打印并返回具体错误,便于排查:
.catch(err => { console.error('Weather API 请求失败:', err.response?.data || err.message); const errorMsg = err.response?.data?.message || '未知错误'; interaction.reply(`请输入有效的城市名称。错误详情:${errorMsg}`); })
5. 修正execute函数参数
移除execute函数的MessageEmbed参数,因为该参数不存在:
async execute(interaction) { // 仅保留interaction参数 // ... 原有逻辑 }
完整修复后的代码
const { SlashCommandBuilder } = require('@discordjs/builders'); const { MessageEmbed } = require('discord.js'); require('dotenv').config(); const { WEATHER_API_KEY } = process.env; const axios = require('axios'); module.exports = { data: new SlashCommandBuilder() .setName('weather') .setDescription('查看指定地区的天气') .addStringOption(option => option.setName('location').setDescription('要查询天气的地区')), async execute(interaction) { const target = interaction.options.getString('location'); const encodedTarget = encodeURIComponent(target); axios.get(`https://api.openweathermap.org/data/2.5/weather?q=${encodedTarget}&units=metric&appid=${WEATHER_API_KEY}`) .then(response => { const apiData = response.data; const currentTemp = Math.ceil(apiData.main.temp); const wind = apiData.wind.speed; const icon = apiData.weather[0].icon; const cityName = apiData.name; // 直接从API返回数据获取城市名更可靠 const country = apiData.sys.country; const cloudness = apiData.weather[0].description; const { pressure, humidity, temp_max, temp_min } = apiData.main; const weatherEmbed = new MessageEmbed() .setTitle(`${cityName}, ${country} 当前气温 ${currentTemp}\u00B0C`) .addFields( { name: '最高气温:', value: `${temp_max}\u00B0C`, inline: true }, { name: '最低气温:', value: `${temp_min}\u00B0C`, inline: true }, { name: '湿度:', value: `${humidity} %`, inline: true }, { name: '风速:', value: `${wind} m/s`, inline: true }, { name: '气压:', value: `${pressure} hpa`, inline: true }, { name: '天气状况:', value: `${cloudness}`, inline: true }, ) .setThumbnail(`http://openweathermap.org/img/w/${icon}.png`) .setColor("#FFC0CB"); interaction.reply({ embeds: [weatherEmbed] }); }) .catch(err => { console.error('Weather API 请求失败:', err.response?.data || err.message); const errorMsg = err.response?.data?.message || '未知错误'; interaction.reply(`请输入有效的城市名称。错误详情:${errorMsg}`); }); }, };
额外优化:从API返回数据中获取cityName,而非从交互参数中读取,避免参数与实际返回城市名不一致的情况。
内容的提问来源于stack exchange,提问作者Nearfight0
相关产品推荐
相关产品推荐

