Browse Source

Code cleanup and simplification

pull/1923/head
quin lynch 3 years ago
parent
commit
8e19bd77ea
14 changed files with 216 additions and 582 deletions
  1. +2
    -2
      src/Discord.Net.Rest/API/Common/ApplicationCommandInteractionData.cs
  2. +14
    -0
      src/Discord.Net.Rest/API/Net/IResolvable.cs
  3. +25
    -31
      src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml
  4. +1
    -1
      src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/Message Commands/SocketMessageCommand.cs
  5. +12
    -116
      src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/Message Commands/SocketMessageCommandData.cs
  6. +1
    -1
      src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/User Commands/SocketUserCommand.cs
  7. +10
    -88
      src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/User Commands/SocketUserCommandData.cs
  8. +1
    -1
      src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommand.cs
  9. +5
    -89
      src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommandData.cs
  10. +12
    -10
      src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommandDataOption.cs
  11. +1
    -1
      src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBase.cs
  12. +19
    -108
      src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBaseData.cs
  13. +0
    -134
      src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBaseDataOption.cs
  14. +113
    -0
      src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketResolvableData.cs

+ 2
- 2
src/Discord.Net.Rest/API/Common/ApplicationCommandInteractionData.cs View File

@@ -3,7 +3,7 @@ using System.Collections.Generic;

namespace Discord.API
{
internal class ApplicationCommandInteractionData : IDiscordInteractionData
internal class ApplicationCommandInteractionData : IResolvable, IDiscordInteractionData
{
[JsonProperty("id")]
public ulong Id { get; set; }
@@ -18,7 +18,7 @@ namespace Discord.API
public Optional<ApplicationCommandInteractionDataResolved> Resolved { get; set; }

[JsonProperty("type")]
public Optional<ApplicationCommandType> Type { get; set; }
public ApplicationCommandType Type { get; set; }

}
}

+ 14
- 0
src/Discord.Net.Rest/API/Net/IResolvable.cs View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Discord.API
{
internal interface IResolvable
{
Optional<ApplicationCommandInteractionDataResolved> Resolved { get; }

}
}

+ 25
- 31
src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml View File

@@ -3617,8 +3617,16 @@
Represents the data tied with the <see cref="T:Discord.WebSocket.SocketMessageCommand"/> interaction.
</summary>
</member>
<member name="P:Discord.WebSocket.SocketMessageCommandData.Name">
<member name="P:Discord.WebSocket.SocketMessageCommandData.Message">
<summary>
Gets the messagte associated with this message command.
</summary>
</member>
<member name="P:Discord.WebSocket.SocketMessageCommandData.Options">
<inheritdoc/>
<remarks>
<b>Note</b> Not implemented for <see cref="T:Discord.WebSocket.SocketMessageCommandData"/>
</remarks>
</member>
<member name="T:Discord.WebSocket.SocketUserCommand">
<summary>
@@ -3635,8 +3643,16 @@
Represents the data tied with the <see cref="T:Discord.WebSocket.SocketUserCommand"/> interaction.
</summary>
</member>
<member name="P:Discord.WebSocket.SocketUserCommandData.Name">
<member name="P:Discord.WebSocket.SocketUserCommandData.Member">
<summary>
The user used to run the command
</summary>
</member>
<member name="P:Discord.WebSocket.SocketUserCommandData.Options">
<inheritdoc/>
<remarks>
<b>Note</b> Not implemented for <see cref="T:Discord.WebSocket.SocketUserCommandData"/>
</remarks>
</member>
<member name="T:Discord.WebSocket.SocketMessageComponent">
<summary>
@@ -3715,14 +3731,6 @@
Represents the data tied with the <see cref="T:Discord.WebSocket.SocketSlashCommand"/> interaction.
</summary>
</member>
<member name="P:Discord.WebSocket.SocketSlashCommandData.Name">
<inheritdoc/>
</member>
<member name="P:Discord.WebSocket.SocketSlashCommandData.Options">
<summary>
The <see cref="T:Discord.WebSocket.SocketSlashCommandDataOption"/>'s received with this interaction.
</summary>
</member>
<member name="T:Discord.WebSocket.SocketSlashCommandDataOption">
<summary>
Represents a Websocket-based <see cref="T:Discord.IApplicationCommandInteractionDataOption"/> recieved by the gateway
@@ -3821,7 +3829,7 @@
</member>
<member name="T:Discord.WebSocket.SocketCommandBase">
<summary>
Base class for User, Message, and Slash command interactions
Base class for User, Message, and Slash command interactions
</summary>
</member>
<member name="P:Discord.WebSocket.SocketCommandBase.Data">
@@ -3843,36 +3851,22 @@
A task that represents the asynchronous operation of acknowledging the interaction.
</returns>
</member>
<member name="T:Discord.WebSocket.SocketCommandBaseData">
<member name="T:Discord.WebSocket.SocketCommandBaseData`1">
<summary>
Represents the base data tied with the <see cref="T:Discord.WebSocket.SocketCommandBase"/> interaction.
</summary>
</member>
<member name="P:Discord.WebSocket.SocketCommandBaseData.Name">
<member name="P:Discord.WebSocket.SocketCommandBaseData`1.Name">
<inheritdoc/>
</member>
<member name="P:Discord.WebSocket.SocketCommandBaseData.Options">
<member name="P:Discord.WebSocket.SocketCommandBaseData`1.Options">
<summary>
The <see cref="T:Discord.WebSocket.SocketCommandBaseDataOption"/>'s received with this interaction.
The <typeparamref name="TOption"/> received with this interaction.
</summary>
</member>
<member name="T:Discord.WebSocket.SocketCommandBaseDataOption">
<summary>
Represents the base Websocket-based <see cref="T:Discord.IApplicationCommandInteractionDataOption"/> recieved by the gateway
</summary>
</member>
<member name="P:Discord.WebSocket.SocketCommandBaseDataOption.Name">
<inheritdoc/>
</member>
<member name="P:Discord.WebSocket.SocketCommandBaseDataOption.Value">
<inheritdoc/>
</member>
<member name="P:Discord.WebSocket.SocketCommandBaseDataOption.Type">
<inheritdoc/>
</member>
<member name="P:Discord.WebSocket.SocketCommandBaseDataOption.Options">
<member name="T:Discord.WebSocket.SocketCommandBaseData">
<summary>
The sub command options received for this sub command group.
Represents the base data tied with the <see cref="T:Discord.WebSocket.SocketCommandBase"/> interaction.
</summary>
</member>
<member name="T:Discord.WebSocket.SocketInteraction">


+ 1
- 1
src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/Message Commands/SocketMessageCommand.cs View File

@@ -15,7 +15,7 @@ namespace Discord.WebSocket
/// <summary>
/// The data associated with this interaction.
/// </summary>
new public SocketMessageCommandData Data { get; }
public new SocketMessageCommandData Data { get; }

internal SocketMessageCommand(DiscordSocketClient client, Model model, ISocketMessageChannel channel)
: base(client, model, channel)


+ 12
- 116
src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/Message Commands/SocketMessageCommandData.cs View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Model = Discord.API.ApplicationCommandInteractionData;

@@ -8,132 +7,29 @@ namespace Discord.WebSocket
/// <summary>
/// Represents the data tied with the <see cref="SocketMessageCommand"/> interaction.
/// </summary>
public class SocketMessageCommandData : SocketEntity<ulong>, IApplicationCommandInteractionData
public class SocketMessageCommandData : SocketCommandBaseData
{
/// <inheritdoc/>
public string Name { get; private set; }
/// <summary>
/// The message selected to run the command
/// Gets the messagte associated with this message command.
/// </summary>
public SocketMessage Message { get; private set; }

internal Dictionary<ulong, SocketGuildUser> guildMembers { get; private set; }
= new Dictionary<ulong, SocketGuildUser>();
internal Dictionary<ulong, SocketGlobalUser> users { get; private set; }
= new Dictionary<ulong, SocketGlobalUser>();
internal Dictionary<ulong, SocketChannel> channels { get; private set; }
= new Dictionary<ulong, SocketChannel>();
internal Dictionary<ulong, SocketRole> roles { get; private set; }
= new Dictionary<ulong, SocketRole>();

IReadOnlyCollection<IApplicationCommandInteractionDataOption> IApplicationCommandInteractionData.Options => throw new System.NotImplementedException();
public SocketMessage Message
=> ResolvableData?.Messages.FirstOrDefault().Value;

private ulong? guildId;
/// <inheritdoc/>
/// <remarks>
/// <b>Note</b> Not implemented for <see cref="SocketMessageCommandData"/>
/// </remarks>
public override IReadOnlyCollection<IApplicationCommandInteractionDataOption> Options
=> throw new System.NotImplementedException();

internal SocketMessageCommandData(DiscordSocketClient client, Model model, ulong? guildId)
: base(client, model.Id)
{
this.guildId = guildId;

if (model.Resolved.IsSpecified)
{
var guild = this.guildId.HasValue ? Discord.GetGuild(this.guildId.Value) : null;

var resolved = model.Resolved.Value;

if (resolved.Users.IsSpecified)
{
foreach (var user in resolved.Users.Value)
{
var socketUser = Discord.GetOrCreateUser(this.Discord.State, user.Value);

this.users.Add(ulong.Parse(user.Key), socketUser);
}
}

if (resolved.Channels.IsSpecified)
{
foreach (var channel in resolved.Channels.Value)
{
SocketChannel socketChannel = guild != null
? guild.GetChannel(channel.Value.Id)
: Discord.GetChannel(channel.Value.Id);

if (socketChannel == null)
{
var channelModel = guild != null
? Discord.Rest.ApiClient.GetChannelAsync(guild.Id, channel.Value.Id).ConfigureAwait(false).GetAwaiter().GetResult()
: Discord.Rest.ApiClient.GetChannelAsync(channel.Value.Id).ConfigureAwait(false).GetAwaiter().GetResult();
: base(client, model, guildId) { }

socketChannel = guild != null
? SocketGuildChannel.Create(guild, Discord.State, channelModel)
: (SocketChannel)SocketChannel.CreatePrivate(Discord, Discord.State, channelModel);
}

Discord.State.AddChannel(socketChannel);
this.channels.Add(ulong.Parse(channel.Key), socketChannel);
}
}

if (resolved.Members.IsSpecified)
{
foreach (var member in resolved.Members.Value)
{
member.Value.User = resolved.Users.Value[member.Key];
var user = guild.AddOrUpdateUser(member.Value);
this.guildMembers.Add(ulong.Parse(member.Key), user);
}
}

if (resolved.Roles.IsSpecified)
{
foreach (var role in resolved.Roles.Value)
{
var socketRole = guild.AddOrUpdateRole(role.Value);
this.roles.Add(ulong.Parse(role.Key), socketRole);
}
}

if (resolved.Messages.IsSpecified)
{
foreach (var msg in resolved.Messages.Value)
{
var channel = client.GetChannel(msg.Value.ChannelId) as ISocketMessageChannel;

SocketUser author;
if (guild != null)
{
if (msg.Value.WebhookId.IsSpecified)
author = SocketWebhookUser.Create(guild, client.State, msg.Value.Author.Value, msg.Value.WebhookId.Value);
else
author = guild.GetUser(msg.Value.Author.Value.Id);
}
else
author = (channel as SocketChannel).GetUser(msg.Value.Author.Value.Id);

if (channel == null)
{
if (!msg.Value.GuildId.IsSpecified) // assume it is a DM
{
channel = client.CreateDMChannel(msg.Value.ChannelId, msg.Value.Author.Value, client.State);
}
}

this.Message = SocketMessage.Create(client, client.State, author, channel, msg.Value);
}
}
}
}

internal static SocketMessageCommandData Create(DiscordSocketClient client, Model model, ulong id, ulong? guildId)
internal new static SocketMessageCommandData Create(DiscordSocketClient client, Model model, ulong id, ulong? guildId)
{
var entity = new SocketMessageCommandData(client, model, guildId);
entity.Update(model);
return entity;
}
internal void Update(Model model)
{
this.Name = model.Name;
}
}
}

+ 1
- 1
src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/User Commands/SocketUserCommand.cs View File

@@ -15,7 +15,7 @@ namespace Discord.WebSocket
/// <summary>
/// The data associated with this interaction.
/// </summary>
new public SocketUserCommandData Data { get; }
public new SocketUserCommandData Data { get; }

internal SocketUserCommand(DiscordSocketClient client, Model model, ISocketMessageChannel channel)
: base(client, model, channel)


+ 10
- 88
src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/User Commands/SocketUserCommandData.cs View File

@@ -1,6 +1,4 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Model = Discord.API.ApplicationCommandInteractionData;

namespace Discord.WebSocket
@@ -8,104 +6,28 @@ namespace Discord.WebSocket
/// <summary>
/// Represents the data tied with the <see cref="SocketUserCommand"/> interaction.
/// </summary>
public class SocketUserCommandData : SocketEntity<ulong>, IApplicationCommandInteractionData
public class SocketUserCommandData : SocketCommandBaseData
{
/// <inheritdoc/>
public string Name { get; private set; }
/// <summary>
/// The user used to run the command
/// The user used to run the command
/// </summary>
public SocketUser Member { get; private set; }

internal Dictionary<ulong, SocketGuildUser> guildMembers { get; private set; }
= new Dictionary<ulong, SocketGuildUser>();
internal Dictionary<ulong, SocketGlobalUser> users { get; private set; }
= new Dictionary<ulong, SocketGlobalUser>();
internal Dictionary<ulong, SocketChannel> channels { get; private set; }
= new Dictionary<ulong, SocketChannel>();
internal Dictionary<ulong, SocketRole> roles { get; private set; }
= new Dictionary<ulong, SocketRole>();

IReadOnlyCollection<IApplicationCommandInteractionDataOption> IApplicationCommandInteractionData.Options => throw new System.NotImplementedException();

private ulong? guildId;
/// <inheritdoc/>
/// <remarks>
/// <b>Note</b> Not implemented for <see cref="SocketUserCommandData"/>
/// </remarks>
public override IReadOnlyCollection<IApplicationCommandInteractionDataOption> Options
=> throw new System.NotImplementedException();

internal SocketUserCommandData(DiscordSocketClient client, Model model, ulong? guildId)
: base(client, model.Id)
{
this.guildId = guildId;

if (model.Resolved.IsSpecified)
{
var guild = this.guildId.HasValue ? Discord.GetGuild(this.guildId.Value) : null;

var resolved = model.Resolved.Value;

if (resolved.Users.IsSpecified)
{
foreach (var user in resolved.Users.Value)
{
var socketUser = Discord.GetOrCreateUser(this.Discord.State, user.Value);

this.users.Add(ulong.Parse(user.Key), socketUser);
}
}
: base(client, model, guildId) { }

if (resolved.Channels.IsSpecified)
{
foreach (var channel in resolved.Channels.Value)
{
SocketChannel socketChannel = guild != null
? guild.GetChannel(channel.Value.Id)
: Discord.GetChannel(channel.Value.Id);

if (socketChannel == null)
{
var channelModel = guild != null
? Discord.Rest.ApiClient.GetChannelAsync(guild.Id, channel.Value.Id).ConfigureAwait(false).GetAwaiter().GetResult()
: Discord.Rest.ApiClient.GetChannelAsync(channel.Value.Id).ConfigureAwait(false).GetAwaiter().GetResult();

socketChannel = guild != null
? SocketGuildChannel.Create(guild, Discord.State, channelModel)
: (SocketChannel)SocketChannel.CreatePrivate(Discord, Discord.State, channelModel);
}

Discord.State.AddChannel(socketChannel);
this.channels.Add(ulong.Parse(channel.Key), socketChannel);
}
}

if (resolved.Members.IsSpecified)
{
foreach (var member in resolved.Members.Value)
{
member.Value.User = resolved.Users.Value[member.Key];
var user = guild.AddOrUpdateUser(member.Value);
this.guildMembers.Add(ulong.Parse(member.Key), user);
this.Member = user;
}
}

if (resolved.Roles.IsSpecified)
{
foreach (var role in resolved.Roles.Value)
{
var socketRole = guild.AddOrUpdateRole(role.Value);
this.roles.Add(ulong.Parse(role.Key), socketRole);
}
}
}
}

internal static SocketUserCommandData Create(DiscordSocketClient client, Model model, ulong id, ulong? guildId)
internal new static SocketUserCommandData Create(DiscordSocketClient client, Model model, ulong id, ulong? guildId)
{
var entity = new SocketUserCommandData(client, model, guildId);
entity.Update(model);
return entity;
}
internal void Update(Model model)
{
this.Name = model.Name;
}
}
}

+ 1
- 1
src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommand.cs View File

@@ -28,7 +28,7 @@ namespace Discord.WebSocket
if (this.Channel is SocketGuildChannel guildChannel)
guildId = guildChannel.Guild.Id;

Data = SocketSlashCommandData.Create(client, dataModel, model.Id, guildId);
Data = SocketSlashCommandData.Create(client, dataModel, guildId);
}

new internal static SocketInteraction Create(DiscordSocketClient client, Model model, ISocketMessageChannel channel)


+ 5
- 89
src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommandData.cs View File

@@ -8,108 +8,24 @@ namespace Discord.WebSocket
/// <summary>
/// Represents the data tied with the <see cref="SocketSlashCommand"/> interaction.
/// </summary>
public class SocketSlashCommandData : SocketEntity<ulong>, IApplicationCommandInteractionData
public class SocketSlashCommandData : SocketCommandBaseData<SocketSlashCommandDataOption>
{
/// <inheritdoc/>
public string Name { get; private set; }

/// <summary>
/// The <see cref="SocketSlashCommandDataOption"/>'s received with this interaction.
/// </summary>
public IReadOnlyCollection<SocketSlashCommandDataOption> Options { get; private set; }

internal Dictionary<ulong, SocketGuildUser> guildMembers { get; private set; }
= new Dictionary<ulong, SocketGuildUser>();
internal Dictionary<ulong, SocketGlobalUser> users { get; private set; }
= new Dictionary<ulong, SocketGlobalUser>();
internal Dictionary<ulong, SocketChannel> channels { get; private set; }
= new Dictionary<ulong, SocketChannel>();
internal Dictionary<ulong, SocketRole> roles { get; private set; }
= new Dictionary<ulong, SocketRole>();

private ulong? guildId;

internal SocketSlashCommandData(DiscordSocketClient client, Model model, ulong? guildId)
: base(client, model.Id)
{
this.guildId = guildId;

if (model.Resolved.IsSpecified)
{
var guild = this.guildId.HasValue ? Discord.GetGuild(this.guildId.Value) : null;

var resolved = model.Resolved.Value;

if (resolved.Users.IsSpecified)
{
foreach (var user in resolved.Users.Value)
{
var socketUser = Discord.GetOrCreateUser(this.Discord.State, user.Value);

this.users.Add(ulong.Parse(user.Key), socketUser);
}
}
: base(client, model, guildId) { }

if (resolved.Channels.IsSpecified)
{
foreach (var channel in resolved.Channels.Value)
{
SocketChannel socketChannel = guild != null
? guild.GetChannel(channel.Value.Id)
: Discord.GetChannel(channel.Value.Id);

if (socketChannel == null)
{
var channelModel = guild != null
? Discord.Rest.ApiClient.GetChannelAsync(guild.Id, channel.Value.Id).ConfigureAwait(false).GetAwaiter().GetResult()
: Discord.Rest.ApiClient.GetChannelAsync(channel.Value.Id).ConfigureAwait(false).GetAwaiter().GetResult();

socketChannel = guild != null
? SocketGuildChannel.Create(guild, Discord.State, channelModel)
: (SocketChannel)SocketChannel.CreatePrivate(Discord, Discord.State, channelModel);
}

Discord.State.AddChannel(socketChannel);
this.channels.Add(ulong.Parse(channel.Key), socketChannel);
}
}

if (resolved.Members.IsSpecified)
{
foreach (var member in resolved.Members.Value)
{
member.Value.User = resolved.Users.Value[member.Key];
var user = guild.AddOrUpdateUser(member.Value);
this.guildMembers.Add(ulong.Parse(member.Key), user);
}
}

if (resolved.Roles.IsSpecified)
{
foreach (var role in resolved.Roles.Value)
{
var socketRole = guild.AddOrUpdateRole(role.Value);
this.roles.Add(ulong.Parse(role.Key), socketRole);
}
}
}
}

internal static SocketSlashCommandData Create(DiscordSocketClient client, Model model, ulong id, ulong? guildId)
internal static SocketSlashCommandData Create(DiscordSocketClient client, Model model, ulong? guildId)
{
var entity = new SocketSlashCommandData(client, model, guildId);
entity.Update(model);
return entity;
}
internal void Update(Model model)
internal override void Update(Model model)
{
this.Name = model.Name;
base.Update(model);

this.Options = model.Options.IsSpecified
? model.Options.Value.Select(x => new SocketSlashCommandDataOption(this, x)).ToImmutableArray()
: null;
}

IReadOnlyCollection<IApplicationCommandInteractionDataOption> IApplicationCommandInteractionData.Options => Options;
}
}

+ 12
- 10
src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommandDataOption.cs View File

@@ -44,34 +44,34 @@ namespace Discord.WebSocket
{
case ApplicationCommandOptionType.User:
{
var guildUser = data.guildMembers.FirstOrDefault(x => x.Key == valueId).Value;
var guildUser = data.ResolvableData.GuildMembers.FirstOrDefault(x => x.Key == valueId).Value;

if (guildUser != null)
this.Value = guildUser;
else
this.Value = data.users.FirstOrDefault(x => x.Key == valueId).Value;
this.Value = data.ResolvableData.Users.FirstOrDefault(x => x.Key == valueId).Value;
}
break;
case ApplicationCommandOptionType.Channel:
this.Value = data.channels.FirstOrDefault(x => x.Key == valueId).Value;
this.Value = data.ResolvableData.Channels.FirstOrDefault(x => x.Key == valueId).Value;
break;
case ApplicationCommandOptionType.Role:
this.Value = data.roles.FirstOrDefault(x => x.Key == valueId).Value;
this.Value = data.ResolvableData.Roles.FirstOrDefault(x => x.Key == valueId).Value;
break;
case ApplicationCommandOptionType.Mentionable:
{
if(data.guildMembers.Any(x => x.Key == valueId) || data.users.Any(x => x.Key == valueId))
if(data.ResolvableData.GuildMembers.Any(x => x.Key == valueId) || data.ResolvableData.Users.Any(x => x.Key == valueId))
{
var guildUser = data.guildMembers.FirstOrDefault(x => x.Key == valueId).Value;
var guildUser = data.ResolvableData.GuildMembers.FirstOrDefault(x => x.Key == valueId).Value;

if (guildUser != null)
this.Value = guildUser;
else
this.Value = data.users.FirstOrDefault(x => x.Key == valueId).Value;
this.Value = data.ResolvableData.Users.FirstOrDefault(x => x.Key == valueId).Value;
}
else if(data.roles.Any(x => x.Key == valueId))
else if(data.ResolvableData.Roles.Any(x => x.Key == valueId))
{
this.Value = data.roles.FirstOrDefault(x => x.Key == valueId).Value;
this.Value = data.ResolvableData.Roles.FirstOrDefault(x => x.Key == valueId).Value;
}
}
break;
@@ -125,6 +125,8 @@ namespace Discord.WebSocket
public static explicit operator string(SocketSlashCommandDataOption option)
=> option.Value.ToString();

IReadOnlyCollection<IApplicationCommandInteractionDataOption> IApplicationCommandInteractionDataOption.Options => this.Options;
// IApplicationCommandInteractionDataOption
IReadOnlyCollection<IApplicationCommandInteractionDataOption> IApplicationCommandInteractionDataOption.Options
=> this.Options;
}
}

+ 1
- 1
src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBase.cs View File

@@ -10,7 +10,7 @@ using Model = Discord.API.Interaction;
namespace Discord.WebSocket
{
/// <summary>
/// Base class for User, Message, and Slash command interactions
/// Base class for User, Message, and Slash command interactions
/// </summary>
public class SocketCommandBase : SocketInteraction
{


+ 19
- 108
src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBaseData.cs View File

@@ -8,123 +8,28 @@ namespace Discord.WebSocket
/// <summary>
/// Represents the base data tied with the <see cref="SocketCommandBase"/> interaction.
/// </summary>
public class SocketCommandBaseData : SocketEntity<ulong>, IApplicationCommandInteractionData
public class SocketCommandBaseData<TOption> : SocketEntity<ulong>, IApplicationCommandInteractionData where TOption : IApplicationCommandInteractionDataOption
{
/// <inheritdoc/>
public string Name { get; private set; }

/// <summary>
/// The <see cref="SocketCommandBaseDataOption"/>'s received with this interaction.
/// The <typeparamref name="TOption"/> received with this interaction.
/// </summary>
public IReadOnlyCollection<SocketCommandBaseDataOption> Options { get; private set; }
internal Dictionary<ulong, SocketGuildUser> guildMembers { get; private set; }
= new Dictionary<ulong, SocketGuildUser>();
internal Dictionary<ulong, SocketGlobalUser> users { get; private set; }
= new Dictionary<ulong, SocketGlobalUser>();
internal Dictionary<ulong, SocketChannel> channels { get; private set; }
= new Dictionary<ulong, SocketChannel>();
internal Dictionary<ulong, SocketRole> roles { get; private set; }
= new Dictionary<ulong, SocketRole>();

private ulong? guildId;
public virtual IReadOnlyCollection<TOption> Options { get; internal set; }

internal SocketMessage Message { get; private set; }
internal readonly SocketResolvableData<Model> ResolvableData;

private ApplicationCommandType Type { get; set; }

internal SocketCommandBaseData(DiscordSocketClient client, Model model, ulong? guildId)
: base(client, model.Id)
{
this.guildId = guildId;

this.Type = (ApplicationCommandType)model.Type;
this.Type = model.Type;

if (model.Resolved.IsSpecified)
{
var guild = this.guildId.HasValue ? Discord.GetGuild(this.guildId.Value) : null;

var resolved = model.Resolved.Value;

if (resolved.Users.IsSpecified)
{
foreach (var user in resolved.Users.Value)
{
var socketUser = Discord.GetOrCreateUser(this.Discord.State, user.Value);

this.users.Add(ulong.Parse(user.Key), socketUser);
}
}

if (resolved.Channels.IsSpecified)
{
foreach (var channel in resolved.Channels.Value)
{
SocketChannel socketChannel = guild != null
? guild.GetChannel(channel.Value.Id)
: Discord.GetChannel(channel.Value.Id);

if (socketChannel == null)
{
var channelModel = guild != null
? Discord.Rest.ApiClient.GetChannelAsync(guild.Id, channel.Value.Id).ConfigureAwait(false).GetAwaiter().GetResult()
: Discord.Rest.ApiClient.GetChannelAsync(channel.Value.Id).ConfigureAwait(false).GetAwaiter().GetResult();

socketChannel = guild != null
? SocketGuildChannel.Create(guild, Discord.State, channelModel)
: (SocketChannel)SocketChannel.CreatePrivate(Discord, Discord.State, channelModel);
}

Discord.State.AddChannel(socketChannel);
this.channels.Add(ulong.Parse(channel.Key), socketChannel);
}
}

if (resolved.Members.IsSpecified)
{
foreach (var member in resolved.Members.Value)
{
member.Value.User = resolved.Users.Value[member.Key];
var user = guild.AddOrUpdateUser(member.Value);
this.guildMembers.Add(ulong.Parse(member.Key), user);
}
}

if (resolved.Roles.IsSpecified)
{
foreach (var role in resolved.Roles.Value)
{
var socketRole = guild.AddOrUpdateRole(role.Value);
this.roles.Add(ulong.Parse(role.Key), socketRole);
}
}

if (resolved.Messages.IsSpecified)
{
foreach (var msg in resolved.Messages.Value)
{
var channel = client.GetChannel(msg.Value.ChannelId) as ISocketMessageChannel;

SocketUser author;
if (guild != null)
{
if (msg.Value.WebhookId.IsSpecified)
author = SocketWebhookUser.Create(guild, client.State, msg.Value.Author.Value, msg.Value.WebhookId.Value);
else
author = guild.GetUser(msg.Value.Author.Value.Id);
}
else
author = (channel as SocketChannel).GetUser(msg.Value.Author.Value.Id);

if (channel == null)
{
if (!msg.Value.GuildId.IsSpecified) // assume it is a DM
{
channel = client.CreateDMChannel(msg.Value.ChannelId, msg.Value.Author.Value, client.State);
}
}

this.Message = SocketMessage.Create(client, client.State, author, channel, msg.Value);
}
}
ResolvableData = new SocketResolvableData<Model>(client, guildId, model);
}
}

@@ -135,15 +40,21 @@ namespace Discord.WebSocket
return entity;
}

internal void Update(Model model)
internal virtual void Update(Model model)
{
this.Name = model.Name;

this.Options = model.Options.IsSpecified
? model.Options.Value.Select(x => new SocketCommandBaseDataOption(this, x)).ToImmutableArray()
: null;
}

IReadOnlyCollection<IApplicationCommandInteractionDataOption> IApplicationCommandInteractionData.Options => Options;
IReadOnlyCollection<IApplicationCommandInteractionDataOption> IApplicationCommandInteractionData.Options
=> (IReadOnlyCollection<IApplicationCommandInteractionDataOption>)Options;
}

/// <summary>
/// Represents the base data tied with the <see cref="SocketCommandBase"/> interaction.
/// </summary>
public class SocketCommandBaseData : SocketCommandBaseData<IApplicationCommandInteractionDataOption>
{
internal SocketCommandBaseData(DiscordSocketClient client, Model model, ulong? guildId)
: base(client, model, guildId) { }
}
}

+ 0
- 134
src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBaseDataOption.cs View File

@@ -1,134 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Model = Discord.API.ApplicationCommandInteractionDataOption;

namespace Discord.WebSocket
{
/// <summary>
/// Represents the base Websocket-based <see cref="IApplicationCommandInteractionDataOption"/> recieved by the gateway
/// </summary>
public class SocketCommandBaseDataOption : IApplicationCommandInteractionDataOption
{
/// <inheritdoc/>
public string Name { get; private set; }

/// <inheritdoc/>
public object Value { get; private set; }

/// <inheritdoc/>
public ApplicationCommandOptionType Type { get; private set; }

/// <summary>
/// The sub command options received for this sub command group.
/// </summary>
public IReadOnlyCollection<IApplicationCommandInteractionDataOption> Options { get; private set; }

internal SocketCommandBaseDataOption() { }
internal SocketCommandBaseDataOption(SocketCommandBaseData data, Model model)
{
this.Name = model.Name;
this.Type = model.Type;

if (model.Value.IsSpecified)
{
switch (Type)
{
case ApplicationCommandOptionType.User:
case ApplicationCommandOptionType.Role:
case ApplicationCommandOptionType.Channel:
case ApplicationCommandOptionType.Mentionable:
if (ulong.TryParse($"{model.Value.Value}", out var valueId))
{
switch (this.Type)
{
case ApplicationCommandOptionType.User:
{
var guildUser = data.guildMembers.FirstOrDefault(x => x.Key == valueId).Value;

if (guildUser != null)
this.Value = guildUser;
else
this.Value = data.users.FirstOrDefault(x => x.Key == valueId).Value;
}
break;
case ApplicationCommandOptionType.Channel:
this.Value = data.channels.FirstOrDefault(x => x.Key == valueId).Value;
break;
case ApplicationCommandOptionType.Role:
this.Value = data.roles.FirstOrDefault(x => x.Key == valueId).Value;
break;
case ApplicationCommandOptionType.Mentionable:
{
if (data.guildMembers.Any(x => x.Key == valueId) || data.users.Any(x => x.Key == valueId))
{
var guildUser = data.guildMembers.FirstOrDefault(x => x.Key == valueId).Value;

if (guildUser != null)
this.Value = guildUser;
else
this.Value = data.users.FirstOrDefault(x => x.Key == valueId).Value;
}
else if (data.roles.Any(x => x.Key == valueId))
{
this.Value = data.roles.FirstOrDefault(x => x.Key == valueId).Value;
}
}
break;
default:
this.Value = model.Value.Value;
break;
}
}
break;
case ApplicationCommandOptionType.String:
this.Value = model.Value.ToString();
break;
case ApplicationCommandOptionType.Integer:
{
if (model.Value.Value is int val)
this.Value = val;
else if (int.TryParse(model.Value.Value.ToString(), out int res))
this.Value = res;
}
break;
case ApplicationCommandOptionType.Boolean:
{
if (model.Value.Value is bool val)
this.Value = val;
else if (bool.TryParse(model.Value.Value.ToString(), out bool res))
this.Value = res;
}
break;
case ApplicationCommandOptionType.Number:
{
if (model.Value.Value is int val)
this.Value = val;
else if (double.TryParse(model.Value.Value.ToString(), out double res))
this.Value = res;
}
break;
}

}

this.Options = model.Options.IsSpecified
? model.Options.Value.Select(x => new SocketCommandBaseDataOption(data, x)).ToImmutableArray()
: null;
}

// Converters
public static explicit operator bool(SocketCommandBaseDataOption option)
=> (bool)option.Value;
public static explicit operator int(SocketCommandBaseDataOption option)
=> (int)option.Value;
public static explicit operator string(SocketCommandBaseDataOption option)
=> option.Value.ToString();

IReadOnlyCollection<IApplicationCommandInteractionDataOption> IApplicationCommandInteractionDataOption.Options => this.Options;
}
}

+ 113
- 0
src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketResolvableData.cs View File

@@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Discord.WebSocket
{
internal class SocketResolvableData<T> where T : API.IResolvable
{
internal readonly Dictionary<ulong, SocketGuildUser> GuildMembers
= new Dictionary<ulong, SocketGuildUser>();
internal readonly Dictionary<ulong, SocketGlobalUser> Users
= new Dictionary<ulong, SocketGlobalUser>();
internal readonly Dictionary<ulong, SocketChannel> Channels
= new Dictionary<ulong, SocketChannel>();
internal readonly Dictionary<ulong, SocketRole> Roles
= new Dictionary<ulong, SocketRole>();

internal readonly Dictionary<ulong, SocketMessage> Messages
= new Dictionary<ulong, SocketMessage>();

internal SocketResolvableData(DiscordSocketClient discord, ulong? guildId, T model)
{
var guild = guildId.HasValue ? discord.GetGuild(guildId.Value) : null;

var resolved = model.Resolved.Value;

if (resolved.Users.IsSpecified)
{
foreach (var user in resolved.Users.Value)
{
var socketUser = discord.GetOrCreateUser(discord.State, user.Value);

this.Users.Add(ulong.Parse(user.Key), socketUser);
}
}

if (resolved.Channels.IsSpecified)
{
foreach (var channel in resolved.Channels.Value)
{
SocketChannel socketChannel = guild != null
? guild.GetChannel(channel.Value.Id)
: discord.GetChannel(channel.Value.Id);

if (socketChannel == null)
{
var channelModel = guild != null
? discord.Rest.ApiClient.GetChannelAsync(guild.Id, channel.Value.Id).ConfigureAwait(false).GetAwaiter().GetResult()
: discord.Rest.ApiClient.GetChannelAsync(channel.Value.Id).ConfigureAwait(false).GetAwaiter().GetResult();

socketChannel = guild != null
? SocketGuildChannel.Create(guild, discord.State, channelModel)
: (SocketChannel)SocketChannel.CreatePrivate(discord, discord.State, channelModel);
}

discord.State.AddChannel(socketChannel);
this.Channels.Add(ulong.Parse(channel.Key), socketChannel);
}
}

if (resolved.Members.IsSpecified)
{
foreach (var member in resolved.Members.Value)
{
member.Value.User = resolved.Users.Value[member.Key];
var user = guild.AddOrUpdateUser(member.Value);
this.GuildMembers.Add(ulong.Parse(member.Key), user);
}
}

if (resolved.Roles.IsSpecified)
{
foreach (var role in resolved.Roles.Value)
{
var socketRole = guild.AddOrUpdateRole(role.Value);
this.Roles.Add(ulong.Parse(role.Key), socketRole);
}
}

if (resolved.Messages.IsSpecified)
{
foreach (var msg in resolved.Messages.Value)
{
var channel = discord.GetChannel(msg.Value.ChannelId) as ISocketMessageChannel;

SocketUser author;
if (guild != null)
{
if (msg.Value.WebhookId.IsSpecified)
author = SocketWebhookUser.Create(guild, discord.State, msg.Value.Author.Value, msg.Value.WebhookId.Value);
else
author = guild.GetUser(msg.Value.Author.Value.Id);
}
else
author = (channel as SocketChannel).GetUser(msg.Value.Author.Value.Id);

if (channel == null)
{
if (!msg.Value.GuildId.IsSpecified) // assume it is a DM
{
channel = discord.CreateDMChannel(msg.Value.ChannelId, msg.Value.Author.Value, discord.State);
}
}

var message = SocketMessage.Create(discord, discord.State, author, channel, msg.Value);
this.Messages.Add(message.Id, message);
}
}
}
}
}

Loading…
Cancel
Save