diff --git a/DisCatSharp.Targets/InternalsVisibleTo.targets b/DisCatSharp.Targets/InternalsVisibleTo.targets
index 98a726adc3..05e9d3ec9e 100644
--- a/DisCatSharp.Targets/InternalsVisibleTo.targets
+++ b/DisCatSharp.Targets/InternalsVisibleTo.targets
@@ -18,6 +18,7 @@
+
diff --git a/DisCatSharp.VoiceNext/VoiceNextConnection.cs b/DisCatSharp.VoiceNext/VoiceNextConnection.cs
index 7780d05bd2..d609cf710a 100644
--- a/DisCatSharp.VoiceNext/VoiceNextConnection.cs
+++ b/DisCatSharp.VoiceNext/VoiceNextConnection.cs
@@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using System.Security.Cryptography;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
@@ -417,7 +418,7 @@ internal Task ConnectAsync()
{
Scheme = "wss",
Host = this.WebSocketEndpoint.Hostname,
- Query = "encoding=json&v=4"
+ Query = "encoding=json&v=10"
};
return this._voiceWs.ConnectAsync(gwuri.Uri);
@@ -638,6 +639,7 @@ private async Task VoiceSenderTask()
/// A bool.
private bool ProcessPacket(ReadOnlySpan data, ref Memory opus, ref Memory pcm, IList> pcmPackets, out AudioSender voiceSender, out AudioFormat outputFormat)
{
+ this._discord.Logger.LogDebug("Processing packet..");
voiceSender = null;
outputFormat = default;
@@ -648,6 +650,7 @@ private bool ProcessPacket(ReadOnlySpan data, ref Memory opus, ref M
if (!this._transmittingSsrCs.TryGetValue(ssrc, out var vtx))
{
+ this._discord.Logger.LogDebug("Don't know user yet, creating dummy for {ssrc}", ssrc);
var decoder = this._opus.CreateDecoder();
vtx = new AudioSender(ssrc, decoder)
@@ -656,29 +659,30 @@ private bool ProcessPacket(ReadOnlySpan data, ref Memory opus, ref M
User = null
};
}
-
- voiceSender = vtx;
var sequence = vtx.GetTrueSequenceAfterWrapping(shortSequence);
- ushort gap = 0;
- if (vtx.LastTrueSequence is ulong lastTrueSequence)
+
+ try
{
- if (sequence <= lastTrueSequence) // out-of-order packet; discard
- return false;
+ voiceSender = vtx;
+ ushort gap = 0;
+ if (vtx.LastTrueSequence is ulong lastTrueSequence)
+ {
+ if (sequence <= lastTrueSequence) // out-of-order packet; discard
+ return false;
- gap = (ushort)(sequence - 1 - lastTrueSequence);
- if (gap >= 5)
- this._discord.Logger.LogWarning(VoiceNextEvents.VoiceReceiveFailure, "5 or more voice packets were dropped when receiving");
- }
+ gap = (ushort)(sequence - 1 - lastTrueSequence);
+ if (gap >= 5)
+ this._discord.Logger.LogWarning(VoiceNextEvents.VoiceReceiveFailure, "5 or more voice packets were dropped when receiving");
+ }
- Span nonce = stackalloc byte[Sodium.NonceSize];
- this._sodium.GetNonce(data, nonce, this._selectedEncryptionMode);
- this._rtp.GetDataFromPacket(data, out var encryptedOpus, this._selectedEncryptionMode);
+ Span nonce = stackalloc byte[Sodium.NonceSize];
+ this._sodium.GetNonce(data, nonce, this._selectedEncryptionMode);
+ this._rtp.GetDataFromPacket(data, out var encryptedOpus, this._selectedEncryptionMode);
- var opusSize = Sodium.CalculateSourceSize(encryptedOpus);
- opus = opus[..opusSize];
- var opusSpan = opus.Span;
- try
- {
+ var opusSize = Sodium.CalculateSourceSize(encryptedOpus);
+ opus = opus[..opusSize];
+ var opusSpan = opus.Span;
+
this._sodium.Decrypt(encryptedOpus, opusSpan, nonce);
// Strip extensions, if any
@@ -720,6 +724,7 @@ private bool ProcessPacket(ReadOnlySpan data, ref Memory opus, ref M
if (gap == 1)
{
+ this._discord.Logger.LogDebug("Gap 1");
var lastSampleCount = this._opus.GetLastPacketSampleCount(vtx.Decoder);
var fecpcm = new byte[this.AudioFormat.SampleCountToSampleSize(lastSampleCount)];
var fecpcmMem = fecpcm.AsSpan();
@@ -728,6 +733,7 @@ private bool ProcessPacket(ReadOnlySpan data, ref Memory opus, ref M
}
else if (gap > 1)
{
+ this._discord.Logger.LogDebug("Gap {gap}", gap);
var lastSampleCount = this._opus.GetLastPacketSampleCount(vtx.Decoder);
for (var i = 0; i < gap; i++)
{
@@ -741,6 +747,12 @@ private bool ProcessPacket(ReadOnlySpan data, ref Memory opus, ref M
var pcmSpan = pcm.Span;
this._opus.Decode(vtx.Decoder, opusSpan, ref pcmSpan, false, out outputFormat);
pcm = pcm[..pcmSpan.Length];
+ this._discord.Logger.LogDebug("Done with processing packet...");
+ }
+ catch (Exception ex)
+ {
+ this._discord.Logger.LogDebug("Exception in ProcessPacket: {ex}", ex.Message);
+ this._discord.Logger.LogDebug("Stack: {ex}", ex.StackTrace);
}
finally
{
@@ -762,6 +774,7 @@ private async Task ProcessVoicePacket(byte[] data)
try
{
+ this._discord.Logger.LogDebug("Received voice data preparing..");
var pcm = new byte[this.AudioFormat.CalculateMaximumFrameSize()];
var pcmMem = pcm.AsMemory();
var opus = new byte[pcm.Length];
@@ -770,6 +783,7 @@ private async Task ProcessVoicePacket(byte[] data)
if (!this.ProcessPacket(data, ref opusMem, ref pcmMem, pcmFillers, out var vtx, out var audioFormat))
return;
+ this._discord.Logger.LogDebug("Received voice data processing..");
foreach (var pcmFiller in pcmFillers)
await this._voiceReceived.InvokeAsync(this, new VoiceReceiveEventArgs(this._discord.ServiceProvider)
{
@@ -1140,19 +1154,19 @@ private async Task HandleDispatch(JObject jo)
switch (opc)
{
case 2: // READY
- this._discord.Logger.LogTrace(VoiceNextEvents.VoiceDispatch, "Received READY (OP2)");
+ this._discord.Logger.LogDebug(VoiceNextEvents.VoiceDispatch, "Received READY (OP2)");
var vrp = opp.ToObject();
this._ssrc = vrp.Ssrc;
this.UdpEndpoint = new ConnectionEndpoint(vrp.Address, vrp.Port);
// this is not the valid interval
// oh, discord
//this.HeartbeatInterval = vrp.HeartbeatInterval;
- this._heartbeatTask = Task.Run(this.HeartbeatAsync);
+ this._heartbeatTask = Task.Run(this.HeartbeatAsync, this.TOKEN);
await this.Stage1(vrp).ConfigureAwait(false);
break;
case 4: // SESSION_DESCRIPTION
- this._discord.Logger.LogTrace(VoiceNextEvents.VoiceDispatch, "Received SESSION_DESCRIPTION (OP4)");
+ this._discord.Logger.LogDebug(VoiceNextEvents.VoiceDispatch, "Received SESSION_DESCRIPTION (OP4)");
var vsd = opp.ToObject();
this._key = vsd.SecretKey;
this._sodium = new Sodium(this._key.AsMemory());
@@ -1162,7 +1176,7 @@ private async Task HandleDispatch(JObject jo)
case 5: // SPEAKING
// Don't spam OP5
// No longer spam, Discord supposedly doesn't send many of these
- this._discord.Logger.LogTrace(VoiceNextEvents.VoiceDispatch, "Received SPEAKING (OP5)");
+ this._discord.Logger.LogDebug(VoiceNextEvents.VoiceDispatch, "Received SPEAKING (OP5): {oop}", opp.ToString(Formatting.Indented));
var spd = opp.ToObject();
var foundUserInCache = this._discord.TryGetCachedUserInternal(spd.UserId.Value, out var resolvedUser);
var spk = new UserSpeakingEventArgs(this._discord.ServiceProvider)
@@ -1201,17 +1215,17 @@ private async Task HandleDispatch(JObject jo)
case 8: // HELLO
// this sends a heartbeat interval that we need to use for heartbeating
- this._discord.Logger.LogTrace(VoiceNextEvents.VoiceDispatch, "Received HELLO (OP8)");
+ this._discord.Logger.LogDebug(VoiceNextEvents.VoiceDispatch, "Received HELLO (OP8)");
this._heartbeatInterval = opp["heartbeat_interval"].ToObject();
break;
case 9: // RESUMED
- this._discord.Logger.LogTrace(VoiceNextEvents.VoiceDispatch, "Received RESUMED (OP9)");
+ this._discord.Logger.LogDebug(VoiceNextEvents.VoiceDispatch, "Received RESUMED (OP9)");
this._heartbeatTask = Task.Run(this.HeartbeatAsync);
break;
case 12: // CLIENT_CONNECTED
- this._discord.Logger.LogTrace(VoiceNextEvents.VoiceDispatch, "Received CLIENT_CONNECTED (OP12)");
+ this._discord.Logger.LogDebug(VoiceNextEvents.VoiceDispatch, "Received CLIENT_CONNECTED (OP12)");
var ujpd = opp.ToObject();
var usrj = await this._discord.GetUserAsync(ujpd.UserId, true).ConfigureAwait(false);
{
@@ -1229,7 +1243,7 @@ private async Task HandleDispatch(JObject jo)
break;
case 13: // CLIENT_DISCONNECTED
- this._discord.Logger.LogTrace(VoiceNextEvents.VoiceDispatch, "Received CLIENT_DISCONNECTED (OP13)");
+ this._discord.Logger.LogDebug(VoiceNextEvents.VoiceDispatch, "Received CLIENT_DISCONNECTED (OP13)");
var ulpd = opp.ToObject();
var txssrc = this._transmittingSsrCs.FirstOrDefault(x => x.Value.Id == ulpd.UserId);
if (this._transmittingSsrCs.ContainsKey(txssrc.Key))
@@ -1247,7 +1261,7 @@ private async Task HandleDispatch(JObject jo)
break;
default:
- this._discord.Logger.LogTrace(VoiceNextEvents.VoiceDispatch, "Received unknown voice opcode (OP{0})", opc);
+ this._discord.Logger.LogDebug(VoiceNextEvents.VoiceDispatch, "Received unknown voice opcode (OP {0}): {data}", opc, opp.ToString(Formatting.Indented));
break;
}
}
diff --git a/DisCatSharp.sln b/DisCatSharp.sln
index f830cccaaf..17e4560ea4 100644
--- a/DisCatSharp.sln
+++ b/DisCatSharp.sln
@@ -93,6 +93,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DisCatSharp.SafetyTests", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DisCatSharp.Lavalink", "DisCatSharp.Lavalink\DisCatSharp.Lavalink.csproj", "{1ADC1D06-3DB8-4741-B740-13161B40CBA3}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DiscatSharp.Voice", "DiscatSharp.Voice\DiscatSharp.Voice.csproj", "{69DF6B77-4A27-4D48-BB05-D25DF93A2AD0}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -163,6 +165,10 @@ Global
{1ADC1D06-3DB8-4741-B740-13161B40CBA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1ADC1D06-3DB8-4741-B740-13161B40CBA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1ADC1D06-3DB8-4741-B740-13161B40CBA3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {69DF6B77-4A27-4D48-BB05-D25DF93A2AD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {69DF6B77-4A27-4D48-BB05-D25DF93A2AD0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {69DF6B77-4A27-4D48-BB05-D25DF93A2AD0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {69DF6B77-4A27-4D48-BB05-D25DF93A2AD0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/DisCatSharp/Net/Rest/DiscordApiClient.cs b/DisCatSharp/Net/Rest/DiscordApiClient.cs
index 047f92b2d0..ed10cfced5 100644
--- a/DisCatSharp/Net/Rest/DiscordApiClient.cs
+++ b/DisCatSharp/Net/Rest/DiscordApiClient.cs
@@ -6026,7 +6026,6 @@ internal async Task ModifyCurrentApplicationInfoAsync(
ConverImageBase64 = coverImageb64,
Flags = flags,
InstallParams = installParams
-
};
var route = $"{Endpoints.APPLICATIONS}{Endpoints.ME}";
diff --git a/DiscatSharp.Voice/Class1.cs b/DiscatSharp.Voice/Class1.cs
new file mode 100644
index 0000000000..1c0e09c90f
--- /dev/null
+++ b/DiscatSharp.Voice/Class1.cs
@@ -0,0 +1,27 @@
+// This file is part of the DisCatSharp project, based off DSharpPlus.
+//
+// Copyright (c) 2021-2023 AITSYS
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+namespace DisCatSharp.Voice;
+public class Class1
+{
+
+}
diff --git a/DiscatSharp.Voice/DiscatSharp.Voice.csproj b/DiscatSharp.Voice/DiscatSharp.Voice.csproj
new file mode 100644
index 0000000000..3e09efbd53
--- /dev/null
+++ b/DiscatSharp.Voice/DiscatSharp.Voice.csproj
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+ DisCatSharp.Voice
+ DisCatSharp.Voice
+ true
+
+
+
+ DisCatSharp.Voice
+
+ DisCatSharp Voice Extension
+
+ Easy made audio player for discord bots.
+
+ Documentation: https://docs.dcs.aitsys.dev/articles/modules/audio/voice/intro.html
+
+ DisCatSharp,Discord API Wrapper,Discord,Bots,Discord Bots,AITSYS,Net6,Net7,Voice,Audio Player
+ annotations
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+