Skip to content

Commit c78296f

Browse files
authored
[Fix] NRE in message commands in user app contexts (#3035)
* bump few more things * expose `MentionedRoleIds` on `SocketMessage` + add some syntax sugar * right, we can't have nice things cuz netfx * omfg that's an I/O operation in ctor bruh
1 parent d5879c8 commit c78296f

File tree

5 files changed

+45
-30
lines changed

5 files changed

+45
-30
lines changed

src/Discord.Net.Commands/Discord.Net.Commands.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@
2020
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="All" />
2121
</ItemGroup>
2222
<ItemGroup>
23-
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
23+
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />
2424
</ItemGroup>
2525
</Project>

src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ public abstract class SocketMessage : SocketEntity<ulong>, IMessage
1616
{
1717
#region SocketMessage
1818
private long _timestampTicks;
19-
private readonly List<SocketReaction> _reactions = new List<SocketReaction>();
20-
private ImmutableArray<SocketUser> _userMentions = ImmutableArray.Create<SocketUser>();
19+
private readonly List<SocketReaction> _reactions = [];
20+
private ImmutableArray<SocketUser> _userMentions = [];
2121

2222
/// <summary>
2323
/// Gets the author of this message.
@@ -113,18 +113,26 @@ public abstract class SocketMessage : SocketEntity<ulong>, IMessage
113113
/// <returns>
114114
/// Collection of WebSocket-based guild channels.
115115
/// </returns>
116-
public virtual IReadOnlyCollection<SocketGuildChannel> MentionedChannels => ImmutableArray.Create<SocketGuildChannel>();
116+
public virtual IReadOnlyCollection<SocketGuildChannel> MentionedChannels => [];
117117
/// <summary>
118118
/// Returns the roles mentioned in this message.
119119
/// </summary>
120+
/// <remarks>
121+
/// This collection may be missing values due to the guild being missing from cache (i.e. in user app interaction context).
122+
/// In that case you can use the <see cref="MentionedRoleIds"/> property.
123+
/// </remarks>
120124
/// <returns>
121125
/// Collection of WebSocket-based roles.
122126
/// </returns>
123-
public virtual IReadOnlyCollection<SocketRole> MentionedRoles => ImmutableArray.Create<SocketRole>();
127+
public virtual IReadOnlyCollection<SocketRole> MentionedRoles => [];
128+
129+
/// <inheritdoc />
130+
public virtual IReadOnlyCollection<ulong> MentionedRoleIds => [];
131+
124132
/// <inheritdoc />
125-
public virtual IReadOnlyCollection<ITag> Tags => ImmutableArray.Create<ITag>();
133+
public virtual IReadOnlyCollection<ITag> Tags => [];
126134
/// <inheritdoc />
127-
public virtual IReadOnlyCollection<SocketSticker> Stickers => ImmutableArray.Create<SocketSticker>();
135+
public virtual IReadOnlyCollection<SocketSticker> Stickers => [];
128136
/// <inheritdoc />
129137
public IReadOnlyDictionary<IEmote, ReactionMetadata> Reactions => _reactions.GroupBy(r => r.Emote).ToDictionary(x => x.Key, x => new ReactionMetadata { ReactionCount = x.Count(), IsMe = x.Any(y => y.UserId == Discord.CurrentUser.Id) });
130138
/// <summary>
@@ -271,7 +279,8 @@ internal virtual void Update(ClientState state, Model model)
271279
var val = value[i];
272280
if (val != null)
273281
{
274-
var user = Channel.GetUserAsync(val.Id, CacheMode.CacheOnly).GetAwaiter().GetResult() as SocketUser;
282+
// TODO: this is cursed af and should be yeeted
283+
var user = Channel?.GetUserAsync(val.Id, CacheMode.CacheOnly).GetAwaiter().GetResult() as SocketUser;
275284
if (user != null)
276285
newMentions.Add(user);
277286
else
@@ -346,8 +355,6 @@ public Task DeleteAsync(RequestOptions options = null)
346355
/// <inheritdoc />
347356
IReadOnlyCollection<ulong> IMessage.MentionedChannelIds => MentionedChannels.Select(x => x.Id).ToImmutableArray();
348357
/// <inheritdoc />
349-
IReadOnlyCollection<ulong> IMessage.MentionedRoleIds => MentionedRoles.Select(x => x.Id).ToImmutableArray();
350-
/// <inheritdoc />
351358
IReadOnlyCollection<ulong> IMessage.MentionedUserIds => MentionedUsers.Select(x => x.Id).ToImmutableArray();
352359

353360
/// <inheritdoc/>

src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@ public class SocketUserMessage : SocketMessage, IUserMessage
1818
private bool _isMentioningEveryone, _isTTS, _isPinned;
1919
private long? _editedTimestampTicks;
2020
private IUserMessage _referencedMessage;
21-
private ImmutableArray<Attachment> _attachments = ImmutableArray.Create<Attachment>();
22-
private ImmutableArray<Embed> _embeds = ImmutableArray.Create<Embed>();
23-
private ImmutableArray<ITag> _tags = ImmutableArray.Create<ITag>();
24-
private ImmutableArray<SocketRole> _roleMentions = ImmutableArray.Create<SocketRole>();
25-
private ImmutableArray<SocketSticker> _stickers = ImmutableArray.Create<SocketSticker>();
21+
private ImmutableArray<Attachment> _attachments = [];
22+
private ImmutableArray<Embed> _embeds = [];
23+
private ImmutableArray<ITag> _tags = [];
24+
private ImmutableArray<SocketRole> _roleMentions;
25+
private ImmutableArray<ulong> _roleMentionsIds = [];
26+
private ImmutableArray<SocketSticker> _stickers = [];
2627

2728
/// <inheritdoc />
2829
public override bool IsTTS => _isTTS;
@@ -44,6 +45,9 @@ public class SocketUserMessage : SocketMessage, IUserMessage
4445
public override IReadOnlyCollection<SocketGuildChannel> MentionedChannels => MessageHelper.FilterTagsByValue<SocketGuildChannel>(TagType.ChannelMention, _tags);
4546
/// <inheritdoc />
4647
public override IReadOnlyCollection<SocketRole> MentionedRoles => _roleMentions;
48+
/// <inheritdoc />
49+
public override IReadOnlyCollection<ulong> MentionedRoleIds => _roleMentionsIds;
50+
4751
/// <inheritdoc />
4852
public override IReadOnlyCollection<SocketSticker> Stickers => _stickers;
4953
/// <inheritdoc />
@@ -64,6 +68,7 @@ public class SocketUserMessage : SocketMessage, IUserMessage
6468
internal SocketUserMessage(DiscordSocketClient discord, ulong id, ISocketMessageChannel channel, SocketUser author, MessageSource source)
6569
: base(discord, id, channel, author, source)
6670
{
71+
_roleMentions = ImmutableArray.Create<SocketRole>();
6772
}
6873
internal new static SocketUserMessage Create(DiscordSocketClient discord, ClientState state, SocketUser author, ISocketMessageChannel channel, Model model)
6974
{
@@ -87,7 +92,12 @@ internal override void Update(ClientState state, Model model)
8792
if (model.MentionEveryone.IsSpecified)
8893
_isMentioningEveryone = model.MentionEveryone.Value;
8994
if (model.RoleMentions.IsSpecified)
90-
_roleMentions = model.RoleMentions.Value.Select(x => guild.GetRole(x)).ToImmutableArray();
95+
{
96+
if (guild is not null)
97+
_roleMentions = model.RoleMentions.Value.Select(x => guild.GetRole(x)).ToImmutableArray();
98+
_roleMentionsIds = model.RoleMentions.Value.ToImmutableArray();
99+
}
100+
91101

92102
if (model.Attachments.IsSpecified)
93103
{
@@ -100,7 +110,7 @@ internal override void Update(ClientState state, Model model)
100110
_attachments = attachments.ToImmutable();
101111
}
102112
else
103-
_attachments = ImmutableArray.Create<Attachment>();
113+
_attachments = [];
104114
}
105115

106116
if (model.Embeds.IsSpecified)
@@ -114,7 +124,7 @@ internal override void Update(ClientState state, Model model)
114124
_embeds = embeds.ToImmutable();
115125
}
116126
else
117-
_embeds = ImmutableArray.Create<Embed>();
127+
_embeds = [];
118128
}
119129

120130
if (model.Content.IsSpecified)
@@ -155,34 +165,32 @@ internal override void Update(ClientState state, Model model)
155165
if (value.Length > 0)
156166
{
157167
var stickers = ImmutableArray.CreateBuilder<SocketSticker>(value.Length);
158-
for (int i = 0; i < value.Length; i++)
168+
foreach (var stickerItem in value)
159169
{
160-
var stickerItem = value[i];
161170
SocketSticker sticker = null;
162171

163172
if (guild != null)
164173
sticker = guild.GetSticker(stickerItem.Id);
165174

166-
if (sticker == null)
167-
sticker = Discord.GetSticker(stickerItem.Id);
175+
sticker ??= Discord.GetSticker(stickerItem.Id);
168176

169177
// if they want to auto resolve
170178
if (Discord.AlwaysResolveStickers)
171179
{
172-
sticker = Task.Run(async () => await Discord.GetStickerAsync(stickerItem.Id).ConfigureAwait(false)).GetAwaiter().GetResult();
180+
var item = stickerItem;
181+
sticker = Task.Run(async () => await Discord.GetStickerAsync(item.Id).ConfigureAwait(false)).GetAwaiter().GetResult();
173182
}
174183

175184
// if its still null, create an unknown
176-
if (sticker == null)
177-
sticker = SocketUnknownSticker.Create(Discord, stickerItem);
185+
sticker ??= SocketUnknownSticker.Create(Discord, stickerItem);
178186

179187
stickers.Add(sticker);
180188
}
181189

182190
_stickers = stickers.ToImmutable();
183191
}
184192
else
185-
_stickers = ImmutableArray.Create<SocketSticker>();
193+
_stickers = [];
186194
}
187195

188196
if (model.Resolved.IsSpecified)

test/Discord.Net.Tests.Integration/Discord.Net.Tests.Integration.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
</ItemGroup>
1515

1616
<ItemGroup>
17-
<PackageReference Include="FluentAssertions" Version="6.12.2" />
18-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
17+
<PackageReference Include="FluentAssertions" Version="7.0.0" />
18+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
1919
<PackageReference Include="xunit" Version="2.9.2" />
2020
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
2121
<PrivateAssets>all</PrivateAssets>

test/Discord.Net.Tests.Unit/Discord.Net.Tests.Unit.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
<ProjectReference Include="../../src/Discord.Net.WebSocket/Discord.Net.WebSocket.csproj" />
1313
</ItemGroup>
1414
<ItemGroup>
15-
<PackageReference Include="FluentAssertions" Version="6.12.2" />
16-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
15+
<PackageReference Include="FluentAssertions" Version="7.0.0" />
16+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
1717
<PackageReference Include="NSubstitute" Version="5.3.0" />
1818
<PackageReference Include="xunit" Version="2.9.2" />
1919
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">

0 commit comments

Comments
 (0)