Skip to content

Commit 20dbcba

Browse files
committed
fix: possible json deserializer exception
Log if DiscordJson fails
1 parent 1cf4a64 commit 20dbcba

File tree

7 files changed

+102
-8
lines changed

7 files changed

+102
-8
lines changed

DisCatSharp.Common/Types/MemoryBuffer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ private void WriteStreamSeekable(Stream stream)
139139

140140
var lsl = this._lastSegmentLength;
141141
var slen = dmem.Span.Length - lsl;
142-
stream.Read(buff, 0, slen);
142+
_ = stream.Read(buff, 0, slen);
143143
buff.AsSpan(0, slen).CopyTo(dmem.Span);
144144
len -= dmem.Span.Length;
145145

DisCatSharp.VoiceNext/VoiceNextConnection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1165,7 +1165,7 @@ private async Task Stage2(VoiceSessionDescriptionPayload voiceSessionDescription
11651165
/// <returns>A Task.</returns>
11661166
private async Task HandleDispatch(JObject jo)
11671167
{
1168-
var opc = (int)jo["op"];
1168+
var opc = (int?)jo["op"];
11691169
ArgumentNullException.ThrowIfNull(opc);
11701170
var opp = jo["d"] as JObject;
11711171

DisCatSharp/DiscordConfiguration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ internal List<Type> TrackExceptions
312312
/// <summary>
313313
/// The exception we track with sentry.
314314
/// </summary>
315-
private List<Type> _exceptions = [typeof(ServerErrorException), typeof(BadRequestException)];
315+
private List<Type> _exceptions = [typeof(ServerErrorException), typeof(BadRequestException), typeof(DiscordJsonException)];
316316

317317
/// <summary>
318318
/// <para>Whether to enable the library developer mode.</para>

DisCatSharp/Entities/Message/DiscordMessage.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,14 +361,14 @@ public DiscordMessageReference Reference
361361
/// <summary>
362362
/// Gets whether this message has a message reference (reply, announcement, etc.).
363363
/// </summary>
364-
[Experimental("We provide that temporary, as we figure out things.")]
364+
[Experimental("We provide that temporary, as we figure out things."), JsonIgnore]
365365
public bool HasMessageReference
366366
=> this.InternalReference is { Type: ReferenceType.Default };
367367

368368
/// <summary>
369369
/// Gets whether this message has forwarded messages.
370370
/// </summary>
371-
[Experimental("We provide that temporary, as we figure out things.")]
371+
[Experimental("We provide that temporary, as we figure out things."), JsonIgnore]
372372
public bool HasMessageSnapshots
373373
=> this.InternalReference is { Type: ReferenceType.Forward };
374374

DisCatSharp/Exceptions/DisCatSharpException.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,16 @@ public class DisCatSharpException : Exception
1111
/// Initializes a new instance of the <see cref="DisCatSharpException"/> class.
1212
/// </summary>
1313
/// <param name="message">The error message.</param>
14-
internal DisCatSharpException(string message)
14+
internal DisCatSharpException(string? message)
1515
: base(message)
1616
{ }
17+
18+
/// <summary>
19+
/// Initializes a new instance of the <see cref="DisCatSharpException"/> class.
20+
/// </summary>
21+
/// <param name="message">The error message.</param>
22+
/// <param name="innerException">The inner exception.</param>
23+
internal DisCatSharpException(string? message, Exception? innerException)
24+
: base(message, innerException)
25+
{ }
1726
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using Newtonsoft.Json;
2+
3+
namespace DisCatSharp.Exceptions;
4+
5+
/// <summary>
6+
/// Represents a <see cref="DiscordJsonException"/>.
7+
/// </summary>
8+
public sealed class DiscordJsonException : DisCatSharpException
9+
{
10+
/// <summary>
11+
/// Gets the line number indicating where the error occurred.
12+
/// </summary>
13+
/// <value>The line number indicating where the error occurred.</value>
14+
public int LineNumber { get; }
15+
16+
/// <summary>
17+
/// Gets the line position indicating where the error occurred.
18+
/// </summary>
19+
/// <value>The line position indicating where the error occurred.</value>
20+
public int LinePosition { get; }
21+
22+
/// <summary>
23+
/// Gets the path to the JSON where the error occurred.
24+
/// </summary>
25+
/// <value>The path to the JSON where the error occurred.</value>
26+
public string? Path { get; }
27+
28+
/// <summary>
29+
/// Initializes a new instance of the <see cref="DiscordJsonException"/> class.
30+
/// </summary>
31+
/// <param name="jre">The JSON reader exception.</param>
32+
public DiscordJsonException(JsonReaderException jre)
33+
: base(jre.Message, jre.InnerException)
34+
{
35+
this.Path = jre.Path;
36+
this.LineNumber = jre.LineNumber;
37+
this.LinePosition = jre.LinePosition;
38+
this.HResult = jre.HResult;
39+
this.HelpLink = jre.HelpLink;
40+
}
41+
}

DisCatSharp/Net/Serialization/DiscordJson.cs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,17 @@
66
using System.Threading.Tasks;
77

88
using DisCatSharp.Entities;
9+
using DisCatSharp.Exceptions;
910

1011
using Microsoft.Extensions.Logging;
1112

1213
using Newtonsoft.Json;
1314
using Newtonsoft.Json.Linq;
1415

1516
using Sentry;
17+
using Sentry.Protocol;
18+
19+
using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
1620

1721
namespace DisCatSharp.Net.Serialization;
1822

@@ -89,6 +93,43 @@ private static string SerializeObjectInternal(object value, Type type, JsonSeria
8993
return stringWriter.ToString();
9094
}
9195

96+
/// <summary>
97+
/// Handles <see cref="DiscordJson"/> errors.
98+
/// </summary>
99+
/// <param name="sender">The sender.</param>
100+
/// <param name="e">The error event args.</param>
101+
/// <param name="discord">The discord client.</param>
102+
private static void DiscordJsonErrorHandler(object? sender, ErrorEventArgs e, BaseDiscordClient? discord)
103+
{
104+
if (discord is null || e.ErrorContext.Error is not JsonReaderException jre)
105+
return;
106+
107+
var sentryMessage = "DiscordJson error on deserialization (" + (sender?.GetType().Name ?? "x") + ")\n\n" +
108+
"Path: " + e.ErrorContext.Path + "\n" +
109+
"Original Object" + e.ErrorContext.OriginalObject + "\n" +
110+
"Current Object" + e.CurrentObject;
111+
SentryEvent sentryEvent = new(new DiscordJsonException(jre))
112+
{
113+
Level = SentryLevel.Error,
114+
Logger = nameof(DiscordJson),
115+
Message = sentryMessage
116+
};
117+
sentryEvent.SetFingerprint(BaseDiscordClient.GenerateSentryFingerPrint(sentryEvent));
118+
if (discord.Configuration.AttachUserInfo && discord.CurrentUser is not null)
119+
sentryEvent.User = new()
120+
{
121+
Id = discord.CurrentUser.Id.ToString(),
122+
Username = discord.CurrentUser.UsernameWithDiscriminator,
123+
Other = new Dictionary<string, string>()
124+
{
125+
{ "developer", discord.Configuration.DeveloperUserId?.ToString() ?? "not_given" },
126+
{ "email", discord.Configuration.FeedbackEmail ?? "not_given" }
127+
}
128+
};
129+
var sid = discord.Sentry.CaptureEvent(sentryEvent);
130+
_ = Task.Run(discord.Sentry.FlushAsync);
131+
}
132+
92133
/// <summary>
93134
/// Deserializes the specified JSON string to an object.
94135
/// </summary>
@@ -101,8 +142,10 @@ private static T DeserializeObjectInternal<T>(string? json, BaseDiscordClient? d
101142

102143
var obj = JsonConvert.DeserializeObject<T>(json, new JsonSerializerSettings()
103144
{
104-
ContractResolver = new OptionalJsonContractResolver()
145+
ContractResolver = new OptionalJsonContractResolver(),
146+
Error = (s, e) => DiscordJsonErrorHandler(s, e, discord)
105147
})!;
148+
106149
if (discord is null)
107150
return obj;
108151

@@ -176,7 +219,8 @@ private static T DeserializeIEnumerableObjectInternal<T>(string? json, BaseDisco
176219

177220
var obj = JsonConvert.DeserializeObject<T>(json, new JsonSerializerSettings()
178221
{
179-
ContractResolver = new OptionalJsonContractResolver()
222+
ContractResolver = new OptionalJsonContractResolver(),
223+
Error = (s, e) => DiscordJsonErrorHandler(s, e, discord)
180224
})!;
181225
if (discord is null)
182226
return obj;

0 commit comments

Comments
 (0)