@@ -1982,11 +1982,48 @@ | |||||
of webhooks that is available in this channel. | of webhooks that is available in this channel. | ||||
</returns> | </returns> | ||||
</member> | </member> | ||||
<member name="M:Discord.ITextChannel.CreateThreadAsync(System.String,Discord.ThreadType,Discord.ThreadArchiveDuration,Discord.IMessage,Discord.RequestOptions)"> | |||||
<summary> | |||||
Creates a thread within this <see cref="T:Discord.ITextChannel"/>. | |||||
</summary> | |||||
<remarks> | |||||
When <paramref name="message"/> is <see langword="null"/> the thread type will be based off of the | |||||
channel its created in. When called on a <see cref="T:Discord.ITextChannel"/>, it creates a <see cref="F:Discord.ThreadType.PublicThread"/>. | |||||
When called on a <see cref="T:Discord.INewsChannel"/>, it creates a <see cref="F:Discord.ThreadType.NewsThread"/>. The id of the created | |||||
thread will be the same as the id of the message, and as such a message can only have a | |||||
single thread created from it. | |||||
</remarks> | |||||
<param name="name">The name of the thread.</param> | |||||
<param name="type"> | |||||
The type of the thread. | |||||
<para> | |||||
<b>Note: </b>This parameter is not used if the <paramref name="message"/> parameter is not specified. | |||||
</para> | |||||
</param> | |||||
<param name="autoArchiveDuration"> | |||||
The duration on which this thread archives after. | |||||
<para> | |||||
<b>Note: </b> Options <see cref="F:Discord.ThreadArchiveDuration.OneWeek"/> and <see cref="F:Discord.ThreadArchiveDuration.ThreeDays"/> | |||||
are only available for guilds that are boosted. You can check in the <see cref="P:Discord.IGuild.Features"/> to see if the | |||||
guild has the <b>THREE_DAY_THREAD_ARCHIVE</b> and <b>SEVEN_DAY_THREAD_ARCHIVE</b>. | |||||
</para> | |||||
</param> | |||||
<param name="message">The message which to start the thread from.</param> | |||||
<param name="options">The options to be used when sending the request.</param> | |||||
<returns> | |||||
A task that represents the asynchronous create operation. The task result contains a <see cref="T:Discord.IThreadChannel"/> | |||||
</returns> | |||||
</member> | |||||
<member name="T:Discord.IThreadChannel"> | <member name="T:Discord.IThreadChannel"> | ||||
<summary> | <summary> | ||||
Represents a thread channel inside of a guild. | Represents a thread channel inside of a guild. | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="P:Discord.IThreadChannel.Type"> | |||||
<summary> | |||||
Gets the type of the current thread channel. | |||||
</summary> | |||||
</member> | |||||
<member name="P:Discord.IThreadChannel.Joined"> | <member name="P:Discord.IThreadChannel.Joined"> | ||||
<summary> | <summary> | ||||
<see langword="true"/> if the current user has joined this thread, otherwise <see langword="false"/>. | <see langword="true"/> if the current user has joined this thread, otherwise <see langword="false"/>. | ||||
@@ -2022,17 +2059,43 @@ | |||||
An approximate count of messages in a thread, stops counting at 50. | An approximate count of messages in a thread, stops counting at 50. | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="M:Discord.IThreadChannel.JoinAsync"> | |||||
<member name="M:Discord.IThreadChannel.JoinAsync(Discord.RequestOptions)"> | |||||
<summary> | <summary> | ||||
Joins the current thread. | Joins the current thread. | ||||
</summary> | </summary> | ||||
<returns></returns> | |||||
<param name="options">The options to be used when sending the request.</param> | |||||
<returns> | |||||
A task that represents the asynchronous join operation. | |||||
</returns> | |||||
</member> | </member> | ||||
<member name="M:Discord.IThreadChannel.LeaveAsync"> | |||||
<member name="M:Discord.IThreadChannel.LeaveAsync(Discord.RequestOptions)"> | |||||
<summary> | <summary> | ||||
Leaves the current thread. | Leaves the current thread. | ||||
</summary> | </summary> | ||||
<returns></returns> | |||||
<param name="options">The options to be used when sending the request.</param> | |||||
<returns> | |||||
A task that represents the asynchronous leave operation. | |||||
</returns> | |||||
</member> | |||||
<member name="M:Discord.IThreadChannel.AddUserAsync(Discord.IGuildUser,Discord.RequestOptions)"> | |||||
<summary> | |||||
Adds a user to this thread. | |||||
</summary> | |||||
<param name="user">The <see cref="T:Discord.IGuildUser"/> to add.</param> | |||||
<param name="options">The options to be used when sending the request.</param> | |||||
<returns> | |||||
A task that represents the asynchronous operation of adding a member to a thread. | |||||
</returns> | |||||
</member> | |||||
<member name="M:Discord.IThreadChannel.RemoveUserAsync(Discord.IGuildUser,Discord.RequestOptions)"> | |||||
<summary> | |||||
Removes a user from this thread. | |||||
</summary> | |||||
<param name="user">The <see cref="T:Discord.IGuildUser"/> to remove from this thread.</param> | |||||
<param name="options">The options to be used when sending the request.</param> | |||||
<returns> | |||||
A task that represents the asynchronous operation of removing a user from this thread. | |||||
</returns> | |||||
</member> | </member> | ||||
<member name="T:Discord.IVoiceChannel"> | <member name="T:Discord.IVoiceChannel"> | ||||
<summary> | <summary> | ||||
@@ -2133,6 +2196,21 @@ | |||||
</remarks> | </remarks> | ||||
<exception cref="T:System.ArgumentOutOfRangeException">Thrown if the value does not fall within [0, 21600].</exception> | <exception cref="T:System.ArgumentOutOfRangeException">Thrown if the value does not fall within [0, 21600].</exception> | ||||
</member> | </member> | ||||
<member name="P:Discord.TextChannelProperties.Archived"> | |||||
<summary> | |||||
Gets or sets whether or not the thread is archived. | |||||
</summary> | |||||
</member> | |||||
<member name="P:Discord.TextChannelProperties.Locked"> | |||||
<summary> | |||||
Gets or sets whether or not the thread is locked. | |||||
</summary> | |||||
</member> | |||||
<member name="P:Discord.TextChannelProperties.AutoArchiveDuration"> | |||||
<summary> | |||||
Gets or sets the auto archive duration. | |||||
</summary> | |||||
</member> | |||||
<member name="T:Discord.ThreadArchiveDuration"> | <member name="T:Discord.ThreadArchiveDuration"> | ||||
<summary> | <summary> | ||||
Represents the thread auto archive duration. | Represents the thread auto archive duration. | ||||
@@ -2164,40 +2242,26 @@ | |||||
</remarks> | </remarks> | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="P:Discord.Entities.ThreadChannelProperties.Archived"> | |||||
<member name="T:Discord.ThreadType"> | |||||
<summary> | <summary> | ||||
Gets or sets whether or not the thread is archived. | |||||
Represents types of threads. | |||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="P:Discord.Entities.ThreadChannelProperties.Locked"> | |||||
<member name="F:Discord.ThreadType.NewsThread"> | |||||
<summary> | <summary> | ||||
Gets or sets whether or not the thread is locked. | |||||
Represents a temporary sub-channel within a GUILD_NEWS channel. | |||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="P:Discord.Entities.ThreadChannelProperties.Name"> | |||||
<member name="F:Discord.ThreadType.PublicThread"> | |||||
<summary> | <summary> | ||||
Gets or sets the name of the thread. | |||||
Represents a temporary sub-channel within a GUILD_TEXT channel. | |||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="P:Discord.Entities.ThreadChannelProperties.AutoArchiveDuration"> | |||||
<member name="F:Discord.ThreadType.PrivateThread"> | |||||
<summary> | <summary> | ||||
Gets or sets the auto archive duration. | |||||
Represents a temporary sub-channel within a GUILD_TEXT channel that is only viewable by those invited and those with the MANAGE_THREADS permission | |||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="P:Discord.Entities.ThreadChannelProperties.SlowModeInterval"> | |||||
<summary> | |||||
Gets or sets the slow-mode ratelimit in seconds for this channel. | |||||
</summary> | |||||
<remarks> | |||||
Setting this value to anything above zero will require each user to wait X seconds before | |||||
sending another message; setting this value to <c>0</c> will disable slow-mode for this channel. | |||||
<note> | |||||
Users with <see cref="F:Discord.ChannelPermission.ManageMessages"/> or | |||||
<see cref="F:Discord.ChannelPermission.ManageChannels"/> will be exempt from slow-mode. | |||||
</note> | |||||
</remarks> | |||||
<exception cref="T:System.ArgumentOutOfRangeException">Thrown if the value does not fall within [0, 21600].</exception> | |||||
</member> | |||||
<member name="T:Discord.VoiceChannelProperties"> | <member name="T:Discord.VoiceChannelProperties"> | ||||
<summary> | <summary> | ||||
Provides properties that are used to modify an <see cref="T:Discord.IVoiceChannel" /> with the specified changes. | Provides properties that are used to modify an <see cref="T:Discord.IVoiceChannel" /> with the specified changes. | ||||
@@ -4747,7 +4811,7 @@ | |||||
<exception cref="T:System.InvalidOperationException">A button must contain either a <see cref="P:Discord.ButtonBuilder.Url"/> or a <see cref="P:Discord.ButtonBuilder.CustomId"/>, but not both.</exception> | <exception cref="T:System.InvalidOperationException">A button must contain either a <see cref="P:Discord.ButtonBuilder.Url"/> or a <see cref="P:Discord.ButtonBuilder.CustomId"/>, but not both.</exception> | ||||
<exception cref="T:System.InvalidOperationException">A button must have an <see cref="P:Discord.ButtonBuilder.Emote"/> or a <see cref="P:Discord.ButtonBuilder.Label"/>.</exception> | <exception cref="T:System.InvalidOperationException">A button must have an <see cref="P:Discord.ButtonBuilder.Emote"/> or a <see cref="P:Discord.ButtonBuilder.Label"/>.</exception> | ||||
<exception cref="T:System.InvalidOperationException">A link button must contain a URL.</exception> | <exception cref="T:System.InvalidOperationException">A link button must contain a URL.</exception> | ||||
<exception cref="T:System.InvalidOperationException">A link must include a protocol (http or https).</exception> | |||||
<exception cref="T:System.InvalidOperationException">A URL must include a protocol (http or https).</exception> | |||||
<exception cref="T:System.InvalidOperationException">A non-link button must contain a custom id</exception> | <exception cref="T:System.InvalidOperationException">A non-link button must contain a custom id</exception> | ||||
</member> | </member> | ||||
<member name="T:Discord.SelectMenuBuilder"> | <member name="T:Discord.SelectMenuBuilder"> | ||||
@@ -6041,7 +6105,7 @@ | |||||
The built embed object. | The built embed object. | ||||
</returns> | </returns> | ||||
<exception cref="T:System.InvalidOperationException">Total embed length exceeds <see cref="F:Discord.EmbedBuilder.MaxEmbedLength"/>.</exception> | <exception cref="T:System.InvalidOperationException">Total embed length exceeds <see cref="F:Discord.EmbedBuilder.MaxEmbedLength"/>.</exception> | ||||
<exception cref="T:System.InvalidOperationException">Any Url must include protocols (i.e http:// or https://).</exception> | |||||
<exception cref="T:System.InvalidOperationException">Any Url must be well formatted include its protocols (i.e http:// or https://).</exception> | |||||
</member> | </member> | ||||
<member name="T:Discord.EmbedFieldBuilder"> | <member name="T:Discord.EmbedFieldBuilder"> | ||||
<summary> | <summary> | ||||
@@ -8024,6 +8088,16 @@ | |||||
Allows for viewing of audit logs. | Allows for viewing of audit logs. | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="F:Discord.GuildPermission.ViewChannel"> | |||||
<summary> | |||||
Allows guild members to view a channel, which includes reading messages in text channels. | |||||
</summary> | |||||
</member> | |||||
<member name="F:Discord.GuildPermission.SendMessages"> | |||||
<summary> | |||||
Allows for sending messages in a channel | |||||
</summary> | |||||
</member> | |||||
<member name="F:Discord.GuildPermission.SendTTSMessages"> | <member name="F:Discord.GuildPermission.SendTTSMessages"> | ||||
<summary> | <summary> | ||||
Allows for sending of text-to-speech messages. | Allows for sending of text-to-speech messages. | ||||
@@ -8094,6 +8168,11 @@ | |||||
Allows for using voice-activity-detection in a voice channel. | Allows for using voice-activity-detection in a voice channel. | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="F:Discord.GuildPermission.PrioritySpeaker"> | |||||
<summary> | |||||
Allows for using priority speaker in a voice channel. | |||||
</summary> | |||||
</member> | |||||
<member name="F:Discord.GuildPermission.Stream"> | <member name="F:Discord.GuildPermission.Stream"> | ||||
<summary> | <summary> | ||||
Allows video streaming in a voice channel. | Allows video streaming in a voice channel. | ||||
@@ -8127,15 +8206,49 @@ | |||||
authentication when used on a guild that has server-wide 2FA enabled. | authentication when used on a guild that has server-wide 2FA enabled. | ||||
</remarks> | </remarks> | ||||
</member> | </member> | ||||
<member name="F:Discord.GuildPermission.ManageEmojis"> | |||||
<member name="F:Discord.GuildPermission.ManageEmojisAndStickers"> | |||||
<summary> | <summary> | ||||
Allows management and editing of emojis. | |||||
Allows management and editing of emojis and stickers. | |||||
</summary> | |||||
<remarks> | |||||
This permission requires the owner account to use two-factor | |||||
authentication when used on a guild that has server-wide 2FA enabled. | |||||
</remarks> | |||||
</member> | |||||
<member name="F:Discord.GuildPermission.UseSlashCommands"> | |||||
<summary> | |||||
Allows members to use slash commands in text channels. | |||||
</summary> | |||||
</member> | |||||
<member name="F:Discord.GuildPermission.RequestToSpeak"> | |||||
<summary> | |||||
Allows for requesting to speak in stage channels. <i>(This permission is under active development and may be changed or removed.)</i>. | |||||
</summary> | |||||
</member> | |||||
<member name="F:Discord.GuildPermission.ManageThreads"> | |||||
<summary> | |||||
Allows for deleting and archiving threads, and viewing all private threads. | |||||
</summary> | </summary> | ||||
<remarks> | <remarks> | ||||
This permission requires the owner account to use two-factor | This permission requires the owner account to use two-factor | ||||
authentication when used on a guild that has server-wide 2FA enabled. | authentication when used on a guild that has server-wide 2FA enabled. | ||||
</remarks> | </remarks> | ||||
</member> | </member> | ||||
<member name="F:Discord.GuildPermission.UsePublicThreads"> | |||||
<summary> | |||||
Allows for creating and participating in threads. | |||||
</summary> | |||||
</member> | |||||
<member name="F:Discord.GuildPermission.UsePrivateThreads"> | |||||
<summary> | |||||
Allows for creating and participating in private threads. | |||||
</summary> | |||||
</member> | |||||
<member name="F:Discord.GuildPermission.UseExternalStickers"> | |||||
<summary> | |||||
Allows the usage of custom stickers from other servers. | |||||
</summary> | |||||
</member> | |||||
<member name="F:Discord.GuildPermissions.None"> | <member name="F:Discord.GuildPermissions.None"> | ||||
<summary> Gets a blank <see cref="T:Discord.GuildPermissions"/> that grants no permissions. </summary> | <summary> Gets a blank <see cref="T:Discord.GuildPermissions"/> that grants no permissions. </summary> | ||||
</member> | </member> | ||||
@@ -8238,7 +8351,7 @@ | |||||
<member name="P:Discord.GuildPermissions.ManageWebhooks"> | <member name="P:Discord.GuildPermissions.ManageWebhooks"> | ||||
<summary> If <c>true</c>, a user may edit the webhooks for this guild. </summary> | <summary> If <c>true</c>, a user may edit the webhooks for this guild. </summary> | ||||
</member> | </member> | ||||
<member name="P:Discord.GuildPermissions.ManageEmojis"> | |||||
<member name="P:Discord.GuildPermissions.ManageEmojisAndStickers"> | |||||
<summary> If <c>true</c>, a user may edit the emojis for this guild. </summary> | <summary> If <c>true</c>, a user may edit the emojis for this guild. </summary> | ||||
</member> | </member> | ||||
<member name="M:Discord.GuildPermissions.#ctor(System.UInt64)"> | <member name="M:Discord.GuildPermissions.#ctor(System.UInt64)"> | ||||
@@ -114,5 +114,38 @@ namespace Discord | |||||
/// of webhooks that is available in this channel. | /// of webhooks that is available in this channel. | ||||
/// </returns> | /// </returns> | ||||
Task<IReadOnlyCollection<IWebhook>> GetWebhooksAsync(RequestOptions options = null); | Task<IReadOnlyCollection<IWebhook>> GetWebhooksAsync(RequestOptions options = null); | ||||
/// <summary> | |||||
/// Creates a thread within this <see cref="ITextChannel"/>. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// When <paramref name="message"/> is <see langword="null"/> the thread type will be based off of the | |||||
/// channel its created in. When called on a <see cref="ITextChannel"/>, it creates a <see cref="ThreadType.PublicThread"/>. | |||||
/// When called on a <see cref="INewsChannel"/>, it creates a <see cref="ThreadType.NewsThread"/>. The id of the created | |||||
/// thread will be the same as the id of the message, and as such a message can only have a | |||||
/// single thread created from it. | |||||
/// </remarks> | |||||
/// <param name="name">The name of the thread.</param> | |||||
/// <param name="type"> | |||||
/// The type of the thread. | |||||
/// <para> | |||||
/// <b>Note: </b>This parameter is not used if the <paramref name="message"/> parameter is not specified. | |||||
/// </para> | |||||
/// </param> | |||||
/// <param name="autoArchiveDuration"> | |||||
/// The duration on which this thread archives after. | |||||
/// <para> | |||||
/// <b>Note: </b> Options <see cref="ThreadArchiveDuration.OneWeek"/> and <see cref="ThreadArchiveDuration.ThreeDays"/> | |||||
/// are only available for guilds that are boosted. You can check in the <see cref="IGuild.Features"/> to see if the | |||||
/// guild has the <b>THREE_DAY_THREAD_ARCHIVE</b> and <b>SEVEN_DAY_THREAD_ARCHIVE</b>. | |||||
/// </para> | |||||
/// </param> | |||||
/// <param name="message">The message which to start the thread from.</param> | |||||
/// <param name="options">The options to be used when sending the request.</param> | |||||
/// <returns> | |||||
/// A task that represents the asynchronous create operation. The task result contains a <see cref="IThreadChannel"/> | |||||
/// </returns> | |||||
Task<IThreadChannel> CreateThreadAsync(string name, ThreadType type = ThreadType.PublicThread, ThreadArchiveDuration autoArchiveDuration = ThreadArchiveDuration.OneDay, | |||||
IMessage message = null, RequestOptions options = null); | |||||
} | } | ||||
} | } |
@@ -11,6 +11,11 @@ namespace Discord | |||||
/// </summary> | /// </summary> | ||||
public interface IThreadChannel : ITextChannel, IGuildChannel | public interface IThreadChannel : ITextChannel, IGuildChannel | ||||
{ | { | ||||
/// <summary> | |||||
/// Gets the type of the current thread channel. | |||||
/// </summary> | |||||
ThreadType Type { get; } | |||||
/// <summary> | /// <summary> | ||||
/// <see langword="true"/> if the current user has joined this thread, otherwise <see langword="false"/>. | /// <see langword="true"/> if the current user has joined this thread, otherwise <see langword="false"/>. | ||||
/// </summary> | /// </summary> | ||||
@@ -49,13 +54,39 @@ namespace Discord | |||||
/// <summary> | /// <summary> | ||||
/// Joins the current thread. | /// Joins the current thread. | ||||
/// </summary> | /// </summary> | ||||
/// <returns></returns> | |||||
Task JoinAsync(); | |||||
/// <param name="options">The options to be used when sending the request.</param> | |||||
/// <returns> | |||||
/// A task that represents the asynchronous join operation. | |||||
/// </returns> | |||||
Task JoinAsync(RequestOptions options = null); | |||||
/// <summary> | /// <summary> | ||||
/// Leaves the current thread. | /// Leaves the current thread. | ||||
/// </summary> | /// </summary> | ||||
/// <returns></returns> | |||||
Task LeaveAsync(); | |||||
/// <param name="options">The options to be used when sending the request.</param> | |||||
/// <returns> | |||||
/// A task that represents the asynchronous leave operation. | |||||
/// </returns> | |||||
Task LeaveAsync(RequestOptions options = null); | |||||
/// <summary> | |||||
/// Adds a user to this thread. | |||||
/// </summary> | |||||
/// <param name="user">The <see cref="IGuildUser"/> to add.</param> | |||||
/// <param name="options">The options to be used when sending the request.</param> | |||||
/// <returns> | |||||
/// A task that represents the asynchronous operation of adding a member to a thread. | |||||
/// </returns> | |||||
Task AddUserAsync(IGuildUser user, RequestOptions options = null); | |||||
/// <summary> | |||||
/// Removes a user from this thread. | |||||
/// </summary> | |||||
/// <param name="user">The <see cref="IGuildUser"/> to remove from this thread.</param> | |||||
/// <param name="options">The options to be used when sending the request.</param> | |||||
/// <returns> | |||||
/// A task that represents the asynchronous operation of removing a user from this thread. | |||||
/// </returns> | |||||
Task RemoveUserAsync(IGuildUser user, RequestOptions options = null); | |||||
} | } | ||||
} | } |
@@ -38,5 +38,21 @@ namespace Discord | |||||
/// </remarks> | /// </remarks> | ||||
/// <exception cref="ArgumentOutOfRangeException">Thrown if the value does not fall within [0, 21600].</exception> | /// <exception cref="ArgumentOutOfRangeException">Thrown if the value does not fall within [0, 21600].</exception> | ||||
public Optional<int> SlowModeInterval { get; set; } | public Optional<int> SlowModeInterval { get; set; } | ||||
/// <summary> | |||||
/// Gets or sets whether or not the thread is archived. | |||||
/// </summary> | |||||
public Optional<bool> Archived { get; set; } | |||||
/// <summary> | |||||
/// Gets or sets whether or not the thread is locked. | |||||
/// </summary> | |||||
public Optional<bool> Locked { get; set; } | |||||
/// <summary> | |||||
/// Gets or sets the auto archive duration. | |||||
/// </summary> | |||||
public Optional<ThreadArchiveDuration> AutoArchiveDuration { get; set; } | |||||
} | } | ||||
} | } |
@@ -1,45 +0,0 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace Discord.Entities | |||||
{ | |||||
public class ThreadChannelProperties | |||||
{ | |||||
/// <summary> | |||||
/// Gets or sets whether or not the thread is archived. | |||||
/// </summary> | |||||
public Optional<bool> Archived { get; set; } | |||||
/// <summary> | |||||
/// Gets or sets whether or not the thread is locked. | |||||
/// </summary> | |||||
public Optional<bool> Locked { get; set; } | |||||
/// <summary> | |||||
/// Gets or sets the name of the thread. | |||||
/// </summary> | |||||
public Optional<string> Name { get; set; } | |||||
/// <summary> | |||||
/// Gets or sets the auto archive duration. | |||||
/// </summary> | |||||
public Optional<ThreadArchiveDuration> AutoArchiveDuration { get; set; } | |||||
/// <summary> | |||||
/// Gets or sets the slow-mode ratelimit in seconds for this channel. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// Setting this value to anything above zero will require each user to wait X seconds before | |||||
/// sending another message; setting this value to <c>0</c> will disable slow-mode for this channel. | |||||
/// <note> | |||||
/// Users with <see cref="Discord.ChannelPermission.ManageMessages"/> or | |||||
/// <see cref="ChannelPermission.ManageChannels"/> will be exempt from slow-mode. | |||||
/// </note> | |||||
/// </remarks> | |||||
/// <exception cref="ArgumentOutOfRangeException">Thrown if the value does not fall within [0, 21600].</exception> | |||||
public Optional<int> SlowModeInterval { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,29 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace Discord | |||||
{ | |||||
/// <summary> | |||||
/// Represents types of threads. | |||||
/// </summary> | |||||
public enum ThreadType | |||||
{ | |||||
/// <summary> | |||||
/// Represents a temporary sub-channel within a GUILD_NEWS channel. | |||||
/// </summary> | |||||
NewsThread = 10, | |||||
/// <summary> | |||||
/// Represents a temporary sub-channel within a GUILD_TEXT channel. | |||||
/// </summary> | |||||
PublicThread = 11, | |||||
/// <summary> | |||||
/// Represents a temporary sub-channel within a GUILD_TEXT channel that is only viewable by those invited and those with the MANAGE_THREADS permission | |||||
/// </summary> | |||||
PrivateThread = 12, | |||||
} | |||||
} |
@@ -10,7 +10,7 @@ namespace Discord | |||||
/// <summary> | /// <summary> | ||||
/// Allows creation of instant invites. | /// Allows creation of instant invites. | ||||
/// </summary> | /// </summary> | ||||
CreateInstantInvite = 0x00_00_00_01, | |||||
CreateInstantInvite = 0x00_00_00_01, | |||||
/// <summary> | /// <summary> | ||||
/// Allows kicking members. | /// Allows kicking members. | ||||
/// </summary> | /// </summary> | ||||
@@ -18,7 +18,7 @@ namespace Discord | |||||
/// This permission requires the owner account to use two-factor | /// This permission requires the owner account to use two-factor | ||||
/// authentication when used on a guild that has server-wide 2FA enabled. | /// authentication when used on a guild that has server-wide 2FA enabled. | ||||
/// </remarks> | /// </remarks> | ||||
KickMembers = 0x00_00_00_02, | |||||
KickMembers = 0x00_00_00_02, | |||||
/// <summary> | /// <summary> | ||||
/// Allows banning members. | /// Allows banning members. | ||||
/// </summary> | /// </summary> | ||||
@@ -26,7 +26,7 @@ namespace Discord | |||||
/// This permission requires the owner account to use two-factor | /// This permission requires the owner account to use two-factor | ||||
/// authentication when used on a guild that has server-wide 2FA enabled. | /// authentication when used on a guild that has server-wide 2FA enabled. | ||||
/// </remarks> | /// </remarks> | ||||
BanMembers = 0x00_00_00_04, | |||||
BanMembers = 0x00_00_00_04, | |||||
/// <summary> | /// <summary> | ||||
/// Allows all permissions and bypasses channel permission overwrites. | /// Allows all permissions and bypasses channel permission overwrites. | ||||
/// </summary> | /// </summary> | ||||
@@ -34,7 +34,7 @@ namespace Discord | |||||
/// This permission requires the owner account to use two-factor | /// This permission requires the owner account to use two-factor | ||||
/// authentication when used on a guild that has server-wide 2FA enabled. | /// authentication when used on a guild that has server-wide 2FA enabled. | ||||
/// </remarks> | /// </remarks> | ||||
Administrator = 0x00_00_00_08, | |||||
Administrator = 0x00_00_00_08, | |||||
/// <summary> | /// <summary> | ||||
/// Allows management and editing of channels. | /// Allows management and editing of channels. | ||||
/// </summary> | /// </summary> | ||||
@@ -42,7 +42,7 @@ namespace Discord | |||||
/// This permission requires the owner account to use two-factor | /// This permission requires the owner account to use two-factor | ||||
/// authentication when used on a guild that has server-wide 2FA enabled. | /// authentication when used on a guild that has server-wide 2FA enabled. | ||||
/// </remarks> | /// </remarks> | ||||
ManageChannels = 0x00_00_00_10, | |||||
ManageChannels = 0x00_00_00_10, | |||||
/// <summary> | /// <summary> | ||||
/// Allows management and editing of the guild. | /// Allows management and editing of the guild. | ||||
/// </summary> | /// </summary> | ||||
@@ -50,27 +50,33 @@ namespace Discord | |||||
/// This permission requires the owner account to use two-factor | /// This permission requires the owner account to use two-factor | ||||
/// authentication when used on a guild that has server-wide 2FA enabled. | /// authentication when used on a guild that has server-wide 2FA enabled. | ||||
/// </remarks> | /// </remarks> | ||||
ManageGuild = 0x00_00_00_20, | |||||
ManageGuild = 0x00_00_00_20, | |||||
/// <summary> | /// <summary> | ||||
/// Allows for viewing of guild insights | /// Allows for viewing of guild insights | ||||
/// </summary> | /// </summary> | ||||
ViewGuildInsights = 0x00_08_00_00, | |||||
ViewGuildInsights = 0x00_08_00_00, | |||||
// Text | // Text | ||||
/// <summary> | /// <summary> | ||||
/// Allows for the addition of reactions to messages. | /// Allows for the addition of reactions to messages. | ||||
/// </summary> | /// </summary> | ||||
AddReactions = 0x00_00_00_40, | |||||
AddReactions = 0x00_00_00_40, | |||||
/// <summary> | /// <summary> | ||||
/// Allows for viewing of audit logs. | /// Allows for viewing of audit logs. | ||||
/// </summary> | /// </summary> | ||||
ViewAuditLog = 0x00_00_00_80, | |||||
ViewChannel = 0x00_00_04_00, | |||||
SendMessages = 0x00_00_08_00, | |||||
ViewAuditLog = 0x00_00_00_80, | |||||
/// <summary> | |||||
/// Allows guild members to view a channel, which includes reading messages in text channels. | |||||
/// </summary> | |||||
ViewChannel = 0x00_00_04_00, | |||||
/// <summary> | |||||
/// Allows for sending messages in a channel | |||||
/// </summary> | |||||
SendMessages = 0x00_00_08_00, | |||||
/// <summary> | /// <summary> | ||||
/// Allows for sending of text-to-speech messages. | /// Allows for sending of text-to-speech messages. | ||||
/// </summary> | /// </summary> | ||||
SendTTSMessages = 0x00_00_10_00, | |||||
SendTTSMessages = 0x00_00_10_00, | |||||
/// <summary> | /// <summary> | ||||
/// Allows for deletion of other users messages. | /// Allows for deletion of other users messages. | ||||
/// </summary> | /// </summary> | ||||
@@ -78,70 +84,73 @@ namespace Discord | |||||
/// This permission requires the owner account to use two-factor | /// This permission requires the owner account to use two-factor | ||||
/// authentication when used on a guild that has server-wide 2FA enabled. | /// authentication when used on a guild that has server-wide 2FA enabled. | ||||
/// </remarks> | /// </remarks> | ||||
ManageMessages = 0x00_00_20_00, | |||||
ManageMessages = 0x00_00_20_00, | |||||
/// <summary> | /// <summary> | ||||
/// Allows links sent by users with this permission will be auto-embedded. | /// Allows links sent by users with this permission will be auto-embedded. | ||||
/// </summary> | /// </summary> | ||||
EmbedLinks = 0x00_00_40_00, | |||||
EmbedLinks = 0x00_00_40_00, | |||||
/// <summary> | /// <summary> | ||||
/// Allows for uploading images and files. | /// Allows for uploading images and files. | ||||
/// </summary> | /// </summary> | ||||
AttachFiles = 0x00_00_80_00, | |||||
AttachFiles = 0x00_00_80_00, | |||||
/// <summary> | /// <summary> | ||||
/// Allows for reading of message history. | /// Allows for reading of message history. | ||||
/// </summary> | /// </summary> | ||||
ReadMessageHistory = 0x00_01_00_00, | |||||
ReadMessageHistory = 0x00_01_00_00, | |||||
/// <summary> | /// <summary> | ||||
/// Allows for using the @everyone tag to notify all users in a channel, and the @here tag to notify all | /// Allows for using the @everyone tag to notify all users in a channel, and the @here tag to notify all | ||||
/// online users in a channel. | /// online users in a channel. | ||||
/// </summary> | /// </summary> | ||||
MentionEveryone = 0x00_02_00_00, | |||||
MentionEveryone = 0x00_02_00_00, | |||||
/// <summary> | /// <summary> | ||||
/// Allows the usage of custom emojis from other servers. | /// Allows the usage of custom emojis from other servers. | ||||
/// </summary> | /// </summary> | ||||
UseExternalEmojis = 0x00_04_00_00, | |||||
UseExternalEmojis = 0x00_04_00_00, | |||||
// Voice | // Voice | ||||
/// <summary> | /// <summary> | ||||
/// Allows for joining of a voice channel. | /// Allows for joining of a voice channel. | ||||
/// </summary> | /// </summary> | ||||
Connect = 0x00_10_00_00, | |||||
Connect = 0x00_10_00_00, | |||||
/// <summary> | /// <summary> | ||||
/// Allows for speaking in a voice channel. | /// Allows for speaking in a voice channel. | ||||
/// </summary> | /// </summary> | ||||
Speak = 0x00_20_00_00, | |||||
Speak = 0x00_20_00_00, | |||||
/// <summary> | /// <summary> | ||||
/// Allows for muting members in a voice channel. | /// Allows for muting members in a voice channel. | ||||
/// </summary> | /// </summary> | ||||
MuteMembers = 0x00_40_00_00, | |||||
MuteMembers = 0x00_40_00_00, | |||||
/// <summary> | /// <summary> | ||||
/// Allows for deafening of members in a voice channel. | /// Allows for deafening of members in a voice channel. | ||||
/// </summary> | /// </summary> | ||||
DeafenMembers = 0x00_80_00_00, | |||||
DeafenMembers = 0x00_80_00_00, | |||||
/// <summary> | /// <summary> | ||||
/// Allows for moving of members between voice channels. | /// Allows for moving of members between voice channels. | ||||
/// </summary> | /// </summary> | ||||
MoveMembers = 0x01_00_00_00, | |||||
MoveMembers = 0x01_00_00_00, | |||||
/// <summary> | /// <summary> | ||||
/// Allows for using voice-activity-detection in a voice channel. | /// Allows for using voice-activity-detection in a voice channel. | ||||
/// </summary> | /// </summary> | ||||
UseVAD = 0x02_00_00_00, | |||||
PrioritySpeaker = 0x00_00_01_00, | |||||
UseVAD = 0x02_00_00_00, | |||||
/// <summary> | |||||
/// Allows for using priority speaker in a voice channel. | |||||
/// </summary> | |||||
PrioritySpeaker = 0x00_00_01_00, | |||||
/// <summary> | /// <summary> | ||||
/// Allows video streaming in a voice channel. | /// Allows video streaming in a voice channel. | ||||
/// </summary> | /// </summary> | ||||
Stream = 0x00_00_02_00, | |||||
Stream = 0x00_00_02_00, | |||||
// General 2 | // General 2 | ||||
/// <summary> | /// <summary> | ||||
/// Allows for modification of own nickname. | /// Allows for modification of own nickname. | ||||
/// </summary> | /// </summary> | ||||
ChangeNickname = 0x04_00_00_00, | |||||
ChangeNickname = 0x04_00_00_00, | |||||
/// <summary> | /// <summary> | ||||
/// Allows for modification of other users nicknames. | /// Allows for modification of other users nicknames. | ||||
/// </summary> | /// </summary> | ||||
ManageNicknames = 0x08_00_00_00, | |||||
ManageNicknames = 0x08_00_00_00, | |||||
/// <summary> | /// <summary> | ||||
/// Allows management and editing of roles. | /// Allows management and editing of roles. | ||||
/// </summary> | /// </summary> | ||||
@@ -149,7 +158,7 @@ namespace Discord | |||||
/// This permission requires the owner account to use two-factor | /// This permission requires the owner account to use two-factor | ||||
/// authentication when used on a guild that has server-wide 2FA enabled. | /// authentication when used on a guild that has server-wide 2FA enabled. | ||||
/// </remarks> | /// </remarks> | ||||
ManageRoles = 0x10_00_00_00, | |||||
ManageRoles = 0x10_00_00_00, | |||||
/// <summary> | /// <summary> | ||||
/// Allows management and editing of webhooks. | /// Allows management and editing of webhooks. | ||||
/// </summary> | /// </summary> | ||||
@@ -157,14 +166,43 @@ namespace Discord | |||||
/// This permission requires the owner account to use two-factor | /// This permission requires the owner account to use two-factor | ||||
/// authentication when used on a guild that has server-wide 2FA enabled. | /// authentication when used on a guild that has server-wide 2FA enabled. | ||||
/// </remarks> | /// </remarks> | ||||
ManageWebhooks = 0x20_00_00_00, | |||||
ManageWebhooks = 0x20_00_00_00, | |||||
/// <summary> | /// <summary> | ||||
/// Allows management and editing of emojis. | |||||
/// Allows management and editing of emojis and stickers. | |||||
/// </summary> | /// </summary> | ||||
/// <remarks> | /// <remarks> | ||||
/// This permission requires the owner account to use two-factor | /// This permission requires the owner account to use two-factor | ||||
/// authentication when used on a guild that has server-wide 2FA enabled. | /// authentication when used on a guild that has server-wide 2FA enabled. | ||||
/// </remarks> | /// </remarks> | ||||
ManageEmojis = 0x40_00_00_00 | |||||
ManageEmojisAndStickers = 0x40_00_00_00, | |||||
/// <summary> | |||||
/// Allows members to use slash commands in text channels. | |||||
/// </summary> | |||||
UseSlashCommands = 0x80_00_00_00, | |||||
/// <summary> | |||||
/// Allows for requesting to speak in stage channels. <i>(This permission is under active development and may be changed or removed.)</i>. | |||||
/// </summary> | |||||
RequestToSpeak = 0x01_00_00_00_00, | |||||
/// <summary> | |||||
/// Allows for deleting and archiving threads, and viewing all private threads. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// This permission requires the owner account to use two-factor | |||||
/// authentication when used on a guild that has server-wide 2FA enabled. | |||||
/// </remarks> | |||||
ManageThreads = 0x04_00_00_00_00, | |||||
/// <summary> | |||||
/// Allows for creating and participating in threads. | |||||
/// </summary> | |||||
UsePublicThreads = 0x08_00_00_00_00, | |||||
/// <summary> | |||||
/// Allows for creating and participating in private threads. | |||||
/// </summary> | |||||
UsePrivateThreads = 0x10_00_00_00_00, | |||||
/// <summary> | |||||
/// Allows the usage of custom stickers from other servers. | |||||
/// </summary> | |||||
UseExternalStickers = 0x20_00_00_00_00 | |||||
} | } | ||||
} | } |
@@ -82,7 +82,7 @@ namespace Discord | |||||
/// <summary> If <c>true</c>, a user may edit the webhooks for this guild. </summary> | /// <summary> If <c>true</c>, a user may edit the webhooks for this guild. </summary> | ||||
public bool ManageWebhooks => Permissions.GetValue(RawValue, GuildPermission.ManageWebhooks); | public bool ManageWebhooks => Permissions.GetValue(RawValue, GuildPermission.ManageWebhooks); | ||||
/// <summary> If <c>true</c>, a user may edit the emojis for this guild. </summary> | /// <summary> If <c>true</c>, a user may edit the emojis for this guild. </summary> | ||||
public bool ManageEmojis => Permissions.GetValue(RawValue, GuildPermission.ManageEmojis); | |||||
public bool ManageEmojisAndStickers => Permissions.GetValue(RawValue, GuildPermission.ManageEmojisAndStickers); | |||||
/// <summary> Creates a new <see cref="GuildPermissions"/> with the provided packed value. </summary> | /// <summary> Creates a new <see cref="GuildPermissions"/> with the provided packed value. </summary> | ||||
public GuildPermissions(ulong rawValue) { RawValue = rawValue; } | public GuildPermissions(ulong rawValue) { RawValue = rawValue; } | ||||
@@ -121,7 +121,7 @@ namespace Discord | |||||
bool? manageNicknames = null, | bool? manageNicknames = null, | ||||
bool? manageRoles = null, | bool? manageRoles = null, | ||||
bool? manageWebhooks = null, | bool? manageWebhooks = null, | ||||
bool? manageEmojis = null) | |||||
bool? manageEmojisAndStickers = null) | |||||
{ | { | ||||
ulong value = initialValue; | ulong value = initialValue; | ||||
@@ -155,7 +155,7 @@ namespace Discord | |||||
Permissions.SetValue(ref value, manageNicknames, GuildPermission.ManageNicknames); | Permissions.SetValue(ref value, manageNicknames, GuildPermission.ManageNicknames); | ||||
Permissions.SetValue(ref value, manageRoles, GuildPermission.ManageRoles); | Permissions.SetValue(ref value, manageRoles, GuildPermission.ManageRoles); | ||||
Permissions.SetValue(ref value, manageWebhooks, GuildPermission.ManageWebhooks); | Permissions.SetValue(ref value, manageWebhooks, GuildPermission.ManageWebhooks); | ||||
Permissions.SetValue(ref value, manageEmojis, GuildPermission.ManageEmojis); | |||||
Permissions.SetValue(ref value, manageEmojisAndStickers, GuildPermission.ManageEmojisAndStickers); | |||||
RawValue = value; | RawValue = value; | ||||
} | } | ||||
@@ -224,7 +224,7 @@ namespace Discord | |||||
changeNickname: changeNickname, | changeNickname: changeNickname, | ||||
manageNicknames: manageNicknames, | manageNicknames: manageNicknames, | ||||
manageWebhooks: manageWebhooks, | manageWebhooks: manageWebhooks, | ||||
manageEmojis: manageEmojis) | |||||
manageEmojisAndStickers: manageEmojis) | |||||
{ } | { } | ||||
/// <summary> Creates a new <see cref="GuildPermissions"/> from this one, changing the provided non-null permissions. </summary> | /// <summary> Creates a new <see cref="GuildPermissions"/> from this one, changing the provided non-null permissions. </summary> | ||||
@@ -18,6 +18,12 @@ namespace Discord.API | |||||
[JsonProperty("join_timestamp")] | [JsonProperty("join_timestamp")] | ||||
public DateTimeOffset JoinTimestamp { get; set; } | public DateTimeOffset JoinTimestamp { get; set; } | ||||
[JsonProperty("presense")] | |||||
public Optional<Presence> Presence { get; set; } | |||||
[JsonProperty("member")] | |||||
public Optional<GuildMember> Member { get; set; } | |||||
[JsonProperty("flags")] | [JsonProperty("flags")] | ||||
public int Flags { get; set; } // No enum type (yet?) | public int Flags { get; set; } // No enum type (yet?) | ||||
} | } | ||||
@@ -13,7 +13,7 @@ namespace Discord.API | |||||
public bool Archived { get; set; } | public bool Archived { get; set; } | ||||
[JsonProperty("auto_archive_duration")] | [JsonProperty("auto_archive_duration")] | ||||
public int AutoArchiveDuration { get; set; } | |||||
public ThreadArchiveDuration AutoArchiveDuration { get; set; } | |||||
[JsonProperty("archive_timestamp")] | [JsonProperty("archive_timestamp")] | ||||
public DateTimeOffset ArchiveTimestamp { get; set; } | public DateTimeOffset ArchiveTimestamp { get; set; } | ||||
@@ -0,0 +1,28 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using Discord; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Rest | |||||
{ | |||||
internal class ModifyThreadParams | |||||
{ | |||||
[JsonProperty("name")] | |||||
public Optional<string> Name { get; set; } | |||||
[JsonProperty("archived")] | |||||
public Optional<bool> Archived { get; set; } | |||||
[JsonProperty("auto_archive_duration")] | |||||
public Optional<ThreadArchiveDuration> AutoArchiveDuration { get; set; } | |||||
[JsonProperty("locked")] | |||||
public Optional<bool> Locked { get; set; } | |||||
[JsonProperty("rate_limit_per_user")] | |||||
public Optional<int> Slowmode { get; set; } | |||||
} | |||||
} |
@@ -16,6 +16,6 @@ namespace Discord.API.Rest | |||||
public ThreadArchiveDuration Duration { get; set; } | public ThreadArchiveDuration Duration { get; set; } | ||||
[JsonProperty("type")] | [JsonProperty("type")] | ||||
public Optional<ChannelType> Type { get; set; } | |||||
public Optional<ThreadType> Type { get; set; } | |||||
} | } | ||||
} | } |
@@ -2458,6 +2458,38 @@ | |||||
<member name="M:Discord.Rest.RestTextChannel.GetInvitesAsync(Discord.RequestOptions)"> | <member name="M:Discord.Rest.RestTextChannel.GetInvitesAsync(Discord.RequestOptions)"> | ||||
<inheritdoc /> | <inheritdoc /> | ||||
</member> | </member> | ||||
<member name="M:Discord.Rest.RestTextChannel.CreateThreadAsync(System.String,Discord.ThreadType,Discord.ThreadArchiveDuration,Discord.IMessage,Discord.RequestOptions)"> | |||||
<summary> | |||||
Creates a thread within this <see cref="T:Discord.ITextChannel"/>. | |||||
</summary> | |||||
<remarks> | |||||
When <paramref name="message"/> is <see langword="null"/> the thread type will be based off of the | |||||
channel its created in. When called on a <see cref="T:Discord.ITextChannel"/>, it creates a <see cref="F:Discord.ThreadType.PublicThread"/>. | |||||
When called on a <see cref="T:Discord.INewsChannel"/>, it creates a <see cref="F:Discord.ThreadType.NewsThread"/>. The id of the created | |||||
thread will be the same as the id of the message, and as such a message can only have a | |||||
single thread created from it. | |||||
</remarks> | |||||
<param name="name">The name of the thread.</param> | |||||
<param name="type"> | |||||
The type of the thread. | |||||
<para> | |||||
<b>Note: </b>This parameter is not used if the <paramref name="message"/> parameter is not specified. | |||||
</para> | |||||
</param> | |||||
<param name="autoArchiveDuration"> | |||||
The duration on which this thread archives after. | |||||
<para> | |||||
<b>Note: </b> Options <see cref="F:Discord.ThreadArchiveDuration.OneWeek"/> and <see cref="F:Discord.ThreadArchiveDuration.ThreeDays"/> | |||||
are only available for guilds that are boosted. You can check in the <see cref="P:Discord.IGuild.Features"/> to see if the | |||||
guild has the <b>THREE_DAY_THREAD_ARCHIVE</b> and <b>SEVEN_DAY_THREAD_ARCHIVE</b>. | |||||
</para> | |||||
</param> | |||||
<param name="message">The message which to start the thread from.</param> | |||||
<param name="options">The options to be used when sending the request.</param> | |||||
<returns> | |||||
A task that represents the asynchronous create operation. The task result contains a <see cref="T:Discord.IThreadChannel"/> | |||||
</returns> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestTextChannel.Discord#ITextChannel#CreateWebhookAsync(System.String,System.IO.Stream,Discord.RequestOptions)"> | <member name="M:Discord.Rest.RestTextChannel.Discord#ITextChannel#CreateWebhookAsync(System.String,System.IO.Stream,Discord.RequestOptions)"> | ||||
<inheritdoc /> | <inheritdoc /> | ||||
</member> | </member> | ||||
@@ -2506,6 +2538,163 @@ | |||||
<member name="M:Discord.Rest.RestTextChannel.Discord#INestedChannel#GetCategoryAsync(Discord.CacheMode,Discord.RequestOptions)"> | <member name="M:Discord.Rest.RestTextChannel.Discord#INestedChannel#GetCategoryAsync(Discord.CacheMode,Discord.RequestOptions)"> | ||||
<inheritdoc /> | <inheritdoc /> | ||||
</member> | </member> | ||||
<member name="T:Discord.Rest.RestThreadChannel"> | |||||
<summary> | |||||
Represents a thread channel recieved over REST. | |||||
</summary> | |||||
</member> | |||||
<member name="P:Discord.Rest.RestThreadChannel.Joined"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.Rest.RestThreadChannel.Archived"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.Rest.RestThreadChannel.AutoArchiveDuration"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.Rest.RestThreadChannel.ArchiveTimestamp"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.Rest.RestThreadChannel.Locked"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.Rest.RestThreadChannel.MemberCount"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.Rest.RestThreadChannel.MessageCount"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.Rest.RestThreadChannel.ParentChannelId"> | |||||
<summary> | |||||
Gets the parent text channel id. | |||||
</summary> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.GetUserAsync(System.UInt64,Discord.RequestOptions)"> | |||||
<summary> | |||||
Gets a user within this thread. | |||||
</summary> | |||||
<param name="userId">The id of the user to fetch.</param> | |||||
<param name="options">The options to be used when sending the request.</param> | |||||
<returns> | |||||
A task representing the asyncronous get operation. The task returns a | |||||
<see cref="T:Discord.Rest.RestThreadUser"/> if found, otherwise <see langword="null"/>. | |||||
</returns> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.GetUsersAsync(Discord.RequestOptions)"> | |||||
<summary> | |||||
Gets a collection of users within this thread. | |||||
</summary> | |||||
<param name="options">The options to be used when sending the request.</param> | |||||
<returns> | |||||
A task representing the asyncronous get operation. The task returns a | |||||
<see cref="T:System.Collections.Generic.IReadOnlyCollection`1"/> of <see cref="T:Discord.Rest.RestThreadUser"/>'s. | |||||
</returns> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.ModifyAsync(System.Action{Discord.TextChannelProperties},Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.AddPermissionOverwriteAsync(Discord.IRole,Discord.OverwritePermissions,Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.AddPermissionOverwriteAsync(Discord.IUser,Discord.OverwritePermissions,Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.CreateInviteAsync(System.Nullable{System.Int32},System.Nullable{System.Int32},System.Boolean,System.Boolean,Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.CreateInviteToApplicationAsync(System.UInt64,System.Nullable{System.Int32},System.Nullable{System.Int32},System.Boolean,System.Boolean,Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.CreateInviteToStreamAsync(Discord.IUser,System.Nullable{System.Int32},System.Nullable{System.Int32},System.Boolean,System.Boolean,Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.CreateWebhookAsync(System.String,System.IO.Stream,Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.GetCategoryAsync(Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.GetInvitesAsync(Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.GetPermissionOverwrite(Discord.IRole)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.GetPermissionOverwrite(Discord.IUser)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.GetWebhookAsync(System.UInt64,Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.GetWebhooksAsync(Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.RemovePermissionOverwriteAsync(Discord.IRole,Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.RemovePermissionOverwriteAsync(Discord.IUser,Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | |||||
<member name="P:Discord.Rest.RestThreadChannel.PermissionOverwrites"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.JoinAsync(Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.LeaveAsync(Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.AddUserAsync(Discord.IGuildUser,Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadChannel.RemoveUserAsync(Discord.IGuildUser,Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="T:Discord.Rest.RestVoiceChannel"> | <member name="T:Discord.Rest.RestVoiceChannel"> | ||||
<summary> | <summary> | ||||
Represents a REST-based voice channel in a guild. | Represents a REST-based voice channel in a guild. | ||||
@@ -4271,6 +4460,35 @@ | |||||
<inheritdoc /> | <inheritdoc /> | ||||
<exception cref="T:System.InvalidOperationException">Unable to modify this object using a different token.</exception> | <exception cref="T:System.InvalidOperationException">Unable to modify this object using a different token.</exception> | ||||
</member> | </member> | ||||
<member name="T:Discord.Rest.RestThreadUser"> | |||||
<summary> | |||||
Represents a thread user recieved over the REST api. | |||||
</summary> | |||||
</member> | |||||
<member name="P:Discord.Rest.RestThreadUser.Thread"> | |||||
<summary> | |||||
Gets the <see cref="T:Discord.Rest.RestThreadChannel"/> this user is in. | |||||
</summary> | |||||
</member> | |||||
<member name="P:Discord.Rest.RestThreadUser.JoinedAt"> | |||||
<summary> | |||||
Gets the timestamp for when this user joined this thread. | |||||
</summary> | |||||
</member> | |||||
<member name="P:Discord.Rest.RestThreadUser.Guild"> | |||||
<summary> | |||||
Gets the guild this user is in. | |||||
</summary> | |||||
</member> | |||||
<member name="M:Discord.Rest.RestThreadUser.GetGuildUser"> | |||||
<summary> | |||||
Gets the guild user for this thread user. | |||||
</summary> | |||||
<returns> | |||||
A task representing the asyncronous get operation. The task returns a | |||||
<see cref="T:Discord.IGuildUser"/> that represents the current thread user. | |||||
</returns> | |||||
</member> | |||||
<member name="T:Discord.Rest.RestUser"> | <member name="T:Discord.Rest.RestUser"> | ||||
<summary> | <summary> | ||||
Represents a REST-based user. | Represents a REST-based user. | ||||
@@ -415,6 +415,15 @@ namespace Discord.API | |||||
} | } | ||||
// Threads | // Threads | ||||
public async Task<Channel> ModifyThreadAsync(ulong channelId, ModifyThreadParams args, RequestOptions options = null) | |||||
{ | |||||
Preconditions.NotEqual(channelId, 0, nameof(channelId)); | |||||
var bucket = new BucketIds(channelId: channelId); | |||||
return await SendJsonAsync<Channel>("PATCH", () => $"channels/{channelId}", args, bucket, options: options); | |||||
} | |||||
public async Task<Channel> StartThreadAsync(ulong channelId, ulong messageId, StartThreadParams args, RequestOptions options = null) | public async Task<Channel> StartThreadAsync(ulong channelId, ulong messageId, StartThreadParams args, RequestOptions options = null) | ||||
{ | { | ||||
Preconditions.NotEqual(channelId, 0, nameof(channelId)); | Preconditions.NotEqual(channelId, 0, nameof(channelId)); | ||||
@@ -426,7 +435,7 @@ namespace Discord.API | |||||
return await SendJsonAsync<Channel>("POST", () => $"channels/{channelId}/messages/{messageId}/threads", args, bucket, options: options).ConfigureAwait(false); | return await SendJsonAsync<Channel>("POST", () => $"channels/{channelId}/messages/{messageId}/threads", args, bucket, options: options).ConfigureAwait(false); | ||||
} | } | ||||
public async Task<Channel> StartThreadAsync(ulong channelId, StartThreadParams args, RequestOptions options = null) | public async Task<Channel> StartThreadAsync(ulong channelId, StartThreadParams args, RequestOptions options = null) | ||||
{ | { | ||||
Preconditions.NotEqual(channelId, 0, nameof(channelId)); | Preconditions.NotEqual(channelId, 0, nameof(channelId)); | ||||
@@ -484,7 +493,7 @@ namespace Discord.API | |||||
var bucket = new BucketIds(channelId: channelId); | var bucket = new BucketIds(channelId: channelId); | ||||
return await SendAsync<ThreadMember[]>("GET", () => $"/channels/{channelId}", bucket, options: options); | |||||
return await SendAsync<ThreadMember[]>("GET", () => $"channels/{channelId}/thread-members", bucket, options: options); | |||||
} | } | ||||
public async Task<ChannelThreads> GetActiveThreadsAsync(ulong channelId, RequestOptions options = null) | public async Task<ChannelThreads> GetActiveThreadsAsync(ulong channelId, RequestOptions options = null) | ||||
@@ -41,14 +41,14 @@ namespace Discord.Rest | |||||
{ | { | ||||
base.Update(model); | base.Update(model); | ||||
CategoryId = model.CategoryId; | CategoryId = model.CategoryId; | ||||
Topic = model.Topic.Value; | |||||
Topic = model.Topic.GetValueOrDefault(); | |||||
if (model.SlowMode.IsSpecified) | if (model.SlowMode.IsSpecified) | ||||
SlowModeInterval = model.SlowMode.Value; | SlowModeInterval = model.SlowMode.Value; | ||||
IsNsfw = model.Nsfw.GetValueOrDefault(); | IsNsfw = model.Nsfw.GetValueOrDefault(); | ||||
} | } | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public async Task ModifyAsync(Action<TextChannelProperties> func, RequestOptions options = null) | |||||
public virtual async Task ModifyAsync(Action<TextChannelProperties> func, RequestOptions options = null) | |||||
{ | { | ||||
var model = await ChannelHelper.ModifyAsync(this, Discord, func, options).ConfigureAwait(false); | var model = await ChannelHelper.ModifyAsync(this, Discord, func, options).ConfigureAwait(false); | ||||
Update(model); | Update(model); | ||||
@@ -173,7 +173,7 @@ namespace Discord.Rest | |||||
/// A task that represents the asynchronous creation operation. The task result contains the newly created | /// A task that represents the asynchronous creation operation. The task result contains the newly created | ||||
/// webhook. | /// webhook. | ||||
/// </returns> | /// </returns> | ||||
public Task<RestWebhook> CreateWebhookAsync(string name, Stream avatar = null, RequestOptions options = null) | |||||
public virtual Task<RestWebhook> CreateWebhookAsync(string name, Stream avatar = null, RequestOptions options = null) | |||||
=> ChannelHelper.CreateWebhookAsync(this, Discord, name, avatar, options); | => ChannelHelper.CreateWebhookAsync(this, Discord, name, avatar, options); | ||||
/// <summary> | /// <summary> | ||||
/// Gets a webhook available in this text channel. | /// Gets a webhook available in this text channel. | ||||
@@ -184,7 +184,7 @@ namespace Discord.Rest | |||||
/// A task that represents the asynchronous get operation. The task result contains a webhook associated | /// A task that represents the asynchronous get operation. The task result contains a webhook associated | ||||
/// with the identifier; <c>null</c> if the webhook is not found. | /// with the identifier; <c>null</c> if the webhook is not found. | ||||
/// </returns> | /// </returns> | ||||
public Task<RestWebhook> GetWebhookAsync(ulong id, RequestOptions options = null) | |||||
public virtual Task<RestWebhook> GetWebhookAsync(ulong id, RequestOptions options = null) | |||||
=> ChannelHelper.GetWebhookAsync(this, Discord, id, options); | => ChannelHelper.GetWebhookAsync(this, Discord, id, options); | ||||
/// <summary> | /// <summary> | ||||
/// Gets the webhooks available in this text channel. | /// Gets the webhooks available in this text channel. | ||||
@@ -194,7 +194,7 @@ namespace Discord.Rest | |||||
/// A task that represents the asynchronous get operation. The task result contains a read-only collection | /// A task that represents the asynchronous get operation. The task result contains a read-only collection | ||||
/// of webhooks that is available in this channel. | /// of webhooks that is available in this channel. | ||||
/// </returns> | /// </returns> | ||||
public Task<IReadOnlyCollection<RestWebhook>> GetWebhooksAsync(RequestOptions options = null) | |||||
public virtual Task<IReadOnlyCollection<RestWebhook>> GetWebhooksAsync(RequestOptions options = null) | |||||
=> ChannelHelper.GetWebhooksAsync(this, Discord, options); | => ChannelHelper.GetWebhooksAsync(this, Discord, options); | ||||
/// <summary> | /// <summary> | ||||
@@ -205,7 +205,7 @@ namespace Discord.Rest | |||||
/// A task that represents the asynchronous get operation. The task result contains the category channel | /// A task that represents the asynchronous get operation. The task result contains the category channel | ||||
/// representing the parent of this channel; <c>null</c> if none is set. | /// representing the parent of this channel; <c>null</c> if none is set. | ||||
/// </returns> | /// </returns> | ||||
public Task<ICategoryChannel> GetCategoryAsync(RequestOptions options = null) | |||||
public virtual Task<ICategoryChannel> GetCategoryAsync(RequestOptions options = null) | |||||
=> ChannelHelper.GetCategoryAsync(this, Discord, options); | => ChannelHelper.GetCategoryAsync(this, Discord, options); | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public Task SyncPermissionsAsync(RequestOptions options = null) | public Task SyncPermissionsAsync(RequestOptions options = null) | ||||
@@ -213,18 +213,55 @@ namespace Discord.Rest | |||||
//Invites | //Invites | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public async Task<IInviteMetadata> CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) | |||||
public virtual async Task<IInviteMetadata> CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) | |||||
=> await ChannelHelper.CreateInviteAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, options).ConfigureAwait(false); | => await ChannelHelper.CreateInviteAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, options).ConfigureAwait(false); | ||||
public Task<IInviteMetadata> CreateInviteToApplicationAsync(ulong applicationId, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) | |||||
public virtual Task<IInviteMetadata> CreateInviteToApplicationAsync(ulong applicationId, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | => throw new NotImplementedException(); | ||||
public Task<IInviteMetadata> CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) | |||||
public virtual Task<IInviteMetadata> CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | => throw new NotImplementedException(); | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public async Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync(RequestOptions options = null) | |||||
public virtual async Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync(RequestOptions options = null) | |||||
=> await ChannelHelper.GetInvitesAsync(this, Discord, options).ConfigureAwait(false); | => await ChannelHelper.GetInvitesAsync(this, Discord, options).ConfigureAwait(false); | ||||
private string DebuggerDisplay => $"{Name} ({Id}, Text)"; | private string DebuggerDisplay => $"{Name} ({Id}, Text)"; | ||||
/// <summary> | |||||
/// Creates a thread within this <see cref="ITextChannel"/>. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// When <paramref name="message"/> is <see langword="null"/> the thread type will be based off of the | |||||
/// channel its created in. When called on a <see cref="ITextChannel"/>, it creates a <see cref="ThreadType.PublicThread"/>. | |||||
/// When called on a <see cref="INewsChannel"/>, it creates a <see cref="ThreadType.NewsThread"/>. The id of the created | |||||
/// thread will be the same as the id of the message, and as such a message can only have a | |||||
/// single thread created from it. | |||||
/// </remarks> | |||||
/// <param name="name">The name of the thread.</param> | |||||
/// <param name="type"> | |||||
/// The type of the thread. | |||||
/// <para> | |||||
/// <b>Note: </b>This parameter is not used if the <paramref name="message"/> parameter is not specified. | |||||
/// </para> | |||||
/// </param> | |||||
/// <param name="autoArchiveDuration"> | |||||
/// The duration on which this thread archives after. | |||||
/// <para> | |||||
/// <b>Note: </b> Options <see cref="ThreadArchiveDuration.OneWeek"/> and <see cref="ThreadArchiveDuration.ThreeDays"/> | |||||
/// are only available for guilds that are boosted. You can check in the <see cref="IGuild.Features"/> to see if the | |||||
/// guild has the <b>THREE_DAY_THREAD_ARCHIVE</b> and <b>SEVEN_DAY_THREAD_ARCHIVE</b>. | |||||
/// </para> | |||||
/// </param> | |||||
/// <param name="message">The message which to start the thread from.</param> | |||||
/// <param name="options">The options to be used when sending the request.</param> | |||||
/// <returns> | |||||
/// A task that represents the asynchronous create operation. The task result contains a <see cref="IThreadChannel"/> | |||||
/// </returns> | |||||
public async Task<RestThreadChannel> CreateThreadAsync(string name, ThreadType type = ThreadType.PublicThread, | |||||
ThreadArchiveDuration autoArchiveDuration = ThreadArchiveDuration.OneDay, IMessage message = null, RequestOptions options = null) | |||||
{ | |||||
var model = await ThreadHelper.CreateThreadAsync(Discord, this, name, type, autoArchiveDuration, message, options); | |||||
return RestThreadChannel.Create(Discord, this.Guild, model); | |||||
} | |||||
//ITextChannel | //ITextChannel | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
async Task<IWebhook> ITextChannel.CreateWebhookAsync(string name, Stream avatar, RequestOptions options) | async Task<IWebhook> ITextChannel.CreateWebhookAsync(string name, Stream avatar, RequestOptions options) | ||||
@@ -236,6 +273,9 @@ namespace Discord.Rest | |||||
async Task<IReadOnlyCollection<IWebhook>> ITextChannel.GetWebhooksAsync(RequestOptions options) | async Task<IReadOnlyCollection<IWebhook>> ITextChannel.GetWebhooksAsync(RequestOptions options) | ||||
=> await GetWebhooksAsync(options).ConfigureAwait(false); | => await GetWebhooksAsync(options).ConfigureAwait(false); | ||||
async Task<IThreadChannel> ITextChannel.CreateThreadAsync(string name, ThreadType type, ThreadArchiveDuration autoArchiveDuration, IMessage message, RequestOptions options) | |||||
=> await CreateThreadAsync(name, type, autoArchiveDuration, message, options); | |||||
//IMessageChannel | //IMessageChannel | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
async Task<IMessage> IMessageChannel.GetMessageAsync(ulong id, CacheMode mode, RequestOptions options) | async Task<IMessage> IMessageChannel.GetMessageAsync(ulong id, CacheMode mode, RequestOptions options) | ||||
@@ -0,0 +1,230 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Collections.Immutable; | |||||
using System.IO; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using Model = Discord.API.Channel; | |||||
namespace Discord.Rest | |||||
{ | |||||
/// <summary> | |||||
/// Represents a thread channel recieved over REST. | |||||
/// </summary> | |||||
public class RestThreadChannel : RestTextChannel, IThreadChannel | |||||
{ | |||||
public ThreadType Type { get; private set; } | |||||
/// <inheritdoc/> | |||||
public bool Joined { get; private set; } | |||||
/// <inheritdoc/> | |||||
public bool Archived { get; private set; } | |||||
/// <inheritdoc/> | |||||
public ThreadArchiveDuration AutoArchiveDuration { get; private set; } | |||||
/// <inheritdoc/> | |||||
public DateTimeOffset ArchiveTimestamp { get; private set; } | |||||
/// <inheritdoc/> | |||||
public bool Locked { get; private set; } | |||||
/// <inheritdoc/> | |||||
public int MemberCount { get; private set; } | |||||
/// <inheritdoc/> | |||||
public int MessageCount { get; private set; } | |||||
/// <summary> | |||||
/// Gets the parent text channel id. | |||||
/// </summary> | |||||
public ulong ParentChannelId { get; private set; } | |||||
internal RestThreadChannel(BaseDiscordClient discord, IGuild guild, ulong id) | |||||
: base(discord, guild, id) | |||||
{ | |||||
} | |||||
internal new static RestThreadChannel Create(BaseDiscordClient discord, IGuild guild, Model model) | |||||
{ | |||||
var entity = new RestThreadChannel(discord, guild, model.Id); | |||||
entity.Update(model); | |||||
return entity; | |||||
} | |||||
internal override void Update(Model model) | |||||
{ | |||||
base.Update(model); | |||||
this.Joined = model.ThreadMember.IsSpecified; | |||||
if (model.ThreadMetadata.IsSpecified) | |||||
{ | |||||
this.Archived = model.ThreadMetadata.Value.Archived; | |||||
this.AutoArchiveDuration = model.ThreadMetadata.Value.AutoArchiveDuration; | |||||
this.ArchiveTimestamp = model.ThreadMetadata.Value.ArchiveTimestamp; | |||||
this.Locked = model.ThreadMetadata.Value.Locked.GetValueOrDefault(false); | |||||
} | |||||
this.MemberCount = model.MemberCount.GetValueOrDefault(0); | |||||
this.MessageCount = model.MessageCount.GetValueOrDefault(0); | |||||
this.Type = (ThreadType)model.Type; | |||||
this.ParentChannelId = model.CategoryId.Value; | |||||
} | |||||
/// <summary> | |||||
/// Gets a user within this thread. | |||||
/// </summary> | |||||
/// <param name="userId">The id of the user to fetch.</param> | |||||
/// <param name="options">The options to be used when sending the request.</param> | |||||
/// <returns> | |||||
/// A task representing the asyncronous get operation. The task returns a | |||||
/// <see cref="RestThreadUser"/> if found, otherwise <see langword="null"/>. | |||||
/// </returns> | |||||
public new Task<RestThreadUser> GetUserAsync(ulong userId, RequestOptions options = null) | |||||
=> ThreadHelper.GetUserAsync(userId, this, Discord, options); | |||||
/// <summary> | |||||
/// Gets a collection of users within this thread. | |||||
/// </summary> | |||||
/// <param name="options">The options to be used when sending the request.</param> | |||||
/// <returns> | |||||
/// A task representing the asyncronous get operation. The task returns a | |||||
/// <see cref="IReadOnlyCollection{T}"/> of <see cref="RestThreadUser"/>'s. | |||||
/// </returns> | |||||
public new async Task<IReadOnlyCollection<RestThreadUser>> GetUsersAsync(RequestOptions options = null) | |||||
=> (await ThreadHelper.GetUsersAsync(this, Discord, options).ConfigureAwait(false)).ToImmutableArray(); | |||||
/// <inheritdoc/> | |||||
public override async Task ModifyAsync(Action<TextChannelProperties> func, RequestOptions options = null) | |||||
{ | |||||
var model = await ThreadHelper.ModifyAsync(this, Discord, func, options); | |||||
Update(model); | |||||
} | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task AddPermissionOverwriteAsync(IRole role, OverwritePermissions permissions, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task AddPermissionOverwriteAsync(IUser user, OverwritePermissions permissions, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task<IInviteMetadata> CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task<IInviteMetadata> CreateInviteToApplicationAsync(ulong applicationId, int? maxAge, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task<IInviteMetadata> CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task<RestWebhook> CreateWebhookAsync(string name, Stream avatar = null, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task<ICategoryChannel> GetCategoryAsync(RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync(RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override OverwritePermissions? GetPermissionOverwrite(IRole role) | |||||
=> throw new NotImplementedException(); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override OverwritePermissions? GetPermissionOverwrite(IUser user) | |||||
=> throw new NotImplementedException(); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task<RestWebhook> GetWebhookAsync(ulong id, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task<IReadOnlyCollection<RestWebhook>> GetWebhooksAsync(RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task RemovePermissionOverwriteAsync(IRole role, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task RemovePermissionOverwriteAsync(IUser user, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override IReadOnlyCollection<Overwrite> PermissionOverwrites | |||||
=> throw new NotImplementedException(); | |||||
/// <inheritdoc/> | |||||
public Task JoinAsync(RequestOptions options = null) | |||||
=> Discord.ApiClient.JoinThreadAsync(this.Id, options); | |||||
/// <inheritdoc/> | |||||
public Task LeaveAsync(RequestOptions options = null) | |||||
=> Discord.ApiClient.LeaveThreadAsync(this.Id, options); | |||||
/// <inheritdoc/> | |||||
public Task AddUserAsync(IGuildUser user, RequestOptions options = null) | |||||
=> Discord.ApiClient.AddThreadMemberAsync(this.Id, user.Id, options); | |||||
/// <inheritdoc/> | |||||
public Task RemoveUserAsync(IGuildUser user, RequestOptions options = null) | |||||
=> Discord.ApiClient.RemoveThreadMemberAsync(this.Id, user.Id, options); | |||||
} | |||||
} |
@@ -0,0 +1,66 @@ | |||||
using Discord.API.Rest; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using Model = Discord.API.Channel; | |||||
namespace Discord.Rest | |||||
{ | |||||
internal static class ThreadHelper | |||||
{ | |||||
public static async Task<Model> CreateThreadAsync(BaseDiscordClient client, ITextChannel channel, string name, ThreadType type = ThreadType.PublicThread, | |||||
ThreadArchiveDuration autoArchiveDuration = ThreadArchiveDuration.OneDay, IMessage message = null, RequestOptions options = null) | |||||
{ | |||||
if (autoArchiveDuration == ThreadArchiveDuration.OneWeek && !channel.Guild.Features.Contains("SEVEN_DAY_THREAD_ARCHIVE")) | |||||
throw new ArgumentException($"The guild {channel.Guild.Name} does not have the SEVEN_DAY_THREAD_ARCHIVE feature!"); | |||||
if (autoArchiveDuration == ThreadArchiveDuration.ThreeDays && !channel.Guild.Features.Contains("THREE_DAY_THREAD_ARCHIVE")) | |||||
throw new ArgumentException($"The guild {channel.Guild.Name} does not have the THREE_DAY_THREAD_ARCHIVE feature!"); | |||||
var args = new StartThreadParams() | |||||
{ | |||||
Name = name, | |||||
Duration = autoArchiveDuration, | |||||
Type = type | |||||
}; | |||||
Model model = null; | |||||
if (message != null) | |||||
model = await client.ApiClient.StartThreadAsync(channel.Id, message.Id, args, options).ConfigureAwait(false); | |||||
else | |||||
model = await client.ApiClient.StartThreadAsync(channel.Id, args, options).ConfigureAwait(false); | |||||
return model; | |||||
} | |||||
public static async Task<Model> ModifyAsync(IThreadChannel channel, BaseDiscordClient client, | |||||
Action<TextChannelProperties> func, | |||||
RequestOptions options) | |||||
{ | |||||
var args = new TextChannelProperties(); | |||||
func(args); | |||||
var apiArgs = new API.Rest.ModifyThreadParams | |||||
{ | |||||
Name = args.Name, | |||||
Archived = args.Archived, | |||||
AutoArchiveDuration = args.AutoArchiveDuration, | |||||
Locked = args.Locked, | |||||
Slowmode = args.SlowModeInterval | |||||
}; | |||||
return await client.ApiClient.ModifyThreadAsync(channel.Id, apiArgs, options).ConfigureAwait(false); | |||||
} | |||||
public static async Task<RestThreadUser[]> GetUsersAsync(IThreadChannel channel, BaseDiscordClient client, RequestOptions options = null) | |||||
{ | |||||
var users = await client.ApiClient.ListThreadMembersAsync(channel.Id, options); | |||||
return users.Select(x => RestThreadUser.Create(client, channel.Guild, x, channel)).ToArray(); | |||||
} | |||||
public static async Task<RestThreadUser> GetUserAsync(ulong userdId, IThreadChannel channel, BaseDiscordClient client, RequestOptions options = null) | |||||
=> (await GetUsersAsync(channel, client, options).ConfigureAwait(false)).FirstOrDefault(x => x.Id == userdId); | |||||
} | |||||
} |
@@ -0,0 +1,60 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Collections.Immutable; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using Model = Discord.API.ThreadMember; | |||||
namespace Discord.Rest | |||||
{ | |||||
/// <summary> | |||||
/// Represents a thread user recieved over the REST api. | |||||
/// </summary> | |||||
public class RestThreadUser : RestEntity<ulong> | |||||
{ | |||||
/// <summary> | |||||
/// Gets the <see cref="RestThreadChannel"/> this user is in. | |||||
/// </summary> | |||||
public IThreadChannel Thread { get; } | |||||
/// <summary> | |||||
/// Gets the timestamp for when this user joined this thread. | |||||
/// </summary> | |||||
public DateTimeOffset JoinedAt { get; private set; } | |||||
/// <summary> | |||||
/// Gets the guild this user is in. | |||||
/// </summary> | |||||
public IGuild Guild { get; } | |||||
internal RestThreadUser(BaseDiscordClient discord, IGuild guild, IThreadChannel channel, ulong id) | |||||
: base(discord, id) | |||||
{ | |||||
this.Guild = guild; | |||||
this.Thread = channel; | |||||
} | |||||
internal static RestThreadUser Create(BaseDiscordClient client, IGuild guild, Model model, IThreadChannel channel) | |||||
{ | |||||
var entity = new RestThreadUser(client, guild, channel, model.UserId.Value); | |||||
entity.Update(model); | |||||
return entity; | |||||
} | |||||
internal void Update(Model model) | |||||
{ | |||||
this.JoinedAt = model.JoinTimestamp; | |||||
} | |||||
/// <summary> | |||||
/// Gets the guild user for this thread user. | |||||
/// </summary> | |||||
/// <returns> | |||||
/// A task representing the asyncronous get operation. The task returns a | |||||
/// <see cref="IGuildUser"/> that represents the current thread user. | |||||
/// </returns> | |||||
public Task<IGuildUser> GetGuildUser() | |||||
=> Guild.GetUserAsync(this.Id); | |||||
} | |||||
} |
@@ -572,5 +572,25 @@ namespace Discord.WebSocket | |||||
} | } | ||||
internal readonly AsyncEvent<Func<Cacheable<SocketThreadChannel, ulong>, Task>> _threadDeleted = new AsyncEvent<Func<Cacheable<SocketThreadChannel, ulong>, Task>>(); | internal readonly AsyncEvent<Func<Cacheable<SocketThreadChannel, ulong>, Task>> _threadDeleted = new AsyncEvent<Func<Cacheable<SocketThreadChannel, ulong>, Task>>(); | ||||
/// <summary> | |||||
/// Fired when a user joins a thread | |||||
/// </summary> | |||||
public event Func<SocketThreadUser, Task> ThreadMemberJoined | |||||
{ | |||||
add { _threadMemberJoined.Add(value); } | |||||
remove { _threadMemberJoined.Remove(value); } | |||||
} | |||||
internal readonly AsyncEvent<Func<SocketThreadUser, Task>> _threadMemberJoined = new AsyncEvent<Func<SocketThreadUser, Task>>(); | |||||
/// <summary> | |||||
/// Fired when a user leaves a thread | |||||
/// </summary> | |||||
public event Func<SocketThreadUser, Task> ThreadMemberLeft | |||||
{ | |||||
add { _threadMemberLeft.Add(value); } | |||||
remove { _threadMemberLeft.Remove(value); } | |||||
} | |||||
internal readonly AsyncEvent<Func<SocketThreadUser, Task>> _threadMemberLeft = new AsyncEvent<Func<SocketThreadUser, Task>>(); | |||||
} | } | ||||
} | } |
@@ -771,6 +771,16 @@ | |||||
Fired when a thread is deleted. | Fired when a thread is deleted. | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="E:Discord.WebSocket.BaseSocketClient.ThreadMemberJoined"> | |||||
<summary> | |||||
Fired when a user joins a thread | |||||
</summary> | |||||
</member> | |||||
<member name="E:Discord.WebSocket.BaseSocketClient.ThreadMemberLeft"> | |||||
<summary> | |||||
Fired when a user leaves a thread | |||||
</summary> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.DiscordShardedClient.Latency"> | <member name="P:Discord.WebSocket.DiscordShardedClient.Latency"> | ||||
<inheritdoc /> | <inheritdoc /> | ||||
</member> | </member> | ||||
@@ -2380,6 +2390,16 @@ | |||||
Represents a thread channel inside of a guild. | Represents a thread channel inside of a guild. | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="P:Discord.WebSocket.SocketThreadChannel.Owner"> | |||||
<summary> | |||||
Gets the owner of the current thread. | |||||
</summary> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketThreadChannel.CurrentUser"> | |||||
<summary> | |||||
Gets the current users within this thread. | |||||
</summary> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketThreadChannel.Joined"> | <member name="P:Discord.WebSocket.SocketThreadChannel.Joined"> | ||||
<inheritdoc/> | <inheritdoc/> | ||||
</member> | </member> | ||||
@@ -2411,182 +2431,152 @@ | |||||
<member name="P:Discord.WebSocket.SocketThreadChannel.Locked"> | <member name="P:Discord.WebSocket.SocketThreadChannel.Locked"> | ||||
<inheritdoc/> | <inheritdoc/> | ||||
</member> | </member> | ||||
<member name="P:Discord.WebSocket.SocketThreadChannel.IsNsfw"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketThreadChannel.Topic"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketThreadChannel.SlowModeInterval"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketThreadChannel.Mention"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketThreadChannel.CategoryId"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketThreadChannel.CachedMessages"> | |||||
<inheritdoc /> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.SyncPermissionsAsync(Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.ModifyAsync(System.Action{Discord.TextChannelProperties},Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
<member name="P:Discord.WebSocket.SocketThreadChannel.Users"> | |||||
<summary> | |||||
Gets a collection of cached users within this thread. | |||||
</summary> | |||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.GetCachedMessage(System.UInt64)"> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.GetUser(System.UInt64)"> | |||||
<inheritdoc /> | <inheritdoc /> | ||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.GetMessageAsync(System.UInt64,Discord.RequestOptions)"> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.GetUsersAsync(Discord.RequestOptions)"> | |||||
<summary> | <summary> | ||||
Gets a message from this message channel. | |||||
Gets all users inside this thread. | |||||
</summary> | </summary> | ||||
<remarks> | <remarks> | ||||
This method follows the same behavior as described in <see cref="M:Discord.IMessageChannel.GetMessageAsync(System.UInt64,Discord.CacheMode,Discord.RequestOptions)"/>. | |||||
Please visit its documentation for more details on this method. | |||||
If all users are not downloaded then this method will call <see cref="M:Discord.WebSocket.SocketThreadChannel.DownloadUsersAsync(Discord.RequestOptions)"/> and return the result. | |||||
</remarks> | </remarks> | ||||
<param name="id">The snowflake identifier of the message.</param> | |||||
<param name="options">The options to be used when sending the request.</param> | <param name="options">The options to be used when sending the request.</param> | ||||
<returns> | |||||
A task that represents an asynchronous get operation for retrieving the message. The task result contains | |||||
the retrieved message; <c>null</c> if no message is found with the specified identifier. | |||||
</returns> | |||||
<returns>A task representing the download operation.</returns> | |||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.GetMessagesAsync(System.Int32,Discord.RequestOptions)"> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.DownloadUsersAsync(Discord.RequestOptions)"> | |||||
<summary> | <summary> | ||||
Gets the last N messages from this message channel. | |||||
Downloads all users that have access to this thread. | |||||
</summary> | </summary> | ||||
<remarks> | |||||
This method follows the same behavior as described in <see cref="M:Discord.IMessageChannel.GetMessagesAsync(System.Int32,Discord.CacheMode,Discord.RequestOptions)"/>. | |||||
Please visit its documentation for more details on this method. | |||||
</remarks> | |||||
<param name="limit">The numbers of message to be gotten from.</param> | |||||
<param name="options">The options to be used when sending the request.</param> | <param name="options">The options to be used when sending the request.</param> | ||||
<returns> | |||||
Paged collection of messages. | |||||
</returns> | |||||
<returns>A task representing the asyncronous download operation.</returns> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.JoinAsync(Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.GetMessagesAsync(System.UInt64,Discord.Direction,System.Int32,Discord.RequestOptions)"> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.LeaveAsync(Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.AddUserAsync(Discord.IGuildUser,Discord.RequestOptions)"> | |||||
<summary> | <summary> | ||||
Gets a collection of messages in this channel. | |||||
Adds a user to this thread. | |||||
</summary> | </summary> | ||||
<remarks> | |||||
This method follows the same behavior as described in <see cref="M:Discord.IMessageChannel.GetMessagesAsync(System.UInt64,Discord.Direction,System.Int32,Discord.CacheMode,Discord.RequestOptions)"/>. | |||||
Please visit its documentation for more details on this method. | |||||
</remarks> | |||||
<param name="fromMessageId">The ID of the starting message to get the messages from.</param> | |||||
<param name="dir">The direction of the messages to be gotten from.</param> | |||||
<param name="limit">The numbers of message to be gotten from.</param> | |||||
<param name="user">The <see cref="T:Discord.IGuildUser"/> to add.</param> | |||||
<param name="options">The options to be used when sending the request.</param> | <param name="options">The options to be used when sending the request.</param> | ||||
<returns> | <returns> | ||||
Paged collection of messages. | |||||
A task that represents the asynchronous operation of adding a member to a thread. | |||||
</returns> | </returns> | ||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.GetMessagesAsync(Discord.IMessage,Discord.Direction,System.Int32,Discord.RequestOptions)"> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.RemoveUserAsync(Discord.IGuildUser,Discord.RequestOptions)"> | |||||
<summary> | <summary> | ||||
Gets a collection of messages in this channel. | |||||
Removes a user from this thread. | |||||
</summary> | </summary> | ||||
<remarks> | |||||
This method follows the same behavior as described in <see cref="M:Discord.IMessageChannel.GetMessagesAsync(Discord.IMessage,Discord.Direction,System.Int32,Discord.CacheMode,Discord.RequestOptions)"/>. | |||||
Please visit its documentation for more details on this method. | |||||
</remarks> | |||||
<param name="fromMessage">The starting message to get the messages from.</param> | |||||
<param name="dir">The direction of the messages to be gotten from.</param> | |||||
<param name="limit">The numbers of message to be gotten from.</param> | |||||
<param name="user">The <see cref="T:Discord.IGuildUser"/> to remove from this thread.</param> | |||||
<param name="options">The options to be used when sending the request.</param> | <param name="options">The options to be used when sending the request.</param> | ||||
<returns> | <returns> | ||||
Paged collection of messages. | |||||
A task that represents the asynchronous operation of removing a user from this thread. | |||||
</returns> | </returns> | ||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.GetCachedMessages(System.Int32)"> | |||||
<inheritdoc /> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.GetCachedMessages(System.UInt64,Discord.Direction,System.Int32)"> | |||||
<inheritdoc /> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.GetCachedMessages(Discord.IMessage,Discord.Direction,System.Int32)"> | |||||
<inheritdoc /> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.GetPinnedMessagesAsync(Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.SendMessageAsync(System.String,System.Boolean,Discord.Embed,Discord.RequestOptions,Discord.AllowedMentions,Discord.MessageReference,Discord.MessageComponent)"> | |||||
<inheritdoc /> | |||||
<exception cref="T:System.ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="F:Discord.DiscordConfig.MaxMessageSize"/>.</exception> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.SendFileAsync(System.String,System.String,System.Boolean,Discord.Embed,Discord.RequestOptions,System.Boolean,Discord.AllowedMentions,Discord.MessageReference,Discord.MessageComponent)"> | |||||
<inheritdoc /> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.SendFileAsync(System.IO.Stream,System.String,System.String,System.Boolean,Discord.Embed,Discord.RequestOptions,System.Boolean,Discord.AllowedMentions,Discord.MessageReference,Discord.MessageComponent)"> | |||||
<inheritdoc /> | |||||
<exception cref="T:System.ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="F:Discord.DiscordConfig.MaxMessageSize"/>.</exception> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.DeleteMessagesAsync(System.Collections.Generic.IEnumerable{Discord.IMessage},Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.DeleteMessagesAsync(System.Collections.Generic.IEnumerable{System.UInt64},Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.ModifyMessageAsync(System.UInt64,System.Action{Discord.MessageProperties},Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.DeleteMessageAsync(System.UInt64,Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.DeleteMessageAsync(Discord.IMessage,Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.TriggerTypingAsync(Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.EnterTypingState(Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.AddPermissionOverwriteAsync(Discord.IRole,Discord.OverwritePermissions,Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.GetUser(System.UInt64)"> | |||||
<inheritdoc /> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.AddPermissionOverwriteAsync(Discord.IUser,Discord.OverwritePermissions,Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.Discord#ITextChannel#CreateWebhookAsync(System.String,System.IO.Stream,Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.CreateInviteAsync(System.Nullable{System.Int32},System.Nullable{System.Int32},System.Boolean,System.Boolean,Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.Discord#ITextChannel#GetWebhookAsync(System.UInt64,Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.CreateInviteToApplicationAsync(System.UInt64,System.Nullable{System.Int32},System.Nullable{System.Int32},System.Boolean,System.Boolean,Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.Discord#ITextChannel#GetWebhooksAsync(Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.CreateInviteToStreamAsync(Discord.IUser,System.Nullable{System.Int32},System.Nullable{System.Int32},System.Boolean,System.Boolean,Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.Discord#IGuildChannel#GetUserAsync(System.UInt64,Discord.CacheMode,Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.CreateWebhookAsync(System.String,System.IO.Stream,Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.Discord#IGuildChannel#GetUsersAsync(Discord.CacheMode,Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.GetInvitesAsync(Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.Discord#IMessageChannel#GetMessageAsync(System.UInt64,Discord.CacheMode,Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.GetPermissionOverwrite(Discord.IRole)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.Discord#IMessageChannel#GetMessagesAsync(System.Int32,Discord.CacheMode,Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.GetPermissionOverwrite(Discord.IUser)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.Discord#IMessageChannel#GetMessagesAsync(System.UInt64,Discord.Direction,System.Int32,Discord.CacheMode,Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.GetWebhookAsync(System.UInt64,Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.Discord#IMessageChannel#GetMessagesAsync(Discord.IMessage,Discord.Direction,System.Int32,Discord.CacheMode,Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.GetWebhooksAsync(Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.Discord#IMessageChannel#GetPinnedMessagesAsync(Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.ModifyAsync(System.Action{Discord.TextChannelProperties},Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.Discord#IMessageChannel#SendFileAsync(System.String,System.String,System.Boolean,Discord.Embed,Discord.RequestOptions,System.Boolean,Discord.AllowedMentions,Discord.MessageReference,Discord.MessageComponent)"> | |||||
<inheritdoc /> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.RemovePermissionOverwriteAsync(Discord.IRole,Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.Discord#IMessageChannel#SendFileAsync(System.IO.Stream,System.String,System.String,System.Boolean,Discord.Embed,Discord.RequestOptions,System.Boolean,Discord.AllowedMentions,Discord.MessageReference,Discord.MessageComponent)"> | |||||
<inheritdoc /> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.RemovePermissionOverwriteAsync(Discord.IUser,Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.Discord#IMessageChannel#SendMessageAsync(System.String,System.Boolean,Discord.Embed,Discord.RequestOptions,Discord.AllowedMentions,Discord.MessageReference,Discord.MessageComponent)"> | |||||
<inheritdoc /> | |||||
<member name="P:Discord.WebSocket.SocketThreadChannel.PermissionOverwrites"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadChannel.Discord#INestedChannel#GetCategoryAsync(Discord.CacheMode,Discord.RequestOptions)"> | |||||
<inheritdoc /> | |||||
<member name="M:Discord.WebSocket.SocketThreadChannel.SyncPermissionsAsync(Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
<remarks> | |||||
<b>This method is not supported in threads.</b> | |||||
</remarks> | |||||
</member> | </member> | ||||
<member name="T:Discord.WebSocket.SocketVoiceChannel"> | <member name="T:Discord.WebSocket.SocketVoiceChannel"> | ||||
<summary> | <summary> | ||||
@@ -4535,6 +4525,11 @@ | |||||
<member name="M:Discord.WebSocket.SocketSelfUser.ModifyAsync(System.Action{Discord.SelfUserProperties},Discord.RequestOptions)"> | <member name="M:Discord.WebSocket.SocketSelfUser.ModifyAsync(System.Action{Discord.SelfUserProperties},Discord.RequestOptions)"> | ||||
<inheritdoc /> | <inheritdoc /> | ||||
</member> | </member> | ||||
<member name="T:Discord.WebSocket.SocketThreadUser"> | |||||
<summary> | |||||
Represents a thread user received over the gateway. | |||||
</summary> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketThreadUser.Thread"> | <member name="P:Discord.WebSocket.SocketThreadUser.Thread"> | ||||
<summary> | <summary> | ||||
Gets the <see cref="T:Discord.WebSocket.SocketThreadChannel"/> this user is in. | Gets the <see cref="T:Discord.WebSocket.SocketThreadChannel"/> this user is in. | ||||
@@ -4565,9 +4560,6 @@ | |||||
<member name="P:Discord.WebSocket.SocketThreadUser.AvatarId"> | <member name="P:Discord.WebSocket.SocketThreadUser.AvatarId"> | ||||
<inheritdoc/> | <inheritdoc/> | ||||
</member> | </member> | ||||
<member name="P:Discord.WebSocket.SocketThreadUser.Discriminator"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketThreadUser.DiscriminatorValue"> | <member name="P:Discord.WebSocket.SocketThreadUser.DiscriminatorValue"> | ||||
<inheritdoc/> | <inheritdoc/> | ||||
</member> | </member> | ||||
@@ -4580,27 +4572,6 @@ | |||||
<member name="P:Discord.WebSocket.SocketThreadUser.Username"> | <member name="P:Discord.WebSocket.SocketThreadUser.Username"> | ||||
<inheritdoc/> | <inheritdoc/> | ||||
</member> | </member> | ||||
<member name="P:Discord.WebSocket.SocketThreadUser.PublicFlags"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketThreadUser.CreatedAt"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketThreadUser.Id"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketThreadUser.Mention"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketThreadUser.Status"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketThreadUser.ActiveClients"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketThreadUser.Activities"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketThreadUser.IsDeafened"> | <member name="P:Discord.WebSocket.SocketThreadUser.IsDeafened"> | ||||
<inheritdoc/> | <inheritdoc/> | ||||
</member> | </member> | ||||
@@ -4658,15 +4629,6 @@ | |||||
<member name="M:Discord.WebSocket.SocketThreadUser.RemoveRolesAsync(System.Collections.Generic.IEnumerable{Discord.IRole},Discord.RequestOptions)"> | <member name="M:Discord.WebSocket.SocketThreadUser.RemoveRolesAsync(System.Collections.Generic.IEnumerable{Discord.IRole},Discord.RequestOptions)"> | ||||
<inheritdoc/> | <inheritdoc/> | ||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketThreadUser.GetAvatarUrl(Discord.ImageFormat,System.UInt16)"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketThreadUser.GetDefaultAvatarUrl"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketThreadUser.CreateDMChannelAsync(Discord.RequestOptions)"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketThreadUser.Discord#IGuildUser#GuildPermissions"> | <member name="P:Discord.WebSocket.SocketThreadUser.Discord#IGuildUser#GuildPermissions"> | ||||
<inheritdoc/> | <inheritdoc/> | ||||
</member> | </member> | ||||
@@ -1975,63 +1975,58 @@ namespace Discord.WebSocket | |||||
// Threads | // Threads | ||||
case "THREAD_CREATE": | case "THREAD_CREATE": | ||||
{ | { | ||||
try | |||||
{ | |||||
await _gatewayLogger.DebugAsync("Received Dispatch (THREAD_CREATE)").ConfigureAwait(false); | |||||
await _gatewayLogger.DebugAsync("Received Dispatch (THREAD_CREATE)").ConfigureAwait(false); | |||||
var data = (payload as JToken).ToObject<Channel>(_serializer); | |||||
var data = (payload as JToken).ToObject<Channel>(_serializer); | |||||
var guild = State.GetGuild(data.GuildId.Value); | |||||
var guild = State.GetGuild(data.GuildId.Value); | |||||
if (guild == null) | |||||
{ | |||||
await UnknownGuildAsync(type, data.GuildId.Value); | |||||
return; | |||||
} | |||||
if (guild == null) | |||||
{ | |||||
await UnknownGuildAsync(type, data.GuildId.Value); | |||||
return; | |||||
} | |||||
var threadChannel = (SocketThreadChannel)guild.AddChannel(this.State, data); | |||||
SocketThreadChannel threadChannel = null; | |||||
await TimedInvokeAsync(_threadCreated, nameof(ThreadCreated), threadChannel).ConfigureAwait(false); | |||||
if ((threadChannel = guild.ThreadChannels.FirstOrDefault(x => x.Id == data.Id)) != null) | |||||
{ | |||||
threadChannel.Update(this.State, data); | |||||
threadChannel.AddOrUpdateThreadMember(data.ThreadMember.Value, guild.CurrentUser); | |||||
} | } | ||||
catch(Exception x) | |||||
else | |||||
{ | { | ||||
threadChannel = (SocketThreadChannel)guild.AddChannel(this.State, data); | |||||
threadChannel.AddOrUpdateThreadMember(data.ThreadMember.Value, guild.CurrentUser); | |||||
await TimedInvokeAsync(_threadCreated, nameof(ThreadCreated), threadChannel).ConfigureAwait(false); | |||||
} | } | ||||
} | } | ||||
break; | break; | ||||
case "THREAD_UPDATE": | case "THREAD_UPDATE": | ||||
{ | { | ||||
try | |||||
{ | |||||
await _gatewayLogger.DebugAsync("Received Dispatch (THREAD_UPDATE)").ConfigureAwait(false); | |||||
var data = (payload as JToken).ToObject<API.Channel>(_serializer); | |||||
var guild = State.GetGuild(data.GuildId.Value); | |||||
if (guild == null) | |||||
{ | |||||
await UnknownGuildAsync(type, data.GuildId.Value); | |||||
return; | |||||
} | |||||
await _gatewayLogger.DebugAsync("Received Dispatch (THREAD_UPDATE)").ConfigureAwait(false); | |||||
var channel = (SocketThreadChannel)guild.GetChannel(data.Id); | |||||
var data = (payload as JToken).ToObject<API.Channel>(_serializer); | |||||
var guild = State.GetGuild(data.GuildId.Value); | |||||
if (guild == null) | |||||
{ | |||||
await UnknownGuildAsync(type, data.GuildId.Value); | |||||
return; | |||||
} | |||||
var before = channel.Clone(); | |||||
channel.Update(State, data); | |||||
var channel = (SocketThreadChannel)guild.GetChannel(data.Id); | |||||
if (!(guild?.IsSynced ?? true)) | |||||
{ | |||||
await UnsyncedGuildAsync(type, guild.Id).ConfigureAwait(false); | |||||
return; | |||||
} | |||||
var before = channel.Clone(); | |||||
channel.Update(State, data); | |||||
await TimedInvokeAsync(_threadUpdated, nameof(ThreadUpdated), before, channel).ConfigureAwait(false); | |||||
} | |||||
catch(Exception x) | |||||
if (!(guild?.IsSynced ?? true)) | |||||
{ | { | ||||
await UnsyncedGuildAsync(type, guild.Id).ConfigureAwait(false); | |||||
return; | |||||
} | } | ||||
await TimedInvokeAsync(_threadUpdated, nameof(ThreadUpdated), before, channel).ConfigureAwait(false); | |||||
} | } | ||||
break; | break; | ||||
case "THREAD_DELETE": | case "THREAD_DELETE": | ||||
@@ -2075,19 +2070,30 @@ namespace Discord.WebSocket | |||||
if(entity == null) | if(entity == null) | ||||
{ | { | ||||
guild.AddChannel(this.State, thread); | |||||
entity = (SocketThreadChannel)guild.AddChannel(this.State, thread); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
entity.Update(this.State, thread); | entity.Update(this.State, thread); | ||||
} | } | ||||
foreach(var member in data.Members.Where(x => x.Id.Value == entity.Id)) | |||||
{ | |||||
var guildMember = guild.GetUser(member.Id.Value); | |||||
entity.AddOrUpdateThreadMember(member, guildMember); | |||||
} | |||||
} | } | ||||
} | } | ||||
break; | break; | ||||
case "THREAD_MEMBER_UPDATE": | case "THREAD_MEMBER_UPDATE": | ||||
{ | { | ||||
await _gatewayLogger.DebugAsync("Received Dispatch (THREAD_MEMBER_UPDATE)").ConfigureAwait(false); | await _gatewayLogger.DebugAsync("Received Dispatch (THREAD_MEMBER_UPDATE)").ConfigureAwait(false); | ||||
var p = payload; | |||||
var data = (payload as JToken).ToObject<ThreadMember>(_serializer); | |||||
//var guild = State.GetGuild(data.) | |||||
} | } | ||||
break; | break; | ||||
@@ -2097,6 +2103,69 @@ namespace Discord.WebSocket | |||||
var data = (payload as JToken).ToObject<ThreadMembersUpdated>(_serializer); | var data = (payload as JToken).ToObject<ThreadMembersUpdated>(_serializer); | ||||
var guild = State.GetGuild(data.GuildId); | |||||
if (guild == null) | |||||
{ | |||||
await UnknownGuildAsync(type, data.GuildId).ConfigureAwait(false); | |||||
return; | |||||
} | |||||
var thread = (SocketThreadChannel)guild.GetChannel(data.Id); | |||||
if(thread == null) | |||||
{ | |||||
await UnknownChannelAsync(type, data.Id); | |||||
return; | |||||
} | |||||
IReadOnlyCollection<SocketThreadUser> leftUsers = null; | |||||
IReadOnlyCollection<SocketThreadUser> joinUsers = null; | |||||
if (data.RemovedMemberIds.IsSpecified) | |||||
{ | |||||
leftUsers = thread.RemoveUsers(data.RemovedMemberIds.Value); | |||||
} | |||||
if (data.AddedMembers.IsSpecified) | |||||
{ | |||||
List<SocketThreadUser> newThreadMembers = new List<SocketThreadUser>(); | |||||
foreach(var threadMember in data.AddedMembers.Value) | |||||
{ | |||||
SocketGuildUser guildMember; | |||||
if (threadMember.Member.IsSpecified) | |||||
{ | |||||
guildMember = guild.AddOrUpdateUser(threadMember.Member.Value); | |||||
} | |||||
else | |||||
{ | |||||
guildMember = guild.GetUser(threadMember.UserId.Value); | |||||
} | |||||
newThreadMembers.Add(thread.AddOrUpdateThreadMember(threadMember, guildMember)); | |||||
} | |||||
if (newThreadMembers.Any()) | |||||
joinUsers = newThreadMembers.ToImmutableArray(); | |||||
} | |||||
if (leftUsers != null) | |||||
{ | |||||
foreach(var threadUser in leftUsers) | |||||
{ | |||||
await TimedInvokeAsync(_threadMemberLeft, nameof(ThreadMemberLeft), threadUser).ConfigureAwait(false); | |||||
} | |||||
} | |||||
if(joinUsers != null) | |||||
{ | |||||
foreach(var threadUser in joinUsers) | |||||
{ | |||||
await TimedInvokeAsync(_threadMemberJoined, nameof(ThreadMemberJoined), threadUser).ConfigureAwait(false); | |||||
} | |||||
} | |||||
} | } | ||||
break; | break; | ||||
@@ -2138,6 +2207,7 @@ namespace Discord.WebSocket | |||||
catch (Exception ex) | catch (Exception ex) | ||||
{ | { | ||||
await _gatewayLogger.ErrorAsync($"Error handling {opCode}{(type != null ? $" ({type})" : "")}", ex).ConfigureAwait(false); | await _gatewayLogger.ErrorAsync($"Error handling {opCode}{(type != null ? $" ({type})" : "")}", ex).ConfigureAwait(false); | ||||
Console.WriteLine(ex); | |||||
} | } | ||||
} | } | ||||
@@ -70,6 +70,7 @@ namespace Discord.WebSocket | |||||
{ | { | ||||
case SocketDMChannel dmChannel: dmChannel.AddMessage(msg); break; | case SocketDMChannel dmChannel: dmChannel.AddMessage(msg); break; | ||||
case SocketGroupChannel groupChannel: groupChannel.AddMessage(msg); break; | case SocketGroupChannel groupChannel: groupChannel.AddMessage(msg); break; | ||||
case SocketThreadChannel threadChannel: threadChannel.AddMessage(msg); break; | |||||
case SocketTextChannel textChannel: textChannel.AddMessage(msg); break; | case SocketTextChannel textChannel: textChannel.AddMessage(msg); break; | ||||
default: throw new NotSupportedException($"Unexpected {nameof(ISocketMessageChannel)} type."); | default: throw new NotSupportedException($"Unexpected {nameof(ISocketMessageChannel)} type."); | ||||
} | } | ||||
@@ -78,9 +78,46 @@ namespace Discord.WebSocket | |||||
} | } | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public Task ModifyAsync(Action<TextChannelProperties> func, RequestOptions options = null) | |||||
public virtual Task ModifyAsync(Action<TextChannelProperties> func, RequestOptions options = null) | |||||
=> ChannelHelper.ModifyAsync(this, Discord, func, options); | => ChannelHelper.ModifyAsync(this, Discord, func, options); | ||||
/// <summary> | |||||
/// Creates a thread within this <see cref="ITextChannel"/>. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// When <paramref name="message"/> is <see langword="null"/> the thread type will be based off of the | |||||
/// channel its created in. When called on a <see cref="ITextChannel"/>, it creates a <see cref="ThreadType.PublicThread"/>. | |||||
/// When called on a <see cref="INewsChannel"/>, it creates a <see cref="ThreadType.NewsThread"/>. The id of the created | |||||
/// thread will be the same as the id of the message, and as such a message can only have a | |||||
/// single thread created from it. | |||||
/// </remarks> | |||||
/// <param name="name">The name of the thread.</param> | |||||
/// <param name="type"> | |||||
/// The type of the thread. | |||||
/// <para> | |||||
/// <b>Note: </b>This parameter is not used if the <paramref name="message"/> parameter is not specified. | |||||
/// </para> | |||||
/// </param> | |||||
/// <param name="autoArchiveDuration"> | |||||
/// The duration on which this thread archives after. | |||||
/// <para> | |||||
/// <b>Note: </b> Options <see cref="ThreadArchiveDuration.OneWeek"/> and <see cref="ThreadArchiveDuration.ThreeDays"/> | |||||
/// are only available for guilds that are boosted. You can check in the <see cref="IGuild.Features"/> to see if the | |||||
/// guild has the <b>THREE_DAY_THREAD_ARCHIVE</b> and <b>SEVEN_DAY_THREAD_ARCHIVE</b>. | |||||
/// </para> | |||||
/// </param> | |||||
/// <param name="message">The message which to start the thread from.</param> | |||||
/// <param name="options">The options to be used when sending the request.</param> | |||||
/// <returns> | |||||
/// A task that represents the asynchronous create operation. The task result contains a <see cref="IThreadChannel"/> | |||||
/// </returns> | |||||
public async Task<SocketThreadChannel> CreateThreadAsync(string name, ThreadType type = ThreadType.PublicThread, | |||||
ThreadArchiveDuration autoArchiveDuration = ThreadArchiveDuration.OneDay, IMessage message = null, RequestOptions options = null) | |||||
{ | |||||
var model = await ThreadHelper.CreateThreadAsync(Discord, this, name, type, autoArchiveDuration, message, options); | |||||
return SocketThreadChannel.Create(this.Guild, Discord.State, model); | |||||
} | |||||
//Messages | //Messages | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public SocketMessage GetCachedMessage(ulong id) | public SocketMessage GetCachedMessage(ulong id) | ||||
@@ -235,7 +272,7 @@ namespace Discord.WebSocket | |||||
/// A task that represents the asynchronous creation operation. The task result contains the newly created | /// A task that represents the asynchronous creation operation. The task result contains the newly created | ||||
/// webhook. | /// webhook. | ||||
/// </returns> | /// </returns> | ||||
public Task<RestWebhook> CreateWebhookAsync(string name, Stream avatar = null, RequestOptions options = null) | |||||
public virtual Task<RestWebhook> CreateWebhookAsync(string name, Stream avatar = null, RequestOptions options = null) | |||||
=> ChannelHelper.CreateWebhookAsync(this, Discord, name, avatar, options); | => ChannelHelper.CreateWebhookAsync(this, Discord, name, avatar, options); | ||||
/// <summary> | /// <summary> | ||||
/// Gets a webhook available in this text channel. | /// Gets a webhook available in this text channel. | ||||
@@ -246,7 +283,7 @@ namespace Discord.WebSocket | |||||
/// A task that represents the asynchronous get operation. The task result contains a webhook associated | /// A task that represents the asynchronous get operation. The task result contains a webhook associated | ||||
/// with the identifier; <c>null</c> if the webhook is not found. | /// with the identifier; <c>null</c> if the webhook is not found. | ||||
/// </returns> | /// </returns> | ||||
public Task<RestWebhook> GetWebhookAsync(ulong id, RequestOptions options = null) | |||||
public virtual Task<RestWebhook> GetWebhookAsync(ulong id, RequestOptions options = null) | |||||
=> ChannelHelper.GetWebhookAsync(this, Discord, id, options); | => ChannelHelper.GetWebhookAsync(this, Discord, id, options); | ||||
/// <summary> | /// <summary> | ||||
/// Gets the webhooks available in this text channel. | /// Gets the webhooks available in this text channel. | ||||
@@ -256,21 +293,21 @@ namespace Discord.WebSocket | |||||
/// A task that represents the asynchronous get operation. The task result contains a read-only collection | /// A task that represents the asynchronous get operation. The task result contains a read-only collection | ||||
/// of webhooks that is available in this channel. | /// of webhooks that is available in this channel. | ||||
/// </returns> | /// </returns> | ||||
public Task<IReadOnlyCollection<RestWebhook>> GetWebhooksAsync(RequestOptions options = null) | |||||
public virtual Task<IReadOnlyCollection<RestWebhook>> GetWebhooksAsync(RequestOptions options = null) | |||||
=> ChannelHelper.GetWebhooksAsync(this, Discord, options); | => ChannelHelper.GetWebhooksAsync(this, Discord, options); | ||||
//Invites | //Invites | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public async Task<IInviteMetadata> CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) | |||||
public virtual async Task<IInviteMetadata> CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) | |||||
=> await ChannelHelper.CreateInviteAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, options).ConfigureAwait(false); | => await ChannelHelper.CreateInviteAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, options).ConfigureAwait(false); | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public async Task<IInviteMetadata> CreateInviteToApplicationAsync(ulong applicationId, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) | |||||
public virtual async Task<IInviteMetadata> CreateInviteToApplicationAsync(ulong applicationId, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) | |||||
=> await ChannelHelper.CreateInviteToApplicationAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, applicationId, options).ConfigureAwait(false); | => await ChannelHelper.CreateInviteToApplicationAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, applicationId, options).ConfigureAwait(false); | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public async Task<IInviteMetadata> CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) | |||||
public virtual async Task<IInviteMetadata> CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null) | |||||
=> await ChannelHelper.CreateInviteToStreamAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, user, options).ConfigureAwait(false); | => await ChannelHelper.CreateInviteToStreamAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, user, options).ConfigureAwait(false); | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public async Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync(RequestOptions options = null) | |||||
public virtual async Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync(RequestOptions options = null) | |||||
=> await ChannelHelper.GetInvitesAsync(this, Discord, options).ConfigureAwait(false); | => await ChannelHelper.GetInvitesAsync(this, Discord, options).ConfigureAwait(false); | ||||
private string DebuggerDisplay => $"{Name} ({Id}, Text)"; | private string DebuggerDisplay => $"{Name} ({Id}, Text)"; | ||||
@@ -286,6 +323,9 @@ namespace Discord.WebSocket | |||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
async Task<IReadOnlyCollection<IWebhook>> ITextChannel.GetWebhooksAsync(RequestOptions options) | async Task<IReadOnlyCollection<IWebhook>> ITextChannel.GetWebhooksAsync(RequestOptions options) | ||||
=> await GetWebhooksAsync(options).ConfigureAwait(false); | => await GetWebhooksAsync(options).ConfigureAwait(false); | ||||
/// <inheritdoc /> | |||||
async Task<IThreadChannel> ITextChannel.CreateThreadAsync(string name, ThreadType type, ThreadArchiveDuration autoArchiveDuration, IMessage message, RequestOptions options) | |||||
=> await CreateThreadAsync(name, type, autoArchiveDuration, message, options); | |||||
//IGuildChannel | //IGuildChannel | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
@@ -9,6 +9,8 @@ using System.Text; | |||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
using Model = Discord.API.Channel; | using Model = Discord.API.Channel; | ||||
using ThreadMember = Discord.API.ThreadMember; | using ThreadMember = Discord.API.ThreadMember; | ||||
using MemberUpdates = Discord.API.Gateway.ThreadMembersUpdated; | |||||
using System.Collections.Concurrent; | |||||
namespace Discord.WebSocket | namespace Discord.WebSocket | ||||
{ | { | ||||
@@ -16,8 +18,21 @@ namespace Discord.WebSocket | |||||
/// Represents a thread channel inside of a guild. | /// Represents a thread channel inside of a guild. | ||||
/// </summary> | /// </summary> | ||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | ||||
public class SocketThreadChannel : SocketGuildChannel, IThreadChannel, ISocketMessageChannel | |||||
public class SocketThreadChannel : SocketTextChannel, IThreadChannel | |||||
{ | { | ||||
/// <inheritdoc/> | |||||
public ThreadType Type { get; private set; } | |||||
/// <summary> | |||||
/// Gets the owner of the current thread. | |||||
/// </summary> | |||||
public SocketThreadUser Owner { get; private set; } | |||||
/// <summary> | |||||
/// Gets the current users within this thread. | |||||
/// </summary> | |||||
public SocketThreadUser CurrentUser | |||||
=> Users.FirstOrDefault(x => x.Id == Discord.CurrentUser.Id); | |||||
/// <inheritdoc/> | /// <inheritdoc/> | ||||
public bool Joined { get; private set; } | public bool Joined { get; private set; } | ||||
@@ -25,7 +40,8 @@ namespace Discord.WebSocket | |||||
/// <summary> | /// <summary> | ||||
/// <see langword="true"/> if this thread is private, otherwise <see langword="false"/> | /// <see langword="true"/> if this thread is private, otherwise <see langword="false"/> | ||||
/// </summary> | /// </summary> | ||||
public bool IsPrivateThread { get; private set; } | |||||
public bool IsPrivateThread | |||||
=> this.Type == ThreadType.PrivateThread; | |||||
/// <summary> | /// <summary> | ||||
/// Gets the parent channel this thread resides in. | /// Gets the parent channel this thread resides in. | ||||
@@ -50,37 +66,29 @@ namespace Discord.WebSocket | |||||
/// <inheritdoc/> | /// <inheritdoc/> | ||||
public bool Locked { get; private set; } | public bool Locked { get; private set; } | ||||
/// <inheritdoc/> | |||||
public bool IsNsfw { get; private set; } | |||||
/// <inheritdoc/> | |||||
public string Topic { get; private set; } | |||||
/// <inheritdoc/> | |||||
public int SlowModeInterval { get; private set; } | |||||
/// <inheritdoc/> | |||||
public string Mention { get; private set; } | |||||
/// <summary> | |||||
/// Gets a collection of cached users within this thread. | |||||
/// </summary> | |||||
public new IReadOnlyCollection<SocketThreadUser> Users => | |||||
_members.Values.ToImmutableArray(); | |||||
/// <inheritdoc/> | |||||
public ulong? CategoryId { get; private set; } | |||||
/// <inheritdoc /> | |||||
public IReadOnlyCollection<SocketMessage> CachedMessages => _messages?.Messages ?? ImmutableArray.Create<SocketMessage>(); | |||||
private ConcurrentDictionary<ulong, SocketThreadUser> _members; | |||||
public new IReadOnlyCollection<SocketThreadUser> Users = ImmutableArray.Create<SocketThreadUser>(); | |||||
private string DebuggerDisplay => $"{Name} ({Id}, Thread)"; | |||||
private readonly MessageCache _messages; | |||||
private bool _usersDownloaded = false; | |||||
private string DebuggerDisplay => $"{Name} ({Id}, Thread)"; | |||||
private object _downloadLock = new object(); | |||||
internal SocketThreadChannel(DiscordSocketClient discord, SocketGuild guild, ulong id, SocketTextChannel parent) | internal SocketThreadChannel(DiscordSocketClient discord, SocketGuild guild, ulong id, SocketTextChannel parent) | ||||
: base(discord, id, guild) | : base(discord, id, guild) | ||||
{ | { | ||||
this.ParentChannel = parent; | this.ParentChannel = parent; | ||||
this._members = new ConcurrentDictionary<ulong, SocketThreadUser>(); | |||||
} | } | ||||
internal static SocketThreadChannel Create(SocketGuild guild, ClientState state, Model model) | |||||
internal new static SocketThreadChannel Create(SocketGuild guild, ClientState state, Model model) | |||||
{ | { | ||||
var parent = (SocketTextChannel)guild.GetChannel(model.CategoryId.Value); | var parent = (SocketTextChannel)guild.GetChannel(model.CategoryId.Value); | ||||
var entity = new SocketThreadChannel(guild.Discord, guild, model.Id, parent); | var entity = new SocketThreadChannel(guild.Discord, guild, model.Id, parent); | ||||
@@ -92,10 +100,9 @@ namespace Discord.WebSocket | |||||
{ | { | ||||
base.Update(state, model); | base.Update(state, model); | ||||
this.Type = (ThreadType)model.Type; | |||||
this.MessageCount = model.MessageCount.GetValueOrDefault(-1); | this.MessageCount = model.MessageCount.GetValueOrDefault(-1); | ||||
this.MemberCount = model.MemberCount.GetValueOrDefault(-1); | this.MemberCount = model.MemberCount.GetValueOrDefault(-1); | ||||
this.IsPrivateThread = model.Type == ChannelType.PrivateThread; | |||||
if (model.ThreadMetadata.IsSpecified) | if (model.ThreadMetadata.IsSpecified) | ||||
{ | { | ||||
@@ -104,259 +111,233 @@ namespace Discord.WebSocket | |||||
this.AutoArchiveDuration = (ThreadArchiveDuration)model.ThreadMetadata.Value.AutoArchiveDuration; | this.AutoArchiveDuration = (ThreadArchiveDuration)model.ThreadMetadata.Value.AutoArchiveDuration; | ||||
this.Locked = model.ThreadMetadata.Value.Locked.GetValueOrDefault(false); | this.Locked = model.ThreadMetadata.Value.Locked.GetValueOrDefault(false); | ||||
} | } | ||||
if (model.OwnerId.IsSpecified) | |||||
{ | |||||
this.Owner = GetUser(model.OwnerId.Value); | |||||
} | |||||
this.Joined = model.ThreadMember.IsSpecified; | |||||
} | } | ||||
internal void Update(ClientState state, ThreadMember self) | |||||
internal IReadOnlyCollection<SocketThreadUser> RemoveUsers(ulong[] users) | |||||
{ | { | ||||
List<SocketThreadUser> threadUsers = new(); | |||||
} | |||||
foreach (var userId in users) | |||||
{ | |||||
if (_members.TryRemove(userId, out var user)) | |||||
threadUsers.Add(user); | |||||
} | |||||
/// <inheritdoc /> | |||||
public virtual Task SyncPermissionsAsync(RequestOptions options = null) | |||||
=> ChannelHelper.SyncPermissionsAsync(this, Discord, options); | |||||
return threadUsers.ToImmutableArray(); | |||||
} | |||||
/// <inheritdoc /> | |||||
public Task ModifyAsync(Action<TextChannelProperties> func, RequestOptions options = null) | |||||
=> ChannelHelper.ModifyAsync(this, Discord, func, options); | |||||
internal SocketThreadUser AddOrUpdateThreadMember(ThreadMember model, SocketGuildUser guildMember) | |||||
{ | |||||
if (_members.TryGetValue(model.UserId.Value, out SocketThreadUser member)) | |||||
member.Update(model); | |||||
else | |||||
{ | |||||
member = SocketThreadUser.Create(this.Guild, this, model, guildMember); | |||||
member.GlobalUser.AddRef(); | |||||
_members[member.Id] = member; | |||||
} | |||||
return member; | |||||
} | |||||
//Messages | |||||
//Users | |||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public SocketMessage GetCachedMessage(ulong id) | |||||
=> _messages?.Get(id); | |||||
public new SocketThreadUser GetUser(ulong id) | |||||
{ | |||||
var user = Users.FirstOrDefault(x => x.Id == id); | |||||
return user; | |||||
} | |||||
/// <summary> | /// <summary> | ||||
/// Gets a message from this message channel. | |||||
/// Gets all users inside this thread. | |||||
/// </summary> | /// </summary> | ||||
/// <remarks> | /// <remarks> | ||||
/// This method follows the same behavior as described in <see cref="IMessageChannel.GetMessageAsync"/>. | |||||
/// Please visit its documentation for more details on this method. | |||||
/// If all users are not downloaded then this method will call <see cref="DownloadUsersAsync(RequestOptions)"/> and return the result. | |||||
/// </remarks> | /// </remarks> | ||||
/// <param name="id">The snowflake identifier of the message.</param> | |||||
/// <param name="options">The options to be used when sending the request.</param> | /// <param name="options">The options to be used when sending the request.</param> | ||||
/// <returns> | |||||
/// A task that represents an asynchronous get operation for retrieving the message. The task result contains | |||||
/// the retrieved message; <c>null</c> if no message is found with the specified identifier. | |||||
/// </returns> | |||||
public async Task<IMessage> GetMessageAsync(ulong id, RequestOptions options = null) | |||||
/// <returns>A task representing the download operation.</returns> | |||||
public async Task<IReadOnlyCollection<SocketThreadUser>> GetUsersAsync(RequestOptions options = null) | |||||
{ | { | ||||
IMessage msg = _messages?.Get(id); | |||||
if (msg == null) | |||||
msg = await ChannelHelper.GetMessageAsync(this, Discord, id, options).ConfigureAwait(false); | |||||
return msg; | |||||
// download all users if we havent | |||||
if (!_usersDownloaded) | |||||
{ | |||||
await DownloadUsersAsync(options); | |||||
this._usersDownloaded = true; | |||||
} | |||||
return this.Users; | |||||
} | } | ||||
/// <summary> | /// <summary> | ||||
/// Gets the last N messages from this message channel. | |||||
/// Downloads all users that have access to this thread. | |||||
/// </summary> | /// </summary> | ||||
/// <remarks> | |||||
/// This method follows the same behavior as described in <see cref="IMessageChannel.GetMessagesAsync(int, CacheMode, RequestOptions)"/>. | |||||
/// Please visit its documentation for more details on this method. | |||||
/// </remarks> | |||||
/// <param name="limit">The numbers of message to be gotten from.</param> | |||||
/// <param name="options">The options to be used when sending the request.</param> | /// <param name="options">The options to be used when sending the request.</param> | ||||
/// <returns> | |||||
/// Paged collection of messages. | |||||
/// </returns> | |||||
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) | |||||
=> SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, null, Direction.Before, limit, CacheMode.AllowDownload, options); | |||||
/// <returns>A task representing the asyncronous download operation.</returns> | |||||
public async Task DownloadUsersAsync(RequestOptions options = null) | |||||
{ | |||||
var users = await Discord.ApiClient.ListThreadMembersAsync(this.Id, options); | |||||
lock (_downloadLock) | |||||
{ | |||||
foreach (var threadMember in users) | |||||
{ | |||||
var guildUser = this.Guild.GetUser(threadMember.UserId.Value); | |||||
this.AddOrUpdateThreadMember(threadMember, guildUser); | |||||
} | |||||
} | |||||
} | |||||
internal new SocketThreadChannel Clone() => MemberwiseClone() as SocketThreadChannel; | |||||
/// <inheritdoc/> | |||||
public Task JoinAsync(RequestOptions options = null) | |||||
=> Discord.ApiClient.JoinThreadAsync(this.Id, options); | |||||
/// <inheritdoc/> | |||||
public Task LeaveAsync(RequestOptions options = null) | |||||
=> Discord.ApiClient.LeaveThreadAsync(this.Id, options); | |||||
/// <summary> | /// <summary> | ||||
/// Gets a collection of messages in this channel. | |||||
/// Adds a user to this thread. | |||||
/// </summary> | /// </summary> | ||||
/// <remarks> | |||||
/// This method follows the same behavior as described in <see cref="IMessageChannel.GetMessagesAsync(ulong, Direction, int, CacheMode, RequestOptions)"/>. | |||||
/// Please visit its documentation for more details on this method. | |||||
/// </remarks> | |||||
/// <param name="fromMessageId">The ID of the starting message to get the messages from.</param> | |||||
/// <param name="dir">The direction of the messages to be gotten from.</param> | |||||
/// <param name="limit">The numbers of message to be gotten from.</param> | |||||
/// <param name="user">The <see cref="IGuildUser"/> to add.</param> | |||||
/// <param name="options">The options to be used when sending the request.</param> | /// <param name="options">The options to be used when sending the request.</param> | ||||
/// <returns> | /// <returns> | ||||
/// Paged collection of messages. | |||||
/// A task that represents the asynchronous operation of adding a member to a thread. | |||||
/// </returns> | /// </returns> | ||||
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) | |||||
=> SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessageId, dir, limit, CacheMode.AllowDownload, options); | |||||
public Task AddUserAsync(IGuildUser user, RequestOptions options = null) | |||||
=> Discord.ApiClient.AddThreadMemberAsync(this.Id, user.Id, options); | |||||
/// <summary> | /// <summary> | ||||
/// Gets a collection of messages in this channel. | |||||
/// Removes a user from this thread. | |||||
/// </summary> | /// </summary> | ||||
/// <remarks> | |||||
/// This method follows the same behavior as described in <see cref="IMessageChannel.GetMessagesAsync(IMessage, Direction, int, CacheMode, RequestOptions)"/>. | |||||
/// Please visit its documentation for more details on this method. | |||||
/// </remarks> | |||||
/// <param name="fromMessage">The starting message to get the messages from.</param> | |||||
/// <param name="dir">The direction of the messages to be gotten from.</param> | |||||
/// <param name="limit">The numbers of message to be gotten from.</param> | |||||
/// <param name="user">The <see cref="IGuildUser"/> to remove from this thread.</param> | |||||
/// <param name="options">The options to be used when sending the request.</param> | /// <param name="options">The options to be used when sending the request.</param> | ||||
/// <returns> | /// <returns> | ||||
/// Paged collection of messages. | |||||
/// A task that represents the asynchronous operation of removing a user from this thread. | |||||
/// </returns> | /// </returns> | ||||
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) | |||||
=> SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessage.Id, dir, limit, CacheMode.AllowDownload, options); | |||||
/// <inheritdoc /> | |||||
public IReadOnlyCollection<SocketMessage> GetCachedMessages(int limit = DiscordConfig.MaxMessagesPerBatch) | |||||
=> SocketChannelHelper.GetCachedMessages(this, Discord, _messages, null, Direction.Before, limit); | |||||
/// <inheritdoc /> | |||||
public IReadOnlyCollection<SocketMessage> GetCachedMessages(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch) | |||||
=> SocketChannelHelper.GetCachedMessages(this, Discord, _messages, fromMessageId, dir, limit); | |||||
/// <inheritdoc /> | |||||
public IReadOnlyCollection<SocketMessage> GetCachedMessages(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch) | |||||
=> SocketChannelHelper.GetCachedMessages(this, Discord, _messages, fromMessage.Id, dir, limit); | |||||
/// <inheritdoc /> | |||||
public Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(RequestOptions options = null) | |||||
=> ChannelHelper.GetPinnedMessagesAsync(this, Discord, options); | |||||
/// <inheritdoc /> | |||||
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> | |||||
public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null) | |||||
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference, component, options); | |||||
public Task RemoveUserAsync(IGuildUser user, RequestOptions options = null) | |||||
=> Discord.ApiClient.RemoveThreadMemberAsync(this.Id, user.Id, options); | |||||
/// <inheritdoc /> | |||||
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null) | |||||
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, allowedMentions, messageReference, component, options, isSpoiler); | |||||
/// <inheritdoc /> | |||||
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> | |||||
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null) | |||||
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions, messageReference, component, options, isSpoiler); | |||||
/// <inheritdoc /> | |||||
public Task DeleteMessagesAsync(IEnumerable<IMessage> messages, RequestOptions options = null) | |||||
=> ChannelHelper.DeleteMessagesAsync(this, Discord, messages.Select(x => x.Id), options); | |||||
/// <inheritdoc /> | |||||
public Task DeleteMessagesAsync(IEnumerable<ulong> messageIds, RequestOptions options = null) | |||||
=> ChannelHelper.DeleteMessagesAsync(this, Discord, messageIds, options); | |||||
/// <inheritdoc /> | |||||
public async Task<IUserMessage> ModifyMessageAsync(ulong messageId, Action<MessageProperties> func, RequestOptions options = null) | |||||
=> await ChannelHelper.ModifyMessageAsync(this, messageId, func, Discord, options).ConfigureAwait(false); | |||||
/// <inheritdoc /> | |||||
public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null) | |||||
=> ChannelHelper.DeleteMessageAsync(this, messageId, Discord, options); | |||||
/// <inheritdoc /> | |||||
public Task DeleteMessageAsync(IMessage message, RequestOptions options = null) | |||||
=> ChannelHelper.DeleteMessageAsync(this, message.Id, Discord, options); | |||||
/// <inheritdoc /> | |||||
public Task TriggerTypingAsync(RequestOptions options = null) | |||||
=> ChannelHelper.TriggerTypingAsync(this, Discord, options); | |||||
/// <inheritdoc /> | |||||
public IDisposable EnterTypingState(RequestOptions options = null) | |||||
=> ChannelHelper.EnterTypingState(this, Discord, options); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task AddPermissionOverwriteAsync(IRole role, OverwritePermissions permissions, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
internal void AddMessage(SocketMessage msg) | |||||
=> _messages?.Add(msg); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task AddPermissionOverwriteAsync(IUser user, OverwritePermissions permissions, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
internal SocketMessage RemoveMessage(ulong id) | |||||
=> _messages?.Remove(id); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task<IInviteMetadata> CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
//Users | |||||
/// <inheritdoc /> | |||||
public new SocketThreadUser GetUser(ulong id) | |||||
{ | |||||
var user = Users.FirstOrDefault(x => x.Id == id); | |||||
return user; | |||||
} | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task<IInviteMetadata> CreateInviteToApplicationAsync(ulong applicationId, int? maxAge, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
public Task GetUsersAsync() | |||||
{ | |||||
return Task.CompletedTask; | |||||
} | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task<IInviteMetadata> CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
internal new SocketThreadChannel Clone() => MemberwiseClone() as SocketThreadChannel; | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task<RestWebhook> CreateWebhookAsync(string name, Stream avatar = null, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
//ITextChannel | |||||
/// <inheritdoc /> | |||||
Task<IWebhook> ITextChannel.CreateWebhookAsync(string name, Stream avatar, RequestOptions options) | |||||
=> throw new NotSupportedException("Thread channels don't support webhooks"); | |||||
/// <inheritdoc /> | |||||
Task<IWebhook> ITextChannel.GetWebhookAsync(ulong id, RequestOptions options) | |||||
=> throw new NotSupportedException("Thread channels don't support webhooks"); | |||||
/// <inheritdoc /> | |||||
Task<IReadOnlyCollection<IWebhook>> ITextChannel.GetWebhooksAsync(RequestOptions options) | |||||
=> throw new NotSupportedException("Thread channels don't support webhooks"); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync(RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
//IGuildChannel | |||||
/// <inheritdoc /> | |||||
Task<IGuildUser> IGuildChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | |||||
=> Task.FromResult<IGuildUser>(GetUser(id)); | |||||
/// <inheritdoc /> | |||||
IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | |||||
=> ImmutableArray.Create<IReadOnlyCollection<IGuildUser>>(Users).ToAsyncEnumerable(); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override OverwritePermissions? GetPermissionOverwrite(IRole role) | |||||
=> throw new NotImplementedException(); | |||||
//IMessageChannel | |||||
/// <inheritdoc /> | |||||
async Task<IMessage> IMessageChannel.GetMessageAsync(ulong id, CacheMode mode, RequestOptions options) | |||||
{ | |||||
if (mode == CacheMode.AllowDownload) | |||||
return await GetMessageAsync(id, options).ConfigureAwait(false); | |||||
else | |||||
return GetCachedMessage(id); | |||||
} | |||||
/// <inheritdoc /> | |||||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(int limit, CacheMode mode, RequestOptions options) | |||||
=> SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, null, Direction.Before, limit, mode, options); | |||||
/// <inheritdoc /> | |||||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(ulong fromMessageId, Direction dir, int limit, CacheMode mode, RequestOptions options) | |||||
=> SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessageId, dir, limit, mode, options); | |||||
/// <inheritdoc /> | |||||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(IMessage fromMessage, Direction dir, int limit, CacheMode mode, RequestOptions options) | |||||
=> SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessage.Id, dir, limit, mode, options); | |||||
/// <inheritdoc /> | |||||
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options) | |||||
=> await GetPinnedMessagesAsync(options).ConfigureAwait(false); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override OverwritePermissions? GetPermissionOverwrite(IUser user) | |||||
=> throw new NotImplementedException(); | |||||
/// <inheritdoc /> | |||||
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent component) | |||||
=> await SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, component).ConfigureAwait(false); | |||||
/// <inheritdoc /> | |||||
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent component) | |||||
=> await SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, component).ConfigureAwait(false); | |||||
/// <inheritdoc /> | |||||
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent component) | |||||
=> await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, component).ConfigureAwait(false); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task<RestWebhook> GetWebhookAsync(ulong id, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
// INestedChannel | |||||
/// <inheritdoc /> | |||||
Task<ICategoryChannel> INestedChannel.GetCategoryAsync(CacheMode mode, RequestOptions options) | |||||
=> Task.FromResult(this.ParentChannel.Category); | |||||
Task<IInviteMetadata> INestedChannel.CreateInviteAsync(int? maxAge, int? maxUses, bool isTemporary, bool isUnique, RequestOptions options) | |||||
=> throw new NotSupportedException("Thread channels don't support invites"); | |||||
Task<IInviteMetadata> INestedChannel.CreateInviteToApplicationAsync(ulong applicationId, int? maxAge, int? maxUses, bool isTemporary, bool isUnique, RequestOptions options) | |||||
=> throw new NotSupportedException("Thread channels don't support invites"); | |||||
Task<IInviteMetadata> INestedChannel.CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses, bool isTemporary, bool isUnique, RequestOptions options) | |||||
=> throw new NotSupportedException("Thread channels don't support invites"); | |||||
Task<IReadOnlyCollection<IInviteMetadata>> INestedChannel.GetInvitesAsync(RequestOptions options) | |||||
=> throw new NotSupportedException("Thread channels don't support invites"); | |||||
public Task JoinAsync() | |||||
{ | |||||
return Task.CompletedTask; | |||||
} | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task<IReadOnlyCollection<RestWebhook>> GetWebhooksAsync(RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
public Task LeaveAsync() | |||||
{ | |||||
return Task.CompletedTask; | |||||
} | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task ModifyAsync(Action<TextChannelProperties> func, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
public Task AddThreadMember(IGuildUser user) | |||||
{ | |||||
return Task.CompletedTask; | |||||
} | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task RemovePermissionOverwriteAsync(IRole role, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
public Task RemoveThreadMember(IGuildUser user) | |||||
{ | |||||
return Task.CompletedTask; | |||||
} | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task RemovePermissionOverwriteAsync(IUser user, RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override IReadOnlyCollection<Overwrite> PermissionOverwrites | |||||
=> throw new NotImplementedException(); | |||||
/// <inheritdoc/> | |||||
/// <remarks> | |||||
/// <b>This method is not supported in threads.</b> | |||||
/// </remarks> | |||||
public override Task SyncPermissionsAsync(RequestOptions options = null) | |||||
=> throw new NotImplementedException(); | |||||
} | } | ||||
} | } |
@@ -387,7 +387,15 @@ namespace Discord.WebSocket | |||||
state.AddChannel(channel); | state.AddChannel(channel); | ||||
channels.TryAdd(channel.Id); | channels.TryAdd(channel.Id); | ||||
} | } | ||||
for(int i = 0; i < model.Threads.Length; i++) | |||||
{ | |||||
var threadChannel = SocketThreadChannel.Create(this, state, model.Threads[i]); | |||||
state.AddChannel(threadChannel); | |||||
channels.TryAdd(threadChannel.Id); | |||||
} | |||||
} | } | ||||
_channels = channels; | _channels = channels; | ||||
var members = new ConcurrentDictionary<ulong, SocketGuildUser>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(model.Members.Length * 1.05)); | var members = new ConcurrentDictionary<ulong, SocketGuildUser>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(model.Members.Length * 1.05)); | ||||
@@ -10,7 +10,10 @@ using System.Collections.Immutable; | |||||
namespace Discord.WebSocket | namespace Discord.WebSocket | ||||
{ | { | ||||
public class SocketThreadUser : IGuildUser | |||||
/// <summary> | |||||
/// Represents a thread user received over the gateway. | |||||
/// </summary> | |||||
public class SocketThreadUser : SocketUser, IGuildUser | |||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
/// Gets the <see cref="SocketThreadChannel"/> this user is in. | /// Gets the <see cref="SocketThreadChannel"/> this user is in. | ||||
@@ -44,56 +47,36 @@ namespace Discord.WebSocket | |||||
=> GuildUser.IsPending; | => GuildUser.IsPending; | ||||
/// <inheritdoc/> | /// <inheritdoc/> | ||||
public string AvatarId | |||||
=> GuildUser.AvatarId; | |||||
/// <inheritdoc/> | |||||
public string Discriminator | |||||
=> GuildUser.Discriminator; | |||||
public override string AvatarId | |||||
{ | |||||
get => GuildUser.AvatarId; | |||||
internal set => GuildUser.AvatarId = value; | |||||
} | |||||
/// <inheritdoc/> | /// <inheritdoc/> | ||||
public ushort DiscriminatorValue | |||||
=> GuildUser.DiscriminatorValue; | |||||
public override ushort DiscriminatorValue | |||||
{ | |||||
get => GuildUser.DiscriminatorValue; | |||||
internal set => GuildUser.DiscriminatorValue = value; | |||||
} | |||||
/// <inheritdoc/> | /// <inheritdoc/> | ||||
public bool IsBot | |||||
=> GuildUser.IsBot; | |||||
public override bool IsBot | |||||
{ | |||||
get => GuildUser.IsBot; | |||||
internal set => GuildUser.IsBot = value; | |||||
} | |||||
/// <inheritdoc/> | /// <inheritdoc/> | ||||
public bool IsWebhook | |||||
public override bool IsWebhook | |||||
=> GuildUser.IsWebhook; | => GuildUser.IsWebhook; | ||||
/// <inheritdoc/> | /// <inheritdoc/> | ||||
public string Username | |||||
=> GuildUser.Username; | |||||
/// <inheritdoc/> | |||||
public UserProperties? PublicFlags | |||||
=> GuildUser.PublicFlags; | |||||
/// <inheritdoc/> | |||||
public DateTimeOffset CreatedAt | |||||
=> GuildUser.CreatedAt; | |||||
/// <inheritdoc/> | |||||
public ulong Id | |||||
=> GuildUser.Id; | |||||
/// <inheritdoc/> | |||||
public string Mention | |||||
=> GuildUser.Mention; | |||||
/// <inheritdoc/> | |||||
public UserStatus Status | |||||
=> GuildUser.Status; | |||||
/// <inheritdoc/> | |||||
public IImmutableSet<ClientType> ActiveClients | |||||
=> GuildUser.ActiveClients; | |||||
/// <inheritdoc/> | |||||
public IImmutableList<IActivity> Activities | |||||
=> GuildUser.Activities; | |||||
public override string Username | |||||
{ | |||||
get => GuildUser.Username; | |||||
internal set => GuildUser.Username = value; | |||||
} | |||||
/// <inheritdoc/> | /// <inheritdoc/> | ||||
public bool IsDeafened | public bool IsDeafened | ||||
@@ -130,13 +113,14 @@ namespace Discord.WebSocket | |||||
private SocketGuildUser GuildUser { get; set; } | private SocketGuildUser GuildUser { get; set; } | ||||
internal SocketThreadUser(SocketGuild guild, SocketThreadChannel thread, SocketGuildUser member) | internal SocketThreadUser(SocketGuild guild, SocketThreadChannel thread, SocketGuildUser member) | ||||
: base(guild.Discord, member.Id) | |||||
{ | { | ||||
this.Thread = thread; | this.Thread = thread; | ||||
this.Guild = guild; | this.Guild = guild; | ||||
this.GuildUser = member; | this.GuildUser = member; | ||||
} | } | ||||
internal SocketThreadUser Create(SocketGuild guild, SocketThreadChannel thread, Model model, SocketGuildUser member) | |||||
internal static SocketThreadUser Create(SocketGuild guild, SocketThreadChannel thread, Model model, SocketGuildUser member) | |||||
{ | { | ||||
var entity = new SocketThreadUser(guild, thread, member); | var entity = new SocketThreadUser(guild, thread, member); | ||||
entity.Update(model); | entity.Update(model); | ||||
@@ -146,6 +130,16 @@ namespace Discord.WebSocket | |||||
internal void Update(Model model) | internal void Update(Model model) | ||||
{ | { | ||||
this.ThreadJoinedAt = model.JoinTimestamp; | this.ThreadJoinedAt = model.JoinTimestamp; | ||||
if (model.Presence.IsSpecified) | |||||
{ | |||||
this.GuildUser.Update(Discord.State, model.Presence.Value, true); | |||||
} | |||||
if (model.Member.IsSpecified) | |||||
{ | |||||
this.GuildUser.Update(Discord.State, model.Member.Value); | |||||
} | |||||
} | } | ||||
@@ -182,15 +176,6 @@ namespace Discord.WebSocket | |||||
/// <inheritdoc/> | /// <inheritdoc/> | ||||
public Task RemoveRolesAsync(IEnumerable<IRole> roles, RequestOptions options = null) => GuildUser.RemoveRolesAsync(roles, options); | public Task RemoveRolesAsync(IEnumerable<IRole> roles, RequestOptions options = null) => GuildUser.RemoveRolesAsync(roles, options); | ||||
/// <inheritdoc/> | |||||
public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) => GuildUser.GetAvatarUrl(format, size); | |||||
/// <inheritdoc/> | |||||
public string GetDefaultAvatarUrl() => GuildUser.GetDefaultAvatarUrl(); | |||||
/// <inheritdoc/> | |||||
public Task<IDMChannel> CreateDMChannelAsync(RequestOptions options = null) => GuildUser.CreateDMChannelAsync(options); | |||||
/// <inheritdoc/> | /// <inheritdoc/> | ||||
GuildPermissions IGuildUser.GuildPermissions => this.GuildUser.GuildPermissions; | GuildPermissions IGuildUser.GuildPermissions => this.GuildUser.GuildPermissions; | ||||
@@ -203,6 +188,10 @@ namespace Discord.WebSocket | |||||
/// <inheritdoc/> | /// <inheritdoc/> | ||||
IReadOnlyCollection<ulong> IGuildUser.RoleIds => this.GuildUser.Roles.Select(x => x.Id).ToImmutableArray(); | IReadOnlyCollection<ulong> IGuildUser.RoleIds => this.GuildUser.Roles.Select(x => x.Id).ToImmutableArray(); | ||||
internal override SocketGlobalUser GlobalUser => GuildUser.GlobalUser; | |||||
internal override SocketPresence Presence { get => GuildUser.Presence; set => GuildUser.Presence = value; } | |||||
/// <summary> | /// <summary> | ||||
/// Gets the guild user of this thread user. | /// Gets the guild user of this thread user. | ||||
/// </summary> | /// </summary> | ||||
@@ -161,7 +161,7 @@ namespace Discord | |||||
AssertUtil(GuildPermission.ManageNicknames, x => x.ManageNicknames, (p, enable) => p.Modify(manageNicknames: enable)); | AssertUtil(GuildPermission.ManageNicknames, x => x.ManageNicknames, (p, enable) => p.Modify(manageNicknames: enable)); | ||||
AssertUtil(GuildPermission.ManageRoles, x => x.ManageRoles, (p, enable) => p.Modify(manageRoles: enable)); | AssertUtil(GuildPermission.ManageRoles, x => x.ManageRoles, (p, enable) => p.Modify(manageRoles: enable)); | ||||
AssertUtil(GuildPermission.ManageWebhooks, x => x.ManageWebhooks, (p, enable) => p.Modify(manageWebhooks: enable)); | AssertUtil(GuildPermission.ManageWebhooks, x => x.ManageWebhooks, (p, enable) => p.Modify(manageWebhooks: enable)); | ||||
AssertUtil(GuildPermission.ManageEmojis, x => x.ManageEmojis, (p, enable) => p.Modify(manageEmojis: enable)); | |||||
AssertUtil(GuildPermission.ManageEmojis, x => x.ManageEmojisAndStickers, (p, enable) => p.Modify(manageEmojis: enable)); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -210,5 +210,7 @@ namespace Discord | |||||
{ | { | ||||
throw new NotImplementedException(); | throw new NotImplementedException(); | ||||
} | } | ||||
public Task<IThreadChannel> CreateThreadAsync(string name, ThreadType type = ThreadType.PublicThread, ThreadArchiveDuration autoArchiveDuration = ThreadArchiveDuration.OneDay, IMessage message = null, RequestOptions options = null) => throw new NotImplementedException(); | |||||
} | } | ||||
} | } |