@@ -165,5 +165,17 @@ namespace Discord | |||
/// clock. Your system will still need a stable clock. | |||
/// </remarks> | |||
public bool UseSystemClock { get; set; } = true; | |||
/// <summary> | |||
/// Gets or sets whether or not the internal experation check uses the system date | |||
/// + snowflake date to check if an interaction can be responded to. | |||
/// </summary> | |||
/// <remarks> | |||
/// If set to <see langword="false"/> then the CreatedAt property in an interaction | |||
/// will be set to when it was received instead of the snowflakes date. | |||
/// <br/> | |||
/// <b>This will still require a stable clock on your system.</b> | |||
/// </remarks> | |||
public bool UseInteractionSnowflakeDate { get; set; } = true; | |||
} | |||
} |
@@ -35,6 +35,7 @@ namespace Discord.Rest | |||
public ISelfUser CurrentUser { get; protected set; } | |||
/// <inheritdoc /> | |||
public TokenType TokenType => ApiClient.AuthTokenType; | |||
internal bool UseInteractionSnowflakeDate { get; private set; } | |||
/// <summary> Creates a new REST-only Discord client. </summary> | |||
internal BaseDiscordClient(DiscordRestConfig config, API.DiscordRestApiClient client) | |||
@@ -47,6 +48,8 @@ namespace Discord.Rest | |||
_restLogger = LogManager.CreateLogger("Rest"); | |||
_isFirstLogin = config.DisplayInitialLog; | |||
UseInteractionSnowflakeDate = config.UseInteractionSnowflakeDate; | |||
ApiClient.RequestQueue.RateLimitTriggered += async (id, info, endpoint) => | |||
{ | |||
if (info == null) | |||
@@ -33,8 +33,7 @@ namespace Discord.Rest | |||
public RestUser User { get; private set; } | |||
/// <inheritdoc/> | |||
public DateTimeOffset CreatedAt | |||
=> SnowflakeUtils.FromSnowflake(Id); | |||
public DateTimeOffset CreatedAt { get; private set; } | |||
internal abstract bool _hasResponded { get; set; } | |||
@@ -57,7 +56,9 @@ namespace Discord.Rest | |||
internal RestInteraction(BaseDiscordClient discord, ulong id) | |||
: base(discord, id) | |||
{ | |||
CreatedAt = discord.UseInteractionSnowflakeDate | |||
? SnowflakeUtils.FromSnowflake(Id) | |||
: DateTime.UtcNow; | |||
} | |||
internal static async Task<RestInteraction> CreateAsync(DiscordRestClient client, Model model) | |||
@@ -26,7 +26,7 @@ namespace Discord.WebSocket | |||
public SocketUserMessage Message { get; private set; } | |||
private object _lock = new object(); | |||
internal override bool _hasResponded { get; set; } = false; | |||
public override bool HasResponded { get; internal set; } = false; | |||
internal SocketMessageComponent(DiscordSocketClient client, Model model, ISocketMessageChannel channel) | |||
: base(client, model.Id, channel) | |||
@@ -130,7 +130,7 @@ namespace Discord.WebSocket | |||
lock (_lock) | |||
{ | |||
if (_hasResponded) | |||
if (HasResponded) | |||
{ | |||
throw new InvalidOperationException("Cannot respond, update, or defer twice to the same interaction"); | |||
} | |||
@@ -140,7 +140,7 @@ namespace Discord.WebSocket | |||
lock (_lock) | |||
{ | |||
_hasResponded = true; | |||
HasResponded = true; | |||
} | |||
} | |||
@@ -225,7 +225,7 @@ namespace Discord.WebSocket | |||
lock (_lock) | |||
{ | |||
if (_hasResponded) | |||
if (HasResponded) | |||
{ | |||
throw new InvalidOperationException("Cannot respond, update, or defer twice to the same interaction"); | |||
} | |||
@@ -235,7 +235,7 @@ namespace Discord.WebSocket | |||
lock (_lock) | |||
{ | |||
_hasResponded = true; | |||
HasResponded = true; | |||
} | |||
} | |||
@@ -380,7 +380,7 @@ namespace Discord.WebSocket | |||
lock (_lock) | |||
{ | |||
if (_hasResponded) | |||
if (HasResponded) | |||
{ | |||
throw new InvalidOperationException("Cannot respond or defer twice to the same interaction"); | |||
} | |||
@@ -390,7 +390,7 @@ namespace Discord.WebSocket | |||
lock (_lock) | |||
{ | |||
_hasResponded = true; | |||
HasResponded = true; | |||
} | |||
} | |||
@@ -408,7 +408,7 @@ namespace Discord.WebSocket | |||
lock (_lock) | |||
{ | |||
if (_hasResponded) | |||
if (HasResponded) | |||
{ | |||
throw new InvalidOperationException("Cannot respond or defer twice to the same interaction"); | |||
} | |||
@@ -418,7 +418,7 @@ namespace Discord.WebSocket | |||
lock (_lock) | |||
{ | |||
_hasResponded = true; | |||
HasResponded = true; | |||
} | |||
} | |||
@@ -18,7 +18,7 @@ namespace Discord.WebSocket | |||
/// </summary> | |||
public new SocketAutocompleteInteractionData Data { get; } | |||
internal override bool _hasResponded { get; set; } | |||
public override bool HasResponded { get; internal set; } | |||
private object _lock = new object(); | |||
internal SocketAutocompleteInteraction(DiscordSocketClient client, Model model, ISocketMessageChannel channel) | |||
@@ -60,7 +60,7 @@ namespace Discord.WebSocket | |||
lock (_lock) | |||
{ | |||
if (_hasResponded) | |||
if (HasResponded) | |||
{ | |||
throw new InvalidOperationException("Cannot respond twice to the same interaction"); | |||
} | |||
@@ -69,7 +69,7 @@ namespace Discord.WebSocket | |||
await InteractionHelper.SendAutocompleteResultAsync(Discord, result, Id, Token, options).ConfigureAwait(false); | |||
lock (_lock) | |||
{ | |||
_hasResponded = true; | |||
HasResponded = true; | |||
} | |||
} | |||
@@ -31,7 +31,7 @@ namespace Discord.WebSocket | |||
/// </summary> | |||
internal new SocketCommandBaseData Data { get; } | |||
internal override bool _hasResponded { get; set; } | |||
public override bool HasResponded { get; internal set; } | |||
private object _lock = new object(); | |||
@@ -124,7 +124,7 @@ namespace Discord.WebSocket | |||
lock (_lock) | |||
{ | |||
if (_hasResponded) | |||
if (HasResponded) | |||
{ | |||
throw new InvalidOperationException("Cannot respond twice to the same interaction"); | |||
} | |||
@@ -134,7 +134,7 @@ namespace Discord.WebSocket | |||
lock (_lock) | |||
{ | |||
_hasResponded = true; | |||
HasResponded = true; | |||
} | |||
} | |||
@@ -283,7 +283,7 @@ namespace Discord.WebSocket | |||
lock (_lock) | |||
{ | |||
if (_hasResponded) | |||
if (HasResponded) | |||
{ | |||
throw new InvalidOperationException("Cannot respond or defer twice to the same interaction"); | |||
} | |||
@@ -293,7 +293,7 @@ namespace Discord.WebSocket | |||
lock (_lock) | |||
{ | |||
_hasResponded = true; | |||
HasResponded = true; | |||
} | |||
} | |||
} | |||
@@ -44,10 +44,16 @@ namespace Discord.WebSocket | |||
public int Version { get; private set; } | |||
/// <inheritdoc/> | |||
public DateTimeOffset CreatedAt | |||
=> SnowflakeUtils.FromSnowflake(Id); | |||
public DateTimeOffset CreatedAt { get; private set; } | |||
internal abstract bool _hasResponded { get; set; } | |||
/// <summary> | |||
/// Gets whether or not this interaction has been responded to. | |||
/// </summary> | |||
/// <remarks> | |||
/// This property is locally set -- if you're running multiple bots | |||
/// off the same token then this property won't be in sync with them. | |||
/// </remarks> | |||
public abstract bool HasResponded { get; internal set; } | |||
/// <summary> | |||
/// <see langword="true"/> if the token is valid for replying to, otherwise <see langword="false"/>. | |||
@@ -59,6 +65,10 @@ namespace Discord.WebSocket | |||
: base(client, id) | |||
{ | |||
Channel = channel; | |||
CreatedAt = client.UseInteractionSnowflakeDate | |||
? SnowflakeUtils.FromSnowflake(Id) | |||
: DateTime.UtcNow; | |||
} | |||
internal static SocketInteraction Create(DiscordSocketClient client, Model model, ISocketMessageChannel channel) | |||