Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Support sending voice messages #3024

Merged
merged 2 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions src/Discord.Net.Core/Entities/Messages/FileAttachment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ public struct FileAttachment : IDisposable
/// </summary>
public bool IsThumbnail { get; set; }

/// <summary>
/// Gets or sets the duration of a voice message. <see langword="null"/> if the attachment is not a voice message.
/// </summary>
public double? DurationSeconds { get; set; }

/// <summary>
/// Gets or sets bytearray representing a sampled waveform. <see langword="null"/> if the attachment is not a voice message.
/// </summary>
public byte[] Waveform { get; set; }

#pragma warning disable IDISP008
/// <summary>
/// Gets the stream containing the file content.
Expand All @@ -44,7 +54,7 @@ public struct FileAttachment : IDisposable
/// <param name="description">The description of the attachment.</param>
/// <param name="isSpoiler">Whether or not the attachment is a spoiler.</param>
/// <param name="isThumbnail">Whether or not this attachment should be a thumbnail for a media channel post.</param>
public FileAttachment(Stream stream, string fileName, string description = null, bool isSpoiler = false, bool isThumbnail = false)
public FileAttachment(Stream stream, string fileName, string description = null, bool isSpoiler = false, bool isThumbnail = false, double? durationSeconds = null, byte[] waveform = null)
{
_isDisposed = false;
FileName = fileName;
Expand All @@ -57,6 +67,8 @@ public FileAttachment(Stream stream, string fileName, string description = null,
}
catch { }
IsSpoiler = isSpoiler;
DurationSeconds = durationSeconds;
Waveform = waveform;
}

/// <summary>
Expand Down Expand Up @@ -91,14 +103,16 @@ public FileAttachment(Stream stream, string fileName, string description = null,
/// <exception cref="FileNotFoundException">The file specified in <paramref name="path" /> was not found.
/// </exception>
/// <exception cref="IOException">An I/O error occurred while opening the file. </exception>
public FileAttachment(string path, string fileName = null, string description = null, bool isSpoiler = false, bool isThumbnail = false)
public FileAttachment(string path, string fileName = null, string description = null, bool isSpoiler = false, bool isThumbnail = false, double? durationSeconds = null, byte[] waveform = null)
{
_isDisposed = false;
Stream = File.OpenRead(path);
FileName = fileName ?? Path.GetFileName(path);
Description = description;
IsSpoiler = isSpoiler;
IsThumbnail = isThumbnail;
DurationSeconds = durationSeconds;
Waveform = waveform;
}

public void Dispose()
Expand Down
5 changes: 5 additions & 0 deletions src/Discord.Net.Core/Entities/Messages/IAttachment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ public interface IAttachment : ISnowflakeEntity
/// </summary>
public string Waveform { get; }

/// <summary>
/// Gets the bytearray representing a sampled waveform. <see langword="null"/> if the attachment is not a voice message.
/// </summary>
public byte[] WaveformBytes { get; }

/// <summary>
/// Gets flags related to this to this attachment.
/// </summary>
Expand Down
10 changes: 9 additions & 1 deletion src/Discord.Net.Rest/API/Rest/UploadFileParams.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Discord.Net.Converters;
using Discord.Net.Rest;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -34,6 +35,9 @@ public IReadOnlyDictionary<string, object> ToDictionary()
{
var d = new Dictionary<string, object>();

if (Files.Any(x => x.Waveform is not null && x.DurationSeconds is not null))
Flags = Flags.GetValueOrDefault(MessageFlags.None) | MessageFlags.VoiceMessage;

var payload = new Dictionary<string, object>();
if (Content.IsSpecified)
payload["content"] = Content.Value;
Expand Down Expand Up @@ -71,7 +75,11 @@ public IReadOnlyDictionary<string, object> ToDictionary()
{
id = (ulong)n,
filename = filename,
description = attachment.Description ?? Optional<string>.Unspecified
description = attachment.Description ?? Optional<string>.Unspecified,
duration_secs = attachment.DurationSeconds ?? Optional<double>.Unspecified,
waveform = attachment.Waveform is null
? Optional<string>.Unspecified
: Convert.ToBase64String(attachment.Waveform)
});
}

Expand Down
8 changes: 7 additions & 1 deletion src/Discord.Net.Rest/API/Rest/UploadInteractionFileParams.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public IReadOnlyDictionary<string, object> ToDictionary()
{
var d = new Dictionary<string, object>();

if (Files.Any(x => x.Waveform is not null && x.DurationSeconds is not null))
Flags = Flags.GetValueOrDefault(MessageFlags.None) | MessageFlags.VoiceMessage;

var payload = new Dictionary<string, object>();
payload["type"] = Type;
Expand Down Expand Up @@ -79,7 +81,11 @@ public IReadOnlyDictionary<string, object> ToDictionary()
{
id = (ulong)n,
filename = filename,
description = attachment.Description ?? Optional<string>.Unspecified
description = attachment.Description ?? Optional<string>.Unspecified,
duration_secs = attachment.DurationSeconds ?? Optional<double>.Unspecified,
waveform = attachment.Waveform is null
? Optional<string>.Unspecified
: Convert.ToBase64String(attachment.Waveform)
});
}

Expand Down
11 changes: 10 additions & 1 deletion src/Discord.Net.Rest/API/Rest/UploadWebhookFileParams.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using Discord.Net.Converters;
using Discord.Net.Rest;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace Discord.API.Rest
Expand Down Expand Up @@ -35,6 +37,9 @@ public IReadOnlyDictionary<string, object> ToDictionary()
{
var d = new Dictionary<string, object>();

if (Files.Any(x => x.Waveform is not null && x.DurationSeconds is not null))
Flags = Flags.GetValueOrDefault(MessageFlags.None) | MessageFlags.VoiceMessage;

var payload = new Dictionary<string, object>();
if (Content.IsSpecified)
payload["content"] = Content.Value;
Expand Down Expand Up @@ -76,7 +81,11 @@ public IReadOnlyDictionary<string, object> ToDictionary()
{
id = (ulong)n,
filename = filename,
description = attachment.Description ?? Optional<string>.Unspecified
description = attachment.Description ?? Optional<string>.Unspecified,
duration_secs = attachment.DurationSeconds ?? Optional<double>.Unspecified,
waveform = attachment.Waveform is null
? Optional<string>.Unspecified
: Convert.ToBase64String(attachment.Waveform)
});
}

Expand Down
5 changes: 5 additions & 0 deletions src/Discord.Net.Rest/Entities/Messages/Attachment.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Discord.Rest;
using System;
using System.Buffers.Text;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
Expand Down Expand Up @@ -35,6 +36,8 @@ public class Attachment : IAttachment
/// <inheritdoc />
public string Waveform { get; }
/// <inheritdoc />
public byte[] WaveformBytes { get; }
/// <inheritdoc />
public double? Duration { get; }

/// <inheritdoc cref="IAttachment.ClipParticipants" />
Expand Down Expand Up @@ -69,6 +72,8 @@ internal Attachment(ulong id, string filename, string url, string proxyUrl, int
Title = title;
ClipParticipants = clipParticipants;
ClipCreatedAt = clipCreatedAt;
if (waveform is not null)
WaveformBytes = Convert.FromBase64String(waveform);
}

internal static Attachment Create(Model model, BaseDiscordClient discord)
Expand Down