简单的解决方案
我想出的discord.js v12最简单的解决方案:
async function getUserBannerUrl(userId) {
const user = await client.api.users(userId).get();
return user.banner ? `https://cdn.discordapp.com/banners/${userId}/${user.banner}?size=512` : null;
}
但是,这不能很好地处理 mime 类型。除非您阅读 content-type 标头,否则您不知道 mime 类型是什么。这可能会破坏一些要求您在 URL 中具有文件扩展名的内容。这就是为什么我想出了更复杂的解决方案。
复杂的解决方案
下面的代码依赖于axios。
const axios = require("axios");
async function getUserBannerUrl(userId, { dynamicFormat = true, defaultFormat = "webp", size = 512 } = {}) {
// Supported image sizes, inspired by 'https://discord.js.org/#/docs/main/stable/typedef/ImageURLOptions'.
if (![16, 32, 64, 128, 256, 512, 1024, 2048, 4096].includes(size)) {
throw new Error(`The size '${size}' is not supported!`);
}
// We don't support gif as a default format,
// because requesting .gif format when the original image is not a gif,
// would result in an error 415 Unsupported Media Type.
// If you want gif support, enable dynamicFormat, .gif will be used when is it available.
if (!["webp", "png", "jpg", "jpeg"].includes(defaultFormat)) {
throw new Error(`The format '${defaultFormat}' is not supported as a default format!`);
}
// We use raw API request to get the User object from Discord API,
// since the discord.js v12's one doens't support .banner property.
const user = await client.api.users(userId).get();
if (!user.banner) return null;
const query = `?size=${size}`;
const baseUrl = `https://cdn.discordapp.com/banners/${userId}/${user.banner}`;
// If dynamic format is enabled we perform a HTTP HEAD request,
// so we can use the content-type header to determine,
// if the image is a gif or not.
if (dynamicFormat) {
const { headers } = await axios.head(baseUrl);
if (headers && headers.hasOwnProperty("content-type")) {
return baseUrl + (headers["content-type"] == "image/gif" ? ".gif" : `.${defaultFormat}`) + query;
}
}
return baseUrl + `.${defaultFormat}` + query;
}
示例用法
实现简单的!banner 命令,将显示消息发送者的横幅。
client.on("message", async (message) => {
if (message.author.bot) return;
if (message.content == "!banner") {
const bannerUrl = await getUserBannerUrl(message.author.id, { size: 4096 });
if (bannerUrl) {
const embed = new Discord.MessageEmbed()
.setTitle(`${message.author.username}'s banner`)
.setDescription("Look at my banner, how cool is that?")
.setImage(bannerUrl);
message.channel.send(embed);
} else {
message.channel.send("You don't have money to buy Discord Nitro... How sad...");
}
}
});