diff --git a/src/Discord.Net.Core/Entities/Channels/IThreadChannel.cs b/src/Discord.Net.Core/Entities/Channels/IThreadChannel.cs index 50e46efa6..f03edbbf9 100644 --- a/src/Discord.Net.Core/Entities/Channels/IThreadChannel.cs +++ b/src/Discord.Net.Core/Entities/Channels/IThreadChannel.cs @@ -48,6 +48,23 @@ namespace Discord /// int MessageCount { get; } + /// + /// Gets whether non-moderators can add other non-moderators to a thread. + /// + /// + /// This property is only available on private threads. + /// + bool? IsInvitable { get; } + + /// + /// Gets when the thread was created. + /// + /// + /// This property is only populated for threads created after 2022-01-09, hence the default date of this + /// property will be that date. + /// + new DateTimeOffset CreatedAt { get; } + /// /// Joins the current thread. /// diff --git a/src/Discord.Net.Rest/API/Common/ThreadMetadata.cs b/src/Discord.Net.Rest/API/Common/ThreadMetadata.cs index 39e9bd13e..15854fab4 100644 --- a/src/Discord.Net.Rest/API/Common/ThreadMetadata.cs +++ b/src/Discord.Net.Rest/API/Common/ThreadMetadata.cs @@ -16,5 +16,11 @@ namespace Discord.API [JsonProperty("locked")] public Optional Locked { get; set; } + + [JsonProperty("invitable")] + public Optional Invitable { get; set; } + + [JsonProperty("create_timestamp")] + public Optional CreatedAt { get; set; } } } diff --git a/src/Discord.Net.Rest/Entities/Channels/RestChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestChannel.cs index 83c6d8bfb..c730596c7 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestChannel.cs @@ -13,7 +13,7 @@ namespace Discord.Rest { #region RestChannel /// - public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); + public virtual DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); internal RestChannel(BaseDiscordClient discord, ulong id) : base(discord, id) diff --git a/src/Discord.Net.Rest/Entities/Channels/RestThreadChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestThreadChannel.cs index 63071b9a5..c763a6660 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestThreadChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestThreadChannel.cs @@ -34,17 +34,26 @@ namespace Discord.Rest /// public int MessageCount { get; private set; } + /// + public bool? IsInvitable { get; private set; } + + /// + public override DateTimeOffset CreatedAt { get; } + /// /// Gets the parent text channel id. /// public ulong ParentChannelId { get; private set; } - internal RestThreadChannel(BaseDiscordClient discord, IGuild guild, ulong id) - : base(discord, guild, id) { } + internal RestThreadChannel(BaseDiscordClient discord, IGuild guild, ulong id, DateTimeOffset? createdAt) + : base(discord, guild, id) + { + CreatedAt = createdAt ?? new DateTimeOffset(2022, 1, 9, 0, 0, 0, TimeSpan.Zero); + } internal new static RestThreadChannel Create(BaseDiscordClient discord, IGuild guild, Model model) { - var entity = new RestThreadChannel(discord, guild, model.Id); + var entity = new RestThreadChannel(discord, guild, model.Id, model.ThreadMetadata.GetValueOrDefault()?.CreatedAt.GetValueOrDefault()); entity.Update(model); return entity; } @@ -57,6 +66,7 @@ namespace Discord.Rest if (model.ThreadMetadata.IsSpecified) { + IsInvitable = model.ThreadMetadata.Value.Invitable.ToNullable(); IsArchived = model.ThreadMetadata.Value.Archived; AutoArchiveDuration = model.ThreadMetadata.Value.AutoArchiveDuration; ArchiveTimestamp = model.ThreadMetadata.Value.ArchiveTimestamp; diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketChannel.cs index 758ee9271..c30b3d254 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketChannel.cs @@ -17,7 +17,7 @@ namespace Discord.WebSocket /// /// Gets when the channel is created. /// - public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); + public virtual DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); /// /// Gets a collection of users from the WebSocket cache. /// diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketThreadChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketThreadChannel.cs index 7fcafc14a..c26a23afd 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketThreadChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketThreadChannel.cs @@ -44,7 +44,7 @@ namespace Discord.WebSocket /// /// Gets the parent channel this thread resides in. /// - public SocketTextChannel ParentChannel { get; private set; } + public SocketGuildChannel ParentChannel { get; private set; } /// public int MessageCount { get; private set; } @@ -64,6 +64,12 @@ namespace Discord.WebSocket /// public bool IsLocked { get; private set; } + /// + public bool? IsInvitable { get; private set; } + + /// + public override DateTimeOffset CreatedAt { get; } + /// /// Gets a collection of cached users within this thread. /// @@ -78,17 +84,19 @@ namespace Discord.WebSocket private readonly object _downloadLock = new object(); - internal SocketThreadChannel(DiscordSocketClient discord, SocketGuild guild, ulong id, SocketTextChannel parent) + internal SocketThreadChannel(DiscordSocketClient discord, SocketGuild guild, ulong id, SocketGuildChannel parent, + DateTimeOffset? createdAt) : base(discord, id, guild) { ParentChannel = parent; _members = new ConcurrentDictionary(); + CreatedAt = createdAt ?? new DateTimeOffset(2022, 1, 9, 0, 0, 0, TimeSpan.Zero); } internal new static SocketThreadChannel Create(SocketGuild guild, ClientState state, Model model) { - var parent = (SocketTextChannel)guild.GetChannel(model.CategoryId.Value); - var entity = new SocketThreadChannel(guild.Discord, guild, model.Id, parent); + var parent = guild.GetChannel(model.CategoryId.Value); + var entity = new SocketThreadChannel(guild.Discord, guild, model.Id, parent, model.ThreadMetadata.GetValueOrDefault()?.CreatedAt.ToNullable()); entity.Update(state, model); return entity; } @@ -103,6 +111,7 @@ namespace Discord.WebSocket if (model.ThreadMetadata.IsSpecified) { + IsInvitable = model.ThreadMetadata.Value.Invitable.ToNullable(); IsArchived = model.ThreadMetadata.Value.Archived; ArchiveTimestamp = model.ThreadMetadata.Value.ArchiveTimestamp; AutoArchiveDuration = model.ThreadMetadata.Value.AutoArchiveDuration;