feature: Forum channels (#2316)
* initial implementation * Update SocketForumChannel.cs * rest forum channel and remove message builder for 4.x * Update src/Discord.Net.Core/DiscordConfig.cs Co-authored-by: Jared L <48422312+lhjt@users.noreply.github.com> * Update src/Discord.Net.Core/Entities/Channels/IForumChannel.cs Co-authored-by: Jared L <48422312+lhjt@users.noreply.github.com> * Update src/Discord.Net.Core/DiscordConfig.cs Co-authored-by: Jared L <48422312+lhjt@users.noreply.github.com> * Update src/Discord.Net.Core/Entities/Channels/IForumChannel.cs Co-authored-by: Jared L <48422312+lhjt@users.noreply.github.com> * Update src/Discord.Net.Core/Entities/Channels/IForumChannel.cs Co-authored-by: Jared L <48422312+lhjt@users.noreply.github.com> * Update src/Discord.Net.Core/Entities/Channels/IForumChannel.cs Co-authored-by: Jared L <48422312+lhjt@users.noreply.github.com> Co-authored-by: Jared L <48422312+lhjt@users.noreply.github.com>
This commit is contained in:
@@ -132,6 +132,16 @@ namespace Discord
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
public const int MaxAuditLogEntriesPerBatch = 100;
|
public const int MaxAuditLogEntriesPerBatch = 100;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the max number of stickers that can be sent with a message.
|
||||||
|
/// </summary>
|
||||||
|
public const int MaxStickersPerMessage = 3;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the max number of embeds that can be sent with a message.
|
||||||
|
/// </summary>
|
||||||
|
public const int MaxEmbedsPerMessage = 10;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets how a request should act in the case of an error, by default.
|
/// Gets or sets how a request should act in the case of an error, by default.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ namespace Discord
|
|||||||
/// <summary> The channel is a stage voice channel. </summary>
|
/// <summary> The channel is a stage voice channel. </summary>
|
||||||
Stage = 13,
|
Stage = 13,
|
||||||
/// <summary> The channel is a guild directory used in hub servers. (Unreleased)</summary>
|
/// <summary> The channel is a guild directory used in hub servers. (Unreleased)</summary>
|
||||||
GuildDirectory = 14
|
GuildDirectory = 14,
|
||||||
|
/// <summary> The channel is a forum channel containing multiple threads. </summary>
|
||||||
|
Forum = 15
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
216
src/Discord.Net.Core/Entities/Channels/IForumChannel.cs
Normal file
216
src/Discord.Net.Core/Entities/Channels/IForumChannel.cs
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Discord
|
||||||
|
{
|
||||||
|
public interface IForumChannel : IGuildChannel, IMentionable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value that indicates whether the channel is NSFW.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// <c>true</c> if the channel has the NSFW flag enabled; otherwise <c>false</c>.
|
||||||
|
/// </returns>
|
||||||
|
bool IsNsfw { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current topic for this text channel.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// A string representing the topic set in the channel; <c>null</c> if none is set.
|
||||||
|
/// </returns>
|
||||||
|
string Topic { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the default archive duration for a newly created post.
|
||||||
|
/// </summary>
|
||||||
|
ThreadArchiveDuration DefaultAutoArchiveDuration { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a collection of tags inside of this forum channel.
|
||||||
|
/// </summary>
|
||||||
|
IReadOnlyCollection<ForumTag> Tags { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new post (thread) within the forum.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="title">The title of the post.</param>
|
||||||
|
/// <param name="archiveDuration">The archive duration of the post.</param>
|
||||||
|
/// <param name="slowmode">The slowmode for the posts thread.</param>
|
||||||
|
/// <param name="text">The message to be sent.</param>
|
||||||
|
/// <param name="embed">The <see cref="Discord.EmbedType.Rich"/> <see cref="Embed"/> to be sent.</param>
|
||||||
|
/// <param name="options">The options to be used when sending the request.</param>
|
||||||
|
/// <param name="allowedMentions">
|
||||||
|
/// Specifies if notifications are sent for mentioned users and roles in the message <paramref name="text"/>.
|
||||||
|
/// If <c>null</c>, all mentioned roles and users will be notified.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="components">The message components to be included with this message. Used for interactions.</param>
|
||||||
|
/// <param name="stickers">A collection of stickers to send with the message.</param>
|
||||||
|
/// <param name="embeds">A array of <see cref="Embed"/>s to send with this response. Max 10.</param>
|
||||||
|
/// <param name="flags">A message flag to be applied to the sent message, only <see cref="MessageFlags.SuppressEmbeds"/> is permitted.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// A task that represents the asynchronous creation operation.
|
||||||
|
/// </returns>
|
||||||
|
Task<IThreadChannel> CreatePostAsync(string title, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay, int? slowmode = null,
|
||||||
|
string text = null, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
|
||||||
|
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new post (thread) within the forum.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="title">The title of the post.</param>
|
||||||
|
/// <param name="archiveDuration">The archive duration of the post.</param>
|
||||||
|
/// <param name="slowmode">The slowmode for the posts thread.</param>
|
||||||
|
/// <param name="filePath">The file path of the file.</param>
|
||||||
|
/// <param name="text">The message to be sent.</param>
|
||||||
|
/// <param name="embed">The <see cref="Discord.EmbedType.Rich" /> <see cref="Embed" /> to be sent.</param>
|
||||||
|
/// <param name="options">The options to be used when sending the request.</param>
|
||||||
|
/// <param name="isSpoiler">Whether the message attachment should be hidden as a spoiler.</param>
|
||||||
|
/// <param name="allowedMentions">
|
||||||
|
/// Specifies if notifications are sent for mentioned users and roles in the message <paramref name="text"/>.
|
||||||
|
/// If <c>null</c>, all mentioned roles and users will be notified.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="components">The message components to be included with this message. Used for interactions.</param>
|
||||||
|
/// <param name="stickers">A collection of stickers to send with the file.</param>
|
||||||
|
/// <param name="embeds">A array of <see cref="Embed"/>s to send with this response. Max 10.</param>
|
||||||
|
/// <param name="flags">A message flag to be applied to the sent message, only <see cref="MessageFlags.SuppressEmbeds"/> is permitted.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// A task that represents the asynchronous creation operation.
|
||||||
|
/// </returns>
|
||||||
|
Task<IThreadChannel> CreatePostWithFileAsync(string title, string filePath, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay,
|
||||||
|
int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, bool isSpoiler = false,
|
||||||
|
AllowedMentions allowedMentions = null, MessageComponent components = null,
|
||||||
|
ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new post (thread) within the forum.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="title">The title of the post.</param>
|
||||||
|
/// <param name="stream">The <see cref="Stream" /> of the file to be sent.</param>
|
||||||
|
/// <param name="filename">The name of the attachment.</param>
|
||||||
|
/// <param name="archiveDuration">The archive duration of the post.</param>
|
||||||
|
/// <param name="slowmode">The slowmode for the posts thread.</param>
|
||||||
|
/// <param name="text">The message to be sent.</param>
|
||||||
|
/// <param name="embed">The <see cref="Discord.EmbedType.Rich"/> <see cref="Embed"/> to be sent.</param>
|
||||||
|
/// <param name="options">The options to be used when sending the request.</param>
|
||||||
|
/// <param name="isSpoiler">Whether the message attachment should be hidden as a spoiler.</param>
|
||||||
|
/// <param name="allowedMentions">
|
||||||
|
/// Specifies if notifications are sent for mentioned users and roles in the message <paramref name="text"/>.
|
||||||
|
/// If <c>null</c>, all mentioned roles and users will be notified.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="components">The message components to be included with this message. Used for interactions.</param>
|
||||||
|
/// <param name="stickers">A collection of stickers to send with the file.</param>
|
||||||
|
/// <param name="embeds">A array of <see cref="Embed"/>s to send with this response. Max 10.</param>
|
||||||
|
/// <param name="flags">A message flag to be applied to the sent message, only <see cref="MessageFlags.SuppressEmbeds"/> is permitted.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// A task that represents the asynchronous creation operation.
|
||||||
|
/// </returns>
|
||||||
|
public Task<IThreadChannel> CreatePostWithFileAsync(string title, Stream stream, string filename, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay,
|
||||||
|
int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, bool isSpoiler = false,
|
||||||
|
AllowedMentions allowedMentions = null, MessageComponent components = null,
|
||||||
|
ISticker[] stickers = null, Embed[] embeds = null,MessageFlags flags = MessageFlags.None);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new post (thread) within the forum.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="title">The title of the post.</param>
|
||||||
|
/// <param name="attachment">The attachment containing the file and description.</param>
|
||||||
|
/// <param name="archiveDuration">The archive duration of the post.</param>
|
||||||
|
/// <param name="slowmode">The slowmode for the posts thread.</param>
|
||||||
|
/// <param name="text">The message to be sent.</param>
|
||||||
|
/// <param name="embed">The <see cref="Discord.EmbedType.Rich"/> <see cref="Embed"/> to be sent.</param>
|
||||||
|
/// <param name="options">The options to be used when sending the request.</param>
|
||||||
|
/// <param name="allowedMentions">
|
||||||
|
/// Specifies if notifications are sent for mentioned users and roles in the message <paramref name="text"/>.
|
||||||
|
/// If <c>null</c>, all mentioned roles and users will be notified.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="components">The message components to be included with this message. Used for interactions.</param>
|
||||||
|
/// <param name="stickers">A collection of stickers to send with the file.</param>
|
||||||
|
/// <param name="embeds">A array of <see cref="Embed"/>s to send with this response. Max 10.</param>
|
||||||
|
/// <param name="flags">A message flag to be applied to the sent message, only <see cref="MessageFlags.SuppressEmbeds"/> is permitted.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// A task that represents the asynchronous creation operation.
|
||||||
|
/// </returns>
|
||||||
|
public Task<IThreadChannel> CreatePostWithFileAsync(string title, FileAttachment attachment, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay,
|
||||||
|
int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
|
||||||
|
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new post (thread) within the forum.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="title">The title of the post.</param>
|
||||||
|
/// <param name="attachments">A collection of attachments to upload.</param>
|
||||||
|
/// <param name="archiveDuration">The archive duration of the post.</param>
|
||||||
|
/// <param name="slowmode">The slowmode for the posts thread.</param>
|
||||||
|
/// <param name="text">The message to be sent.</param>
|
||||||
|
/// <param name="embed">The <see cref="Discord.EmbedType.Rich"/> <see cref="Embed"/> to be sent.</param>
|
||||||
|
/// <param name="options">The options to be used when sending the request.</param>
|
||||||
|
/// <param name="allowedMentions">
|
||||||
|
/// Specifies if notifications are sent for mentioned users and roles in the message <paramref name="text"/>.
|
||||||
|
/// If <c>null</c>, all mentioned roles and users will be notified.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="components">The message components to be included with this message. Used for interactions.</param>
|
||||||
|
/// <param name="stickers">A collection of stickers to send with the file.</param>
|
||||||
|
/// <param name="embeds">A array of <see cref="Embed"/>s to send with this response. Max 10.</param>
|
||||||
|
/// <param name="flags">A message flag to be applied to the sent message, only <see cref="MessageFlags.SuppressEmbeds"/> is permitted.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// A task that represents the asynchronous creation operation.
|
||||||
|
/// </returns>
|
||||||
|
public Task<IThreadChannel> CreatePostWithFilesAsync(string title, IEnumerable<FileAttachment> attachments, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay,
|
||||||
|
int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
|
||||||
|
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a collection of active threads within this forum channel.
|
||||||
|
/// </summary>
|
||||||
|
/// <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 threads. The task result contains
|
||||||
|
/// a collection of active threads.
|
||||||
|
/// </returns>
|
||||||
|
Task<IReadOnlyCollection<IThreadChannel>> GetActiveThreadsAsync(RequestOptions options = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a collection of publicly archived threads within this forum channel.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="limit">The optional limit of how many to get.</param>
|
||||||
|
/// <param name="before">The optional date to return threads created before this timestamp.</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 threads. The task result contains
|
||||||
|
/// a collection of publicly archived threads.
|
||||||
|
/// </returns>
|
||||||
|
Task<IReadOnlyCollection<IThreadChannel>> GetPublicArchivedThreadsAsync(int? limit = null, DateTimeOffset? before = null, RequestOptions options = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a collection of privately archived threads within this forum channel.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The bot requires the <see cref="GuildPermission.ManageThreads"/> permission in order to execute this request.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="limit">The optional limit of how many to get.</param>
|
||||||
|
/// <param name="before">The optional date to return threads created before this timestamp.</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 threads. The task result contains
|
||||||
|
/// a collection of privately archived threads.
|
||||||
|
/// </returns>
|
||||||
|
Task<IReadOnlyCollection<IThreadChannel>> GetPrivateArchivedThreadsAsync(int? limit = null, DateTimeOffset? before = null, RequestOptions options = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a collection of privately archived threads that the current bot has joined within this forum channel.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="limit">The optional limit of how many to get.</param>
|
||||||
|
/// <param name="before">The optional date to return threads created before this timestamp.</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 threads. The task result contains
|
||||||
|
/// a collection of privately archived threads.
|
||||||
|
/// </returns>
|
||||||
|
Task<IReadOnlyCollection<IThreadChannel>> GetJoinedPrivateArchivedThreadsAsync(int? limit = null, DateTimeOffset? before = null, RequestOptions options = null);
|
||||||
|
}
|
||||||
|
}
|
||||||
42
src/Discord.Net.Core/Entities/ForumTag.cs
Normal file
42
src/Discord.Net.Core/Entities/ForumTag.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Discord
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A struct representing a forum channel tag.
|
||||||
|
/// </summary>
|
||||||
|
public struct ForumTag
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Id of the tag.
|
||||||
|
/// </summary>
|
||||||
|
public ulong Id { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the tag.
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the emoji of the tag or <see langword="null"/> if none is set.
|
||||||
|
/// </summary>
|
||||||
|
public IEmote Emoji { get; }
|
||||||
|
|
||||||
|
internal ForumTag(ulong id, string name, ulong? emojiId, string emojiName)
|
||||||
|
{
|
||||||
|
if (emojiId.HasValue && emojiId.Value != 0)
|
||||||
|
Emoji = new Emote(emojiId.Value, emojiName, false);
|
||||||
|
else if (emojiName != null)
|
||||||
|
Emoji = new Emoji(name);
|
||||||
|
else
|
||||||
|
Emoji = null;
|
||||||
|
|
||||||
|
Id = id;
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -67,6 +67,10 @@ namespace Discord.API
|
|||||||
[JsonProperty("member_count")]
|
[JsonProperty("member_count")]
|
||||||
public Optional<int> MemberCount { get; set; }
|
public Optional<int> MemberCount { get; set; }
|
||||||
|
|
||||||
|
//ForumChannel
|
||||||
|
[JsonProperty("available_tags")]
|
||||||
|
public Optional<ForumTags[]> ForumTags { get; set; }
|
||||||
|
|
||||||
[JsonProperty("default_auto_archive_duration")]
|
[JsonProperty("default_auto_archive_duration")]
|
||||||
public Optional<ThreadArchiveDuration> AutoArchiveDuration { get; set; }
|
public Optional<ThreadArchiveDuration> AutoArchiveDuration { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,5 @@ namespace Discord.API.Rest
|
|||||||
|
|
||||||
[JsonProperty("members")]
|
[JsonProperty("members")]
|
||||||
public ThreadMember[] Members { get; set; }
|
public ThreadMember[] Members { get; set; }
|
||||||
|
|
||||||
[JsonProperty("has_more")]
|
|
||||||
public bool HasMore { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
21
src/Discord.Net.Rest/API/Common/ForumTags.cs
Normal file
21
src/Discord.Net.Rest/API/Common/ForumTags.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Discord.API
|
||||||
|
{
|
||||||
|
internal class ForumTags
|
||||||
|
{
|
||||||
|
[JsonProperty("id")]
|
||||||
|
public ulong Id { get; set; }
|
||||||
|
[JsonProperty("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
[JsonProperty("emoji_id")]
|
||||||
|
public Optional<ulong?> EmojiId { get; set; }
|
||||||
|
[JsonProperty("emoji_name")]
|
||||||
|
public Optional<string> EmojiName { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/Discord.Net.Rest/API/Common/ForumThreadMessage.cs
Normal file
33
src/Discord.Net.Rest/API/Common/ForumThreadMessage.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Discord.API
|
||||||
|
{
|
||||||
|
internal class ForumThreadMessage
|
||||||
|
{
|
||||||
|
[JsonProperty("content")]
|
||||||
|
public Optional<string> Content { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("nonce")]
|
||||||
|
public Optional<string> Nonce { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("embeds")]
|
||||||
|
public Optional<Embed[]> Embeds { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("allowed_mentions")]
|
||||||
|
public Optional<AllowedMentions> AllowedMentions { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("components")]
|
||||||
|
public Optional<API.ActionRowComponent[]> Components { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("sticker_ids")]
|
||||||
|
public Optional<ulong[]> Stickers { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("flags")]
|
||||||
|
public Optional<MessageFlags> Flags { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
96
src/Discord.Net.Rest/API/Rest/CreateMultipartPostAsync.cs
Normal file
96
src/Discord.Net.Rest/API/Rest/CreateMultipartPostAsync.cs
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
using Discord.Net.Converters;
|
||||||
|
using Discord.Net.Rest;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Discord.API.Rest
|
||||||
|
{
|
||||||
|
internal class CreateMultipartPostAsync
|
||||||
|
{
|
||||||
|
private static JsonSerializer _serializer = new JsonSerializer { ContractResolver = new DiscordContractResolver() };
|
||||||
|
|
||||||
|
public FileAttachment[] Files { get; }
|
||||||
|
|
||||||
|
public string Title { get; set; }
|
||||||
|
public ThreadArchiveDuration ArchiveDuration { get; set; }
|
||||||
|
public Optional<int?> Slowmode { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public Optional<string> Content { get; set; }
|
||||||
|
public Optional<Embed[]> Embeds { get; set; }
|
||||||
|
public Optional<AllowedMentions> AllowedMentions { get; set; }
|
||||||
|
public Optional<ActionRowComponent[]> MessageComponent { get; set; }
|
||||||
|
public Optional<MessageFlags?> Flags { get; set; }
|
||||||
|
public Optional<ulong[]> Stickers { get; set; }
|
||||||
|
|
||||||
|
public CreateMultipartPostAsync(params FileAttachment[] attachments)
|
||||||
|
{
|
||||||
|
Files = attachments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IReadOnlyDictionary<string, object> ToDictionary()
|
||||||
|
{
|
||||||
|
var d = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
var payload = new Dictionary<string, object>();
|
||||||
|
var message = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
payload["name"] = Title;
|
||||||
|
payload["auto_archive_duration"] = ArchiveDuration;
|
||||||
|
|
||||||
|
if (Slowmode.IsSpecified)
|
||||||
|
payload["rate_limit_per_user"] = Slowmode.Value;
|
||||||
|
|
||||||
|
// message
|
||||||
|
if (Content.IsSpecified)
|
||||||
|
message["content"] = Content.Value;
|
||||||
|
if (Embeds.IsSpecified)
|
||||||
|
message["embeds"] = Embeds.Value;
|
||||||
|
if (AllowedMentions.IsSpecified)
|
||||||
|
message["allowed_mentions"] = AllowedMentions.Value;
|
||||||
|
if (MessageComponent.IsSpecified)
|
||||||
|
message["components"] = MessageComponent.Value;
|
||||||
|
if (Stickers.IsSpecified)
|
||||||
|
message["sticker_ids"] = Stickers.Value;
|
||||||
|
if (Flags.IsSpecified)
|
||||||
|
message["flags"] = Flags.Value;
|
||||||
|
|
||||||
|
List<object> attachments = new();
|
||||||
|
|
||||||
|
for (int n = 0; n != Files.Length; n++)
|
||||||
|
{
|
||||||
|
var attachment = Files[n];
|
||||||
|
|
||||||
|
var filename = attachment.FileName ?? "unknown.dat";
|
||||||
|
if (attachment.IsSpoiler && !filename.StartsWith(AttachmentExtensions.SpoilerPrefix))
|
||||||
|
filename = filename.Insert(0, AttachmentExtensions.SpoilerPrefix);
|
||||||
|
d[$"files[{n}]"] = new MultipartFile(attachment.Stream, filename);
|
||||||
|
|
||||||
|
attachments.Add(new
|
||||||
|
{
|
||||||
|
id = (ulong)n,
|
||||||
|
filename = filename,
|
||||||
|
description = attachment.Description ?? Optional<string>.Unspecified
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
message["attachments"] = attachments;
|
||||||
|
|
||||||
|
payload["message"] = message;
|
||||||
|
|
||||||
|
var json = new StringBuilder();
|
||||||
|
using (var text = new StringWriter(json))
|
||||||
|
using (var writer = new JsonTextWriter(text))
|
||||||
|
_serializer.Serialize(writer, payload);
|
||||||
|
|
||||||
|
d["payload_json"] = json.ToString();
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
25
src/Discord.Net.Rest/API/Rest/CreatePostParams.cs
Normal file
25
src/Discord.Net.Rest/API/Rest/CreatePostParams.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Discord.API.Rest
|
||||||
|
{
|
||||||
|
internal class CreatePostParams
|
||||||
|
{
|
||||||
|
// thread
|
||||||
|
[JsonProperty("name")]
|
||||||
|
public string Title { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("auto_archive_duration")]
|
||||||
|
public ThreadArchiveDuration ArchiveDuration { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("rate_limit_per_user")]
|
||||||
|
public Optional<int?> Slowmode { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("message")]
|
||||||
|
public ForumThreadMessage Message { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,7 +37,7 @@ namespace Discord.API.Rest
|
|||||||
if (Content.IsSpecified)
|
if (Content.IsSpecified)
|
||||||
payload["content"] = Content.Value;
|
payload["content"] = Content.Value;
|
||||||
if (IsTTS.IsSpecified)
|
if (IsTTS.IsSpecified)
|
||||||
payload["tts"] = IsTTS.Value.ToString();
|
payload["tts"] = IsTTS.Value;
|
||||||
if (Nonce.IsSpecified)
|
if (Nonce.IsSpecified)
|
||||||
payload["nonce"] = Nonce.Value;
|
payload["nonce"] = Nonce.Value;
|
||||||
if (Embeds.IsSpecified)
|
if (Embeds.IsSpecified)
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ namespace Discord.API.Rest
|
|||||||
if (Content.IsSpecified)
|
if (Content.IsSpecified)
|
||||||
data["content"] = Content.Value;
|
data["content"] = Content.Value;
|
||||||
if (IsTTS.IsSpecified)
|
if (IsTTS.IsSpecified)
|
||||||
data["tts"] = IsTTS.Value.ToString();
|
data["tts"] = IsTTS.Value;
|
||||||
if (MessageComponents.IsSpecified)
|
if (MessageComponents.IsSpecified)
|
||||||
data["components"] = MessageComponents.Value;
|
data["components"] = MessageComponents.Value;
|
||||||
if (Embeds.IsSpecified)
|
if (Embeds.IsSpecified)
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace Discord.API.Rest
|
|||||||
if (Content.IsSpecified)
|
if (Content.IsSpecified)
|
||||||
payload["content"] = Content.Value;
|
payload["content"] = Content.Value;
|
||||||
if (IsTTS.IsSpecified)
|
if (IsTTS.IsSpecified)
|
||||||
payload["tts"] = IsTTS.Value.ToString();
|
payload["tts"] = IsTTS.Value;
|
||||||
if (Nonce.IsSpecified)
|
if (Nonce.IsSpecified)
|
||||||
payload["nonce"] = Nonce.Value;
|
payload["nonce"] = Nonce.Value;
|
||||||
if (Username.IsSpecified)
|
if (Username.IsSpecified)
|
||||||
|
|||||||
@@ -466,6 +466,24 @@ namespace Discord.API
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Threads
|
#region Threads
|
||||||
|
public async Task<Channel> CreatePostAsync(ulong channelId, CreatePostParams args, RequestOptions options = null)
|
||||||
|
{
|
||||||
|
Preconditions.NotEqual(channelId, 0, nameof(channelId));
|
||||||
|
|
||||||
|
var bucket = new BucketIds(channelId: channelId);
|
||||||
|
|
||||||
|
return await SendJsonAsync<Channel>("POST", () => $"channels/{channelId}/threads", args, bucket, options: options);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Channel> CreatePostAsync(ulong channelId, CreateMultipartPostAsync args, RequestOptions options = null)
|
||||||
|
{
|
||||||
|
Preconditions.NotEqual(channelId, 0, nameof(channelId));
|
||||||
|
|
||||||
|
var bucket = new BucketIds(channelId: channelId);
|
||||||
|
|
||||||
|
return await SendMultipartAsync<Channel>("POST", () => $"channels/{channelId}/threads", args.ToDictionary(), bucket, options: options);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<Channel> ModifyThreadAsync(ulong channelId, ModifyThreadParams args, RequestOptions options = null)
|
public async Task<Channel> ModifyThreadAsync(ulong channelId, ModifyThreadParams args, RequestOptions options = null)
|
||||||
{
|
{
|
||||||
Preconditions.NotEqual(channelId, 0, nameof(channelId));
|
Preconditions.NotEqual(channelId, 0, nameof(channelId));
|
||||||
@@ -566,15 +584,15 @@ namespace Discord.API
|
|||||||
return await SendAsync<ThreadMember>("GET", () => $"channels/{channelId}/thread-members/{userId}", bucket, options: options).ConfigureAwait(false);
|
return await SendAsync<ThreadMember>("GET", () => $"channels/{channelId}/thread-members/{userId}", bucket, options: options).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ChannelThreads> GetActiveThreadsAsync(ulong channelId, RequestOptions options = null)
|
public async Task<ChannelThreads> GetActiveThreadsAsync(ulong guildId, RequestOptions options = null)
|
||||||
{
|
{
|
||||||
Preconditions.NotEqual(channelId, 0, nameof(channelId));
|
Preconditions.NotEqual(guildId, 0, nameof(guildId));
|
||||||
|
|
||||||
options = RequestOptions.CreateOrClone(options);
|
options = RequestOptions.CreateOrClone(options);
|
||||||
|
|
||||||
var bucket = new BucketIds(channelId: channelId);
|
var bucket = new BucketIds(guildId: guildId);
|
||||||
|
|
||||||
return await SendAsync<ChannelThreads>("GET", () => $"channels/{channelId}/threads/active", bucket, options: options);
|
return await SendAsync<ChannelThreads>("GET", () => $"guilds/{guildId}/threads/active", bucket, options: options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ChannelThreads> GetPublicArchivedThreadsAsync(ulong channelId, DateTimeOffset? before = null, int? limit = null, RequestOptions options = null)
|
public async Task<ChannelThreads> GetPublicArchivedThreadsAsync(ulong channelId, DateTimeOffset? before = null, int? limit = null, RequestOptions options = null)
|
||||||
|
|||||||
131
src/Discord.Net.Rest/Entities/Channels/RestForumChannel.cs
Normal file
131
src/Discord.Net.Rest/Entities/Channels/RestForumChannel.cs
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
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 REST-based forum channel in a guild.
|
||||||
|
/// </summary>
|
||||||
|
public class RestForumChannel : RestGuildChannel, IForumChannel
|
||||||
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool IsNsfw { get; private set; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string Topic { get; private set; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public ThreadArchiveDuration DefaultAutoArchiveDuration { get; private set; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IReadOnlyCollection<ForumTag> Tags { get; private set; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string Mention => MentionUtils.MentionChannel(Id);
|
||||||
|
|
||||||
|
internal RestForumChannel(BaseDiscordClient client, IGuild guild, ulong id)
|
||||||
|
: base(client, guild, id)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal new static RestStageChannel Create(BaseDiscordClient discord, IGuild guild, Model model)
|
||||||
|
{
|
||||||
|
var entity = new RestStageChannel(discord, guild, model.Id);
|
||||||
|
entity.Update(model);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Update(Model model)
|
||||||
|
{
|
||||||
|
base.Update(model);
|
||||||
|
IsNsfw = model.Nsfw.GetValueOrDefault(false);
|
||||||
|
Topic = model.Topic.GetValueOrDefault();
|
||||||
|
DefaultAutoArchiveDuration = model.AutoArchiveDuration.GetValueOrDefault(ThreadArchiveDuration.OneDay);
|
||||||
|
|
||||||
|
Tags = model.ForumTags.GetValueOrDefault(Array.Empty<API.ForumTags>()).Select(
|
||||||
|
x => new ForumTag(x.Id, x.Name, x.EmojiId.GetValueOrDefault(null), x.EmojiName.GetValueOrDefault())
|
||||||
|
).ToImmutableArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IForumChannel.CreatePostAsync(string, ThreadArchiveDuration, int?, string, Embed, RequestOptions, AllowedMentions, MessageComponent, ISticker[], Embed[], MessageFlags)"/>
|
||||||
|
public Task<RestThreadChannel> CreatePostAsync(string title, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay, int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||||
|
=> ThreadHelper.CreatePostAsync(this, Discord, title, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IForumChannel.CreatePostWithFileAsync(string, string, ThreadArchiveDuration, int?, string, Embed, RequestOptions, bool, AllowedMentions, MessageComponent, ISticker[], Embed[], MessageFlags)"/>
|
||||||
|
public async Task<RestThreadChannel> CreatePostWithFileAsync(string title, string filePath, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay,
|
||||||
|
int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, bool isSpoiler = false,
|
||||||
|
AllowedMentions allowedMentions = null, MessageComponent components = null,
|
||||||
|
ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||||
|
{
|
||||||
|
using var file = new FileAttachment(filePath, isSpoiler: isSpoiler);
|
||||||
|
return await ThreadHelper.CreatePostAsync(this, Discord, title, new FileAttachment[] { file }, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IForumChannel.CreatePostWithFileAsync(string, Stream, string, ThreadArchiveDuration, int?, string, Embed, RequestOptions, bool, AllowedMentions, MessageComponent, ISticker[], Embed[], MessageFlags)"/>
|
||||||
|
public async Task<RestThreadChannel> CreatePostWithFileAsync(string title, Stream stream, string filename, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay,
|
||||||
|
int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, bool isSpoiler = false,
|
||||||
|
AllowedMentions allowedMentions = null, MessageComponent components = null,
|
||||||
|
ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||||
|
{
|
||||||
|
using var file = new FileAttachment(stream, filename, isSpoiler: isSpoiler);
|
||||||
|
return await ThreadHelper.CreatePostAsync(this, Discord, title, new FileAttachment[] { file }, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IForumChannel.CreatePostWithFileAsync(string, FileAttachment, ThreadArchiveDuration, int?, string, Embed, RequestOptions, AllowedMentions, MessageComponent, ISticker[], Embed[], MessageFlags)"/>
|
||||||
|
public Task<RestThreadChannel> CreatePostWithFileAsync(string title, FileAttachment attachment, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay,
|
||||||
|
int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
|
||||||
|
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||||
|
=> ThreadHelper.CreatePostAsync(this, Discord, title, new FileAttachment[] { attachment }, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IForumChannel.CreatePostWithFilesAsync(string, IEnumerable{FileAttachment}, ThreadArchiveDuration, int?, string, Embed, RequestOptions, AllowedMentions, MessageComponent, ISticker[], Embed[], MessageFlags)"/>
|
||||||
|
public Task<RestThreadChannel> CreatePostWithFilesAsync(string title, IEnumerable<FileAttachment> attachments, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay,
|
||||||
|
int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
|
||||||
|
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||||
|
=> ThreadHelper.CreatePostAsync(this, Discord, title, attachments, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IForumChannel.GetActiveThreadsAsync(RequestOptions)"/>
|
||||||
|
public Task<IReadOnlyCollection<RestThreadChannel>> GetActiveThreadsAsync(RequestOptions options = null)
|
||||||
|
=> ThreadHelper.GetActiveThreadsAsync(Guild, Discord, options);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IForumChannel.GetJoinedPrivateArchivedThreadsAsync(int?, DateTimeOffset?, RequestOptions)"/>
|
||||||
|
public Task<IReadOnlyCollection<RestThreadChannel>> GetJoinedPrivateArchivedThreadsAsync(int? limit = null, DateTimeOffset? before = null, RequestOptions options = null)
|
||||||
|
=> ThreadHelper.GetJoinedPrivateArchivedThreadsAsync(this, Discord, limit, before, options);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IForumChannel.GetPrivateArchivedThreadsAsync(int?, DateTimeOffset?, RequestOptions)"/>
|
||||||
|
public Task<IReadOnlyCollection<RestThreadChannel>> GetPrivateArchivedThreadsAsync(int? limit = null, DateTimeOffset? before = null, RequestOptions options = null)
|
||||||
|
=> ThreadHelper.GetPrivateArchivedThreadsAsync(this, Discord, limit, before, options);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IForumChannel.GetPublicArchivedThreadsAsync(int?, DateTimeOffset?, RequestOptions)"/>
|
||||||
|
public Task<IReadOnlyCollection<RestThreadChannel>> GetPublicArchivedThreadsAsync(int? limit = null, DateTimeOffset? before = null, RequestOptions options = null)
|
||||||
|
=> ThreadHelper.GetPublicArchivedThreadsAsync(this, Discord, limit, before, options);
|
||||||
|
|
||||||
|
#region IForumChannel
|
||||||
|
async Task<IReadOnlyCollection<IThreadChannel>> IForumChannel.GetActiveThreadsAsync(RequestOptions options)
|
||||||
|
=> await GetActiveThreadsAsync(options).ConfigureAwait(false);
|
||||||
|
async Task<IReadOnlyCollection<IThreadChannel>> IForumChannel.GetPublicArchivedThreadsAsync(int? limit, DateTimeOffset? before, RequestOptions options)
|
||||||
|
=> await GetPublicArchivedThreadsAsync(limit, before, options).ConfigureAwait(false);
|
||||||
|
async Task<IReadOnlyCollection<IThreadChannel>> IForumChannel.GetPrivateArchivedThreadsAsync(int? limit, DateTimeOffset? before, RequestOptions options)
|
||||||
|
=> await GetPrivateArchivedThreadsAsync(limit, before, options).ConfigureAwait(false);
|
||||||
|
async Task<IReadOnlyCollection<IThreadChannel>> IForumChannel.GetJoinedPrivateArchivedThreadsAsync(int? limit, DateTimeOffset? before, RequestOptions options)
|
||||||
|
=> await GetJoinedPrivateArchivedThreadsAsync(limit, before, options).ConfigureAwait(false);
|
||||||
|
async Task<IThreadChannel> IForumChannel.CreatePostAsync(string title, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags)
|
||||||
|
=> await CreatePostAsync(title, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags).ConfigureAwait(false);
|
||||||
|
async Task<IThreadChannel> IForumChannel.CreatePostWithFileAsync(string title, string filePath, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags)
|
||||||
|
=> await CreatePostWithFileAsync(title, filePath, archiveDuration, slowmode, text, embed, options, isSpoiler, allowedMentions, components, stickers, embeds, flags).ConfigureAwait(false);
|
||||||
|
async Task<IThreadChannel> IForumChannel.CreatePostWithFileAsync(string title, Stream stream, string filename, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags)
|
||||||
|
=> await CreatePostWithFileAsync(title, stream, filename, archiveDuration, slowmode, text, embed, options, isSpoiler, allowedMentions, components, stickers, embeds, flags).ConfigureAwait(false);
|
||||||
|
async Task<IThreadChannel> IForumChannel.CreatePostWithFileAsync(string title, FileAttachment attachment, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags)
|
||||||
|
=> await CreatePostWithFileAsync(title, attachment, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags).ConfigureAwait(false);
|
||||||
|
async Task<IThreadChannel> IForumChannel.CreatePostWithFilesAsync(string title, IEnumerable<FileAttachment> attachments, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags)
|
||||||
|
=> await CreatePostWithFilesAsync(title, attachments, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,6 +39,7 @@ namespace Discord.Rest
|
|||||||
ChannelType.Text => RestTextChannel.Create(discord, guild, model),
|
ChannelType.Text => RestTextChannel.Create(discord, guild, model),
|
||||||
ChannelType.Voice => RestVoiceChannel.Create(discord, guild, model),
|
ChannelType.Voice => RestVoiceChannel.Create(discord, guild, model),
|
||||||
ChannelType.Stage => RestStageChannel.Create(discord, guild, model),
|
ChannelType.Stage => RestStageChannel.Create(discord, guild, model),
|
||||||
|
ChannelType.Forum => RestForumChannel.Create(discord, guild, model),
|
||||||
ChannelType.Category => RestCategoryChannel.Create(discord, guild, model),
|
ChannelType.Category => RestCategoryChannel.Create(discord, guild, model),
|
||||||
ChannelType.PublicThread or ChannelType.PrivateThread or ChannelType.NewsThread => RestThreadChannel.Create(discord, guild, model),
|
ChannelType.PublicThread or ChannelType.PrivateThread or ChannelType.NewsThread => RestThreadChannel.Create(discord, guild, model),
|
||||||
_ => new RestGuildChannel(discord, guild, model.Id),
|
_ => new RestGuildChannel(discord, guild, model.Id),
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using Discord.API.Rest;
|
using Discord.API.Rest;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Model = Discord.API.Channel;
|
using Model = Discord.API.Channel;
|
||||||
@@ -60,6 +62,33 @@ namespace Discord.Rest
|
|||||||
return await client.ApiClient.ModifyThreadAsync(channel.Id, apiArgs, options).ConfigureAwait(false);
|
return await client.ApiClient.ModifyThreadAsync(channel.Id, apiArgs, options).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<IReadOnlyCollection<RestThreadChannel>> GetActiveThreadsAsync(IGuild guild, BaseDiscordClient client, RequestOptions options)
|
||||||
|
{
|
||||||
|
var result = await client.ApiClient.GetActiveThreadsAsync(guild.Id, options).ConfigureAwait(false);
|
||||||
|
return result.Threads.Select(x => RestThreadChannel.Create(client, guild, x)).ToImmutableArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<IReadOnlyCollection<RestThreadChannel>> GetPublicArchivedThreadsAsync(IGuildChannel channel, BaseDiscordClient client, int? limit = null,
|
||||||
|
DateTimeOffset? before = null, RequestOptions options = null)
|
||||||
|
{
|
||||||
|
var result = await client.ApiClient.GetPublicArchivedThreadsAsync(channel.Id, before, limit, options);
|
||||||
|
return result.Threads.Select(x => RestThreadChannel.Create(client, channel.Guild, x)).ToImmutableArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<IReadOnlyCollection<RestThreadChannel>> GetPrivateArchivedThreadsAsync(IGuildChannel channel, BaseDiscordClient client, int? limit = null,
|
||||||
|
DateTimeOffset? before = null, RequestOptions options = null)
|
||||||
|
{
|
||||||
|
var result = await client.ApiClient.GetPrivateArchivedThreadsAsync(channel.Id, before, limit, options);
|
||||||
|
return result.Threads.Select(x => RestThreadChannel.Create(client, channel.Guild, x)).ToImmutableArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<IReadOnlyCollection<RestThreadChannel>> GetJoinedPrivateArchivedThreadsAsync(IGuildChannel channel, BaseDiscordClient client, int? limit = null,
|
||||||
|
DateTimeOffset? before = null, RequestOptions options = null)
|
||||||
|
{
|
||||||
|
var result = await client.ApiClient.GetJoinedPrivateArchivedThreadsAsync(channel.Id, before, limit, options);
|
||||||
|
return result.Threads.Select(x => RestThreadChannel.Create(client, channel.Guild, x)).ToImmutableArray();
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task<RestThreadUser[]> GetUsersAsync(IThreadChannel channel, BaseDiscordClient client, RequestOptions options = null)
|
public static async Task<RestThreadUser[]> GetUsersAsync(IThreadChannel channel, BaseDiscordClient client, RequestOptions options = null)
|
||||||
{
|
{
|
||||||
var users = await client.ApiClient.ListThreadMembersAsync(channel.Id, options);
|
var users = await client.ApiClient.ListThreadMembersAsync(channel.Id, options);
|
||||||
@@ -73,5 +102,114 @@ namespace Discord.Rest
|
|||||||
|
|
||||||
return RestThreadUser.Create(client, channel.Guild, model, channel);
|
return RestThreadUser.Create(client, channel.Guild, model, channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<RestThreadChannel> CreatePostAsync(IForumChannel channel, BaseDiscordClient client, string title, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay, int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||||
|
{
|
||||||
|
embeds ??= Array.Empty<Embed>();
|
||||||
|
if (embed != null)
|
||||||
|
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||||
|
|
||||||
|
Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed.");
|
||||||
|
Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed.");
|
||||||
|
Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed.");
|
||||||
|
|
||||||
|
// check that user flag and user Id list are exclusive, same with role flag and role Id list
|
||||||
|
if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue)
|
||||||
|
{
|
||||||
|
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Users) &&
|
||||||
|
allowedMentions.UserIds != null && allowedMentions.UserIds.Count > 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("The Users flag is mutually exclusive with the list of User Ids.", nameof(allowedMentions));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Roles) &&
|
||||||
|
allowedMentions.RoleIds != null && allowedMentions.RoleIds.Count > 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(allowedMentions));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stickers != null)
|
||||||
|
{
|
||||||
|
Preconditions.AtMost(stickers.Length, 3, nameof(stickers), "A max of 3 stickers are allowed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (flags is not MessageFlags.None and not MessageFlags.SuppressEmbeds)
|
||||||
|
throw new ArgumentException("The only valid MessageFlags are SuppressEmbeds and none.", nameof(flags));
|
||||||
|
|
||||||
|
var args = new CreatePostParams()
|
||||||
|
{
|
||||||
|
Title = title,
|
||||||
|
ArchiveDuration = archiveDuration,
|
||||||
|
Slowmode = slowmode,
|
||||||
|
Message = new()
|
||||||
|
{
|
||||||
|
AllowedMentions = allowedMentions.ToModel(),
|
||||||
|
Content = text,
|
||||||
|
Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional<API.Embed[]>.Unspecified,
|
||||||
|
Flags = flags,
|
||||||
|
Components = components?.Components?.Any() ?? false ? components.Components.Select(x => new API.ActionRowComponent(x)).ToArray() : Optional<API.ActionRowComponent[]>.Unspecified,
|
||||||
|
Stickers = stickers?.Any() ?? false ? stickers.Select(x => x.Id).ToArray() : Optional<ulong[]>.Unspecified,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var model = await client.ApiClient.CreatePostAsync(channel.Id, args, options).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return RestThreadChannel.Create(client, channel.Guild, model);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<RestThreadChannel> CreatePostAsync(IForumChannel channel, BaseDiscordClient client, string title, IEnumerable<FileAttachment> attachments, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags)
|
||||||
|
{
|
||||||
|
embeds ??= Array.Empty<Embed>();
|
||||||
|
if (embed != null)
|
||||||
|
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||||
|
|
||||||
|
Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed.");
|
||||||
|
Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed.");
|
||||||
|
Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed.");
|
||||||
|
|
||||||
|
// check that user flag and user Id list are exclusive, same with role flag and role Id list
|
||||||
|
if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue)
|
||||||
|
{
|
||||||
|
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Users) &&
|
||||||
|
allowedMentions.UserIds != null && allowedMentions.UserIds.Count > 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("The Users flag is mutually exclusive with the list of User Ids.", nameof(allowedMentions));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Roles) &&
|
||||||
|
allowedMentions.RoleIds != null && allowedMentions.RoleIds.Count > 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(allowedMentions));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stickers != null)
|
||||||
|
{
|
||||||
|
Preconditions.AtMost(stickers.Length, 3, nameof(stickers), "A max of 3 stickers are allowed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (flags is not MessageFlags.None and not MessageFlags.SuppressEmbeds)
|
||||||
|
throw new ArgumentException("The only valid MessageFlags are SuppressEmbeds and none.", nameof(flags));
|
||||||
|
|
||||||
|
var args = new CreateMultipartPostAsync(attachments.ToArray())
|
||||||
|
{
|
||||||
|
AllowedMentions = allowedMentions.ToModel(),
|
||||||
|
ArchiveDuration = archiveDuration,
|
||||||
|
Content = text,
|
||||||
|
Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional<API.Embed[]>.Unspecified,
|
||||||
|
Flags = flags,
|
||||||
|
MessageComponent = components?.Components?.Any() ?? false ? components.Components.Select(x => new API.ActionRowComponent(x)).ToArray() : Optional<API.ActionRowComponent[]>.Unspecified,
|
||||||
|
Slowmode = slowmode,
|
||||||
|
Stickers = stickers?.Any() ?? false ? stickers.Select(x => x.Id).ToArray() : Optional<ulong[]>.Unspecified,
|
||||||
|
Title = title
|
||||||
|
};
|
||||||
|
|
||||||
|
var model = await client.ApiClient.CreatePostAsync(channel.Id, args, options);
|
||||||
|
|
||||||
|
return RestThreadChannel.Create(client, channel.Guild, model);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -369,7 +369,7 @@ namespace Discord.Rest
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Responses
|
#region Responses
|
||||||
public static async Task<Message> ModifyFollowupMessageAsync(BaseDiscordClient client, RestFollowupMessage message, Action<MessageProperties> func,
|
public static async Task<Discord.API.Message> ModifyFollowupMessageAsync(BaseDiscordClient client, RestFollowupMessage message, Action<MessageProperties> func,
|
||||||
RequestOptions options = null)
|
RequestOptions options = null)
|
||||||
{
|
{
|
||||||
var args = new MessageProperties();
|
var args = new MessageProperties();
|
||||||
@@ -411,7 +411,7 @@ namespace Discord.Rest
|
|||||||
}
|
}
|
||||||
public static async Task DeleteFollowupMessageAsync(BaseDiscordClient client, RestFollowupMessage message, RequestOptions options = null)
|
public static async Task DeleteFollowupMessageAsync(BaseDiscordClient client, RestFollowupMessage message, RequestOptions options = null)
|
||||||
=> await client.ApiClient.DeleteInteractionFollowupMessageAsync(message.Id, message.Token, options);
|
=> await client.ApiClient.DeleteInteractionFollowupMessageAsync(message.Id, message.Token, options);
|
||||||
public static async Task<Message> ModifyInteractionResponseAsync(BaseDiscordClient client, string token, Action<MessageProperties> func,
|
public static async Task<API.Message> ModifyInteractionResponseAsync(BaseDiscordClient client, string token, Action<MessageProperties> func,
|
||||||
RequestOptions options = null)
|
RequestOptions options = null)
|
||||||
{
|
{
|
||||||
var args = new MessageProperties();
|
var args = new MessageProperties();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ namespace Discord.Net.Converters
|
|||||||
|
|
||||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||||
{
|
{
|
||||||
return ulong.Parse((string)reader.Value, NumberStyles.None, CultureInfo.InvariantCulture);
|
return ulong.Parse(reader.Value?.ToString(), NumberStyles.None, CultureInfo.InvariantCulture);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||||
|
|||||||
@@ -0,0 +1,128 @@
|
|||||||
|
using Discord.Rest;
|
||||||
|
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.WebSocket
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a forum channel in a guild.
|
||||||
|
/// </summary>
|
||||||
|
public class SocketForumChannel : SocketGuildChannel, IForumChannel
|
||||||
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool IsNsfw { get; private set; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string Topic { get; private set; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public ThreadArchiveDuration DefaultAutoArchiveDuration { get; private set; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IReadOnlyCollection<ForumTag> Tags { get; private set; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string Mention => MentionUtils.MentionChannel(Id);
|
||||||
|
|
||||||
|
internal SocketForumChannel(DiscordSocketClient discord, ulong id, SocketGuild guild) : base(discord, id, guild) { }
|
||||||
|
|
||||||
|
internal new static SocketForumChannel Create(SocketGuild guild, ClientState state, Model model)
|
||||||
|
{
|
||||||
|
var entity = new SocketForumChannel(guild.Discord, model.Id, guild);
|
||||||
|
entity.Update(state, model);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Update(ClientState state, Model model)
|
||||||
|
{
|
||||||
|
base.Update(state, model);
|
||||||
|
IsNsfw = model.Nsfw.GetValueOrDefault(false);
|
||||||
|
Topic = model.Topic.GetValueOrDefault();
|
||||||
|
DefaultAutoArchiveDuration = model.AutoArchiveDuration.GetValueOrDefault(ThreadArchiveDuration.OneDay);
|
||||||
|
|
||||||
|
Tags = model.ForumTags.GetValueOrDefault(Array.Empty<API.ForumTags>()).Select(
|
||||||
|
x => new ForumTag(x.Id, x.Name, x.EmojiId.GetValueOrDefault(null), x.EmojiName.GetValueOrDefault())
|
||||||
|
).ToImmutableArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IForumChannel.CreatePostAsync(string, ThreadArchiveDuration, int?, string, Embed, RequestOptions, AllowedMentions, MessageComponent, ISticker[], Embed[], MessageFlags)"/>
|
||||||
|
public Task<RestThreadChannel> CreatePostAsync(string title, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay, int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||||
|
=> ThreadHelper.CreatePostAsync(this, Discord, title, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IForumChannel.CreatePostWithFileAsync(string, string, ThreadArchiveDuration, int?, string, Embed, RequestOptions, bool, AllowedMentions, MessageComponent, ISticker[], Embed[], MessageFlags)"/>
|
||||||
|
public async Task<RestThreadChannel> CreatePostWithFileAsync(string title, string filePath, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay,
|
||||||
|
int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, bool isSpoiler = false,
|
||||||
|
AllowedMentions allowedMentions = null, MessageComponent components = null,
|
||||||
|
ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||||
|
{
|
||||||
|
using var file = new FileAttachment(filePath, isSpoiler: isSpoiler);
|
||||||
|
return await ThreadHelper.CreatePostAsync(this, Discord, title, new FileAttachment[] { file }, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IForumChannel.CreatePostWithFileAsync(string, Stream, string, ThreadArchiveDuration, int?, string, Embed, RequestOptions, bool, AllowedMentions, MessageComponent, ISticker[], Embed[], MessageFlags)"/>
|
||||||
|
public async Task<RestThreadChannel> CreatePostWithFileAsync(string title, Stream stream, string filename, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay,
|
||||||
|
int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, bool isSpoiler = false,
|
||||||
|
AllowedMentions allowedMentions = null, MessageComponent components = null,
|
||||||
|
ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||||
|
{
|
||||||
|
using var file = new FileAttachment(stream, filename, isSpoiler: isSpoiler);
|
||||||
|
return await ThreadHelper.CreatePostAsync(this, Discord, title, new FileAttachment[] { file }, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IForumChannel.CreatePostWithFileAsync(string, FileAttachment, ThreadArchiveDuration, int?, string, Embed, RequestOptions, AllowedMentions, MessageComponent, ISticker[], Embed[], MessageFlags)"/>
|
||||||
|
public Task<RestThreadChannel> CreatePostWithFileAsync(string title, FileAttachment attachment, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay,
|
||||||
|
int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
|
||||||
|
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||||
|
=> ThreadHelper.CreatePostAsync(this, Discord, title, new FileAttachment[] { attachment }, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IForumChannel.CreatePostWithFilesAsync(string, IEnumerable{FileAttachment}, ThreadArchiveDuration, int?, string, Embed, RequestOptions, AllowedMentions, MessageComponent, ISticker[], Embed[], MessageFlags)"/>
|
||||||
|
public Task<RestThreadChannel> CreatePostWithFilesAsync(string title, IEnumerable<FileAttachment> attachments, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay,
|
||||||
|
int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
|
||||||
|
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||||
|
=> ThreadHelper.CreatePostAsync(this, Discord, title, attachments, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IForumChannel.GetActiveThreadsAsync(RequestOptions)"/>
|
||||||
|
public Task<IReadOnlyCollection<RestThreadChannel>> GetActiveThreadsAsync(RequestOptions options = null)
|
||||||
|
=> ThreadHelper.GetActiveThreadsAsync(Guild, Discord, options);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IForumChannel.GetJoinedPrivateArchivedThreadsAsync(int?, DateTimeOffset?, RequestOptions)"/>
|
||||||
|
public Task<IReadOnlyCollection<RestThreadChannel>> GetJoinedPrivateArchivedThreadsAsync(int? limit = null, DateTimeOffset? before = null, RequestOptions options = null)
|
||||||
|
=> ThreadHelper.GetJoinedPrivateArchivedThreadsAsync(this, Discord, limit, before, options);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IForumChannel.GetPrivateArchivedThreadsAsync(int?, DateTimeOffset?, RequestOptions)"/>
|
||||||
|
public Task<IReadOnlyCollection<RestThreadChannel>> GetPrivateArchivedThreadsAsync(int? limit = null, DateTimeOffset? before = null, RequestOptions options = null)
|
||||||
|
=> ThreadHelper.GetPrivateArchivedThreadsAsync(this, Discord, limit, before, options);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IForumChannel.GetPublicArchivedThreadsAsync(int?, DateTimeOffset?, RequestOptions)"/>
|
||||||
|
public Task<IReadOnlyCollection<RestThreadChannel>> GetPublicArchivedThreadsAsync(int? limit = null, DateTimeOffset? before = null, RequestOptions options = null)
|
||||||
|
=> ThreadHelper.GetPublicArchivedThreadsAsync(this, Discord, limit, before, options);
|
||||||
|
|
||||||
|
#region IForumChannel
|
||||||
|
async Task<IReadOnlyCollection<IThreadChannel>> IForumChannel.GetActiveThreadsAsync(RequestOptions options)
|
||||||
|
=> await GetActiveThreadsAsync(options).ConfigureAwait(false);
|
||||||
|
async Task<IReadOnlyCollection<IThreadChannel>> IForumChannel.GetPublicArchivedThreadsAsync(int? limit, DateTimeOffset? before, RequestOptions options)
|
||||||
|
=> await GetPublicArchivedThreadsAsync(limit, before, options).ConfigureAwait(false);
|
||||||
|
async Task<IReadOnlyCollection<IThreadChannel>> IForumChannel.GetPrivateArchivedThreadsAsync(int? limit, DateTimeOffset? before, RequestOptions options)
|
||||||
|
=> await GetPrivateArchivedThreadsAsync(limit, before, options).ConfigureAwait(false);
|
||||||
|
async Task<IReadOnlyCollection<IThreadChannel>> IForumChannel.GetJoinedPrivateArchivedThreadsAsync(int? limit, DateTimeOffset? before, RequestOptions options)
|
||||||
|
=> await GetJoinedPrivateArchivedThreadsAsync(limit, before, options).ConfigureAwait(false);
|
||||||
|
async Task<IThreadChannel> IForumChannel.CreatePostAsync(string title, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags)
|
||||||
|
=> await CreatePostAsync(title, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags).ConfigureAwait(false);
|
||||||
|
async Task<IThreadChannel> IForumChannel.CreatePostWithFileAsync(string title, string filePath, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags)
|
||||||
|
=> await CreatePostWithFileAsync(title, filePath, archiveDuration, slowmode, text, embed, options, isSpoiler, allowedMentions, components, stickers, embeds, flags).ConfigureAwait(false);
|
||||||
|
async Task<IThreadChannel> IForumChannel.CreatePostWithFileAsync(string title, Stream stream, string filename, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags)
|
||||||
|
=> await CreatePostWithFileAsync(title, stream, filename, archiveDuration, slowmode, text, embed, options, isSpoiler, allowedMentions, components, stickers, embeds, flags).ConfigureAwait(false);
|
||||||
|
async Task<IThreadChannel> IForumChannel.CreatePostWithFileAsync(string title, FileAttachment attachment, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags)
|
||||||
|
=> await CreatePostWithFileAsync(title, attachment, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags).ConfigureAwait(false);
|
||||||
|
async Task<IThreadChannel> IForumChannel.CreatePostWithFilesAsync(string title, IEnumerable<FileAttachment> attachments, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags)
|
||||||
|
=> await CreatePostWithFilesAsync(title, attachments, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -59,6 +59,7 @@ namespace Discord.WebSocket
|
|||||||
ChannelType.Category => SocketCategoryChannel.Create(guild, state, model),
|
ChannelType.Category => SocketCategoryChannel.Create(guild, state, model),
|
||||||
ChannelType.PrivateThread or ChannelType.PublicThread or ChannelType.NewsThread => SocketThreadChannel.Create(guild, state, model),
|
ChannelType.PrivateThread or ChannelType.PublicThread or ChannelType.NewsThread => SocketThreadChannel.Create(guild, state, model),
|
||||||
ChannelType.Stage => SocketStageChannel.Create(guild, state, model),
|
ChannelType.Stage => SocketStageChannel.Create(guild, state, model),
|
||||||
|
ChannelType.Forum => SocketForumChannel.Create(guild, state, model),
|
||||||
_ => new SocketGuildChannel(guild.Discord, model.Id, guild),
|
_ => new SocketGuildChannel(guild.Discord, model.Id, guild),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -705,7 +705,15 @@ namespace Discord.WebSocket
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
public SocketThreadChannel GetThreadChannel(ulong id)
|
public SocketThreadChannel GetThreadChannel(ulong id)
|
||||||
=> GetChannel(id) as SocketThreadChannel;
|
=> GetChannel(id) as SocketThreadChannel;
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a forum channel in this guild.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The snowflake identifier for the forum channel.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// A forum channel associated with the specified <paramref name="id" />; <see langword="null"/> if none is found.
|
||||||
|
/// </returns>
|
||||||
|
public SocketForumChannel GetForumChannel(ulong id)
|
||||||
|
=> GetChannel(id) as SocketForumChannel;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a voice channel in this guild.
|
/// Gets a voice channel in this guild.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user