将本地图像与 EmbedBuilder 结合使用
Using a local image with EmbedBuilder
根据Discord.NETdocumentation page for the EmbedBuilder
class的语法(转换为VB)添加一个本地图片 到 EmbedBuilder
对象应该看起来像这样:
Dim fileName = "image.png"
Dim embed = New EmbedBuilder() With {
.ImageUrl = $"attachment://{fileName}"
}.Build()
我正在尝试使用类似这样的方法将动态创建的图像添加到 EmbedBuilder
,但我似乎无法使其正常工作。这基本上是我得到的:
Dim TweetBuilder As New Discord.EmbedBuilder
Dim DynamicImagePath As String = CreateDynamicImage()
Dim AttachURI As String = $"attachment:///" & DynamicImagePath.Replace("\", "/").Replace(" ", "%20")
With Builder
.Description = "SAMPLE DESCRIPTION"
.ImageUrl = AttachURI
End With
MyClient.GetGuild(ServerID).GetTextChannel(PostChannelID).SendMessageAsync("THIS IS A TEST", False, Builder.Build)
我的 CreateDynamicImage
方法 returns 本地创建图像的完整路径(例如,C:\Folder\Another Folder\image.png
)。我已经为此进行了大量的“战斗”/测试,以克服我最初因为路径中的 [SPACE]
而遇到的 Url must be a well-formed URI
异常。
MyClient
是在别处设置的 Discord.WebSocket.SocketClient
对象。
SendMessageAsync
方法确实在正确的频道上将嵌入发送到 Discord,但没有嵌入图像。
如果我改为使用 SendFileAsync
方法发送图像(像这样):
MyClient.GetGuild(ServerID).GetTextChannel(PostChannelID).SendFileAsync(DynamicImagePath, "THIS IS A TEST", False, Builder.Build)
图像已发送,但作为消息的一部分,而不是作为嵌入的一部分包含(这是预期的行为 - 我只提出它b/c 这是我测试的一部分,以确保将图像实际发送到 Discord 没有问题。
我试过使用 file:///
方案而不是 attachment:///
方案,但这导致整个 post 根本无法进入 Discord。
此外,我已经尝试将 ImageUrl
属性 设置为 Web 资源(例如,https://www.somesite.com/someimage.png
)并且嵌入看起来与图像和所有内容完全符合预期成功 post 到 Discord。
所以,我现在想知道我是不是漏掉了什么,还是我做的完全错了?
我已经尽我所能,但我还是卡在了你现在所在的位置。
我的猜测是 Discord 不喜欢来自 https://cdn.discordapp.com/attachments, and only accepts the new files from https://media.discordapp.net 的嵌入图像。不过我可能是错的,这就是它对我有用的方式。
我认为这只是一个视觉故障,我发现如果您在常规 Discord 客户端中为来自 cdn.discordapp.com/attchments 的图像发送 link,它会出错并由于某种原因显示了一个空嵌入。
这是有道理的,因为嵌入图像中使用的默认 link 实际上以 https://cdn.discordapp.com/attachments/.. 开头。
您可以使用 https://media.discordapp.net 解决此问题,但似乎 Discord.net 配置为使用旧域。
我 cross-posted 把这个发给 issue #1609 in the Discord.Net GitHub project 以便更好地了解对此有哪些选项可用,并收到了对该问题的很好解释:
The Embed
(and EmbedImage
) objects don't do anything with files. They simply pass the URI as configured straight into Discord. Discord then expects a URI in the form attachment://filename.ext
if you want to refer to an attached image.
What you need to do is use SendFileAsync
with the embed. You have two options here:
Use SendFileAsync
with the Stream stream, string filename
overload. I think this makes it clear what you need to do: you provide a file stream (via File.OpenRead
or similar) and a filename. The provided filename does not have to match any file on disk. > So, for example:
var embed = new EmbedBuilder()
.WithImageUrl("attachment://myimage.png")
.Build();
await channel.SendFileAsync(stream, "myimage.png", embed: embed);
Alternatively, you can use SendFileAsync
with the string filePath
overload. Internally, this gets a stream of the file at the path, and sets filename
(as sent to Discord) to the last part of the path. So it's equivalent to:
using var stream = File.OpenRead(filePath);
var filename = Path.GetFileName(filePath);
await channel.SendFileAsync(stream, filename);
From here, you can see that if you want to use the string filePath
overload, you need to set embed image URI to something like $"attachment://{Path.GetFileName(filePath)}"
, because the attachment filename must match the one sent to Discord.
我几乎用我上面的代码就可以了,但是我误解了方法的意图和用法,属性。我想我认为 .ImageUrl
属性 以某种方式“自动”在后台启动了 Stream
。另外,我错过了一个非常重要的部分:
As it's an async method, you must await (or whatever the VB.NET equivalent is) on SendFileAsync.
所以,在将我的调用方法变成异步方法之后,我的代码现在看起来像这样:
Private Async Sub TestMessageToDiscord()
Dim Builder As New Discord.EmbedBuilder
Dim AttachmentPath As String = CreateDynamicImage() '<-- Returns the full, local path to the created file
With Builder
.Description = "SAMPLE DESCRIPTION"
.ImageUrl = $"attachment://{IO.Path.GetFileName(AttachmentPath)}"
End With
Using AttachmentStream As IO.Stream = IO.File.OpenRead(AttachmentPath)
Await MyClient.GetGuild(ServerID).GetTextChannel(PostChannelID).SendFileAsync(AttachmentStream, IO.Path.GetFileName(AttachmentPath), "THIS IS A TEST", False, Builder.Build)
End Using
End Sub
现在,一切都完全按预期工作,我不必求助于将图像上传到托管站点并使用新的 URL(我实际上在我之前就已经开始工作了在 GitHub 上收到了回复。我确信 代码不会浪费 )。
编辑
好的,所以我 仍然 出于一个原因最终回到我单独托管的图像选项:我有一个单独的事件方法来修改原始 Embed
对象在此期间我想删除图像并替换文本。然而,当该事件触发时,文本被替换,图像被“移动”到 Discord 消息的正文中。虽然我 可能 已经能够弄清楚如何完全摆脱图像,但我决定“退后一步”,因为我已经制定了托管图像解决方案。
根据Discord.NETdocumentation page for the EmbedBuilder
class的语法(转换为VB)添加一个本地图片 到 EmbedBuilder
对象应该看起来像这样:
Dim fileName = "image.png"
Dim embed = New EmbedBuilder() With {
.ImageUrl = $"attachment://{fileName}"
}.Build()
我正在尝试使用类似这样的方法将动态创建的图像添加到 EmbedBuilder
,但我似乎无法使其正常工作。这基本上是我得到的:
Dim TweetBuilder As New Discord.EmbedBuilder
Dim DynamicImagePath As String = CreateDynamicImage()
Dim AttachURI As String = $"attachment:///" & DynamicImagePath.Replace("\", "/").Replace(" ", "%20")
With Builder
.Description = "SAMPLE DESCRIPTION"
.ImageUrl = AttachURI
End With
MyClient.GetGuild(ServerID).GetTextChannel(PostChannelID).SendMessageAsync("THIS IS A TEST", False, Builder.Build)
我的 CreateDynamicImage
方法 returns 本地创建图像的完整路径(例如,C:\Folder\Another Folder\image.png
)。我已经为此进行了大量的“战斗”/测试,以克服我最初因为路径中的 [SPACE]
而遇到的 Url must be a well-formed URI
异常。
MyClient
是在别处设置的 Discord.WebSocket.SocketClient
对象。
SendMessageAsync
方法确实在正确的频道上将嵌入发送到 Discord,但没有嵌入图像。
如果我改为使用 SendFileAsync
方法发送图像(像这样):
MyClient.GetGuild(ServerID).GetTextChannel(PostChannelID).SendFileAsync(DynamicImagePath, "THIS IS A TEST", False, Builder.Build)
图像已发送,但作为消息的一部分,而不是作为嵌入的一部分包含(这是预期的行为 - 我只提出它b/c 这是我测试的一部分,以确保将图像实际发送到 Discord 没有问题。
我试过使用 file:///
方案而不是 attachment:///
方案,但这导致整个 post 根本无法进入 Discord。
此外,我已经尝试将 ImageUrl
属性 设置为 Web 资源(例如,https://www.somesite.com/someimage.png
)并且嵌入看起来与图像和所有内容完全符合预期成功 post 到 Discord。
所以,我现在想知道我是不是漏掉了什么,还是我做的完全错了?
我已经尽我所能,但我还是卡在了你现在所在的位置。 我的猜测是 Discord 不喜欢来自 https://cdn.discordapp.com/attachments, and only accepts the new files from https://media.discordapp.net 的嵌入图像。不过我可能是错的,这就是它对我有用的方式。
我认为这只是一个视觉故障,我发现如果您在常规 Discord 客户端中为来自 cdn.discordapp.com/attchments 的图像发送 link,它会出错并由于某种原因显示了一个空嵌入。
这是有道理的,因为嵌入图像中使用的默认 link 实际上以 https://cdn.discordapp.com/attachments/.. 开头。
您可以使用 https://media.discordapp.net 解决此问题,但似乎 Discord.net 配置为使用旧域。
我 cross-posted 把这个发给 issue #1609 in the Discord.Net GitHub project 以便更好地了解对此有哪些选项可用,并收到了对该问题的很好解释:
The
Embed
(andEmbedImage
) objects don't do anything with files. They simply pass the URI as configured straight into Discord. Discord then expects a URI in the formattachment://filename.ext
if you want to refer to an attached image.What you need to do is use
SendFileAsync
with the embed. You have two options here:Use
SendFileAsync
with theStream stream, string filename
overload. I think this makes it clear what you need to do: you provide a file stream (viaFile.OpenRead
or similar) and a filename. The provided filename does not have to match any file on disk. > So, for example:var embed = new EmbedBuilder() .WithImageUrl("attachment://myimage.png") .Build(); await channel.SendFileAsync(stream, "myimage.png", embed: embed);
Alternatively, you can use
SendFileAsync
with thestring filePath
overload. Internally, this gets a stream of the file at the path, and setsfilename
(as sent to Discord) to the last part of the path. So it's equivalent to:using var stream = File.OpenRead(filePath); var filename = Path.GetFileName(filePath); await channel.SendFileAsync(stream, filename);
From here, you can see that if you want to use the
string filePath
overload, you need to set embed image URI to something like$"attachment://{Path.GetFileName(filePath)}"
, because the attachment filename must match the one sent to Discord.
我几乎用我上面的代码就可以了,但是我误解了方法的意图和用法,属性。我想我认为 .ImageUrl
属性 以某种方式“自动”在后台启动了 Stream
。另外,我错过了一个非常重要的部分:
As it's an async method, you must await (or whatever the VB.NET equivalent is) on SendFileAsync.
所以,在将我的调用方法变成异步方法之后,我的代码现在看起来像这样:
Private Async Sub TestMessageToDiscord()
Dim Builder As New Discord.EmbedBuilder
Dim AttachmentPath As String = CreateDynamicImage() '<-- Returns the full, local path to the created file
With Builder
.Description = "SAMPLE DESCRIPTION"
.ImageUrl = $"attachment://{IO.Path.GetFileName(AttachmentPath)}"
End With
Using AttachmentStream As IO.Stream = IO.File.OpenRead(AttachmentPath)
Await MyClient.GetGuild(ServerID).GetTextChannel(PostChannelID).SendFileAsync(AttachmentStream, IO.Path.GetFileName(AttachmentPath), "THIS IS A TEST", False, Builder.Build)
End Using
End Sub
现在,一切都完全按预期工作,我不必求助于将图像上传到托管站点并使用新的 URL(我实际上在我之前就已经开始工作了在 GitHub 上收到了回复。我确信 代码不会浪费 )。
编辑
好的,所以我 仍然 出于一个原因最终回到我单独托管的图像选项:我有一个单独的事件方法来修改原始 Embed
对象在此期间我想删除图像并替换文本。然而,当该事件触发时,文本被替换,图像被“移动”到 Discord 消息的正文中。虽然我 可能 已经能够弄清楚如何完全摆脱图像,但我决定“退后一步”,因为我已经制定了托管图像解决方案。