Merge Labs 3.X into dev (#1923)
* meta: bump version * Null or empty fix (#176) * Add components and stickers to ReplyAsync extension * Fixed null or empty * Changed Label to Description * -||- Co-authored-by: quin lynch <lynchquin@gmail.com> * More regions (#177) * Preconditions * ChannelHelper * RestDMChannel * RestGroupChannel * RestBan * RestGroupUser * EntityExtensions * DiscordSocketClient * DiscordSocketClient * Discord.net.core.xml fix (#178) * Changed Label to Description * Added Discord- .MessageComponent .ISticker[] ,Discord.MessageComponent,Discord.ISticker[] to ReplyAsync * Remove references to labs * Update Discord.Net.sln * Added SendMessagesInThreads and StartEmbeddedActivities. (#175) * Added SendMessagesInThreads and StartEmbeddedActivities. Adjusted owner perms. Change UsePublicThreads -> CreatePublicThreads Change UsePrivateThreads -> CreatePrivateThreads * removed extra /// * Added UsePublicThreads and UsePrivateThreads back with Obsolete Attribute * removed 'false' from Obsolete Attribute * Squashed commit of the following: commit dca41a348e36a9b4e7006ef3a76377eb32aad276 Author: quin lynch <lynchquin@gmail.com> Date: Thu Sep 23 07:02:19 2021 -0300 Autocomplete commands * meta: xml. closes #171 * Revert user agent and $device to dnet * meta: bump version * meta: bump vers * Fix sticker args * Grammer fix (#179) * Made IVoiceChannel mentionable * Embeds array for send message async (#181) * meta: bump version * meta: bump vers * Fix sticker args * Grammer fix (#179) * Added embeds for SendMessageAsync * [JsonProperty("embed")] forgot to remove this public Optional<Embed> Embed { get; set; } * It has been done as requested. * Changed the old way of handeling single embeds * Moved embeds param and added options param * xmls Co-authored-by: quin lynch <lynchquin@gmail.com> * Fix thread permissions (#183) * Update GuildPermissionsTests.cs * Update GuildPermissions.cs * Use compound assignment (#186) * Used compound assignment * -||- * -||- * Remove unnecessary suppression (#188) * Inlined variable declarations (#185) * Fixed some warnings (#184) * Fixed some warnings * Another fixed warning * Changed the SSendFileAsync to SendFileAsync * Removed para AlwaysAcknowledgeInteractions * Moved it back to the previous version * Added periods to the end like quin requested!! :(( Co-authored-by: MrCakeSlayer <13650699+MrCakeSlayer@users.noreply.github.com> * Object initialization can be simplified fixed (#189) * Conditional-expression-simplification (#193) * Capitlazation fixes (#192) * Removed-this. (#191) * Use 'switch' expression (#187) * Use 'switch' expression * Reverted it to the old switch case * Fixed-compiler-error (#194) * Submitting updates to include new permissions. (#195) * Submitting updates to include new permissions. * Make old permissions obsolete and update tests Co-authored-by: quin lynch <lynchquin@gmail.com> * Update azure-pipelines.yml * Update azure-pipelines.yml * Update azure-pipelines.yml * Add support for long in autocomplete option * Add support for sending files with multiple embeds (#196) * Add support for sending files with multiple embeds * Simplify prepending single embed to embed array * Consistency for embeds endpoints (#197) * Changed the way of handling prepending of embeds. For consistency. * reformatted the summary * Revert pipeline * Fix duplicate merge conflicts * Changed minimum slash command name length to 1 per Discord API docs (#198) * Channel endpoints requirements correction (#199) * Added some requirements to channels for topic * Changed check from NotNullOrEmpty to NotNullOrEmpty * Added some requirements to channels for name Preconditions.LessThan * Formatting of file * Added restriction for description not being null (#200) * Update azure-pipelines.yml * Update deploy.yml * Remove version tag from proj * Update deploy.yml * Removed versions from project files * Removed style of the nuget badge and added logo (#201) The style was not properly added to it and the plastic version does not look good with the discord badge. I thought it would look better with a logo * Fix Type not being set in SocketApplicationCommand * Remove useless GuildId property * meta: update XML * Add Autocomplete to SlashCommandOptionBuilder * Added autocomplete in SlashCommandOptionBuilder. (#206) Co-authored-by: Quin Lynch <49576606+quinchs@users.noreply.github.com> * Fix duplicate autocomplete * Fix #208 * Fix sub commands being interpreted as a parameter for autocomplete * Fix exposed optional * Support the discord:// protocol in buttons (#207) * Update UrlValidation.cs * Update ComponentBuilder.cs * Add docs and better error messages. * Fix wonky intentation * Add competing activity status type (#205) * Update GuildPermissionsTests.cs * Update GuildPermissions.cs * Add competing status type * Add Icons to IRole (#204) * Added icon field to IRole * Added GetGuildRoleIconUrl() * Added Clean Content Function (#174) * Added Clean Content Function * Fixed Spelling problems and bad var handling * Add StripMarkDown Method * Clean Content Expanded (#212) * Implement CleanContent In IMessage & RestMessage * Update Spelling and Documentation * Add SanatizeMessage to MessageHelper and Refactor Rest and Socket Message * Add event for autocomplete interaction (#214) * Spelling corrections (#215) * Remove null collections * Followup with file async warnings (#216) * Changed from NotNullOrWhitespace to NotNullOrEmpty * Added NotNullOrEmpty on filename * Added system to interpret from the path * Added a check for if it contains a period * It has been done, how ever it will break stuff * Changed to use ??= how ever still added error check * Added space under check * Changed from with a period to valid file extension * Added checks for SendFileAsync * Removed filename != null && * Add channel types in application command options. (#217) * add channel types in application command options * Indent Docs * Stage instance audit logs as well as thread audit log type * Update azure-pipelines.yml * Update azure-pipelines.yml * Fix system messages not including mentioned users. Added ContextMenuCommand message type * Remove file extension check (#218) * Fix NRE in modify guild channel * Fix 429's not being accounted for in ratelimit updates * meta: add net5 framework Co-Authored-By: MrCakeSlayer <13650699+MrCakeSlayer@users.noreply.github.com> * Proper doc logos (#221) * Update GuildPermissionsTests.cs * Update GuildPermissions.cs * Add competing activity status type * logo changes * logo text as path * add missing logo * Update package logo and favicon * Update docfx references * Remove XML files and use original pipeline format * Remove console writeline * Remove Console.WriteLine * Remove useless log * Rename Available sticker field to IsAvailable * Rename Available to IsAvailable in stickers * Add summary indent for role members * Add summary indent to SocketInvite * Rename DefaultPermission to IsDefaultPermission * Rename Default to IsDefault and Required to IsRequired in IApplicationCommandOption * Rename Default and Required to IsDefault and IsRequired in IApplicationCommandOption. Rename DefaultPermission to IsDefaultPermission in IApplicationCommand * Remove extra white spaces * Renamed Joined, Archived, and Locked to HasJoined, IsArchived, and IsLocked * Rename Live and DiscoverableDisabled to IsDiscoverableDisabled and IsLive in IStageChannel * Remove newline * Add indent to summaries * Remove unnecessary json serializer field * Fix ToEntity for roletags incorrectly using IsPremiumSubscriber * Update RestChannel for new channel types * Fix different rest channels not deserializing properly * fully qualify internal for UrlValidation and add indent to summary * Add missing periods to InteractionResponseType * Fix summary in IApplicationCommandOptionChoice * Update IApplicationCommandOption summaries * Update IApplicationCommandInteractionDataOption summaries * Update IApplicationCommandInteractionData summaries * Update IApplicationCommand summaries * Update ApplicationCommandType summaries * rename DefaultPermission to IsDefaultPermission in ApplicationCommandProperties * update ApplicationCommandOptionChoiceProperties summaries * Rename Default, Required, and Autocomplete to IsDefault, IsRequired, and IsAutocomplete in ApplicationCommandOptionProperties * Update SlashCommandProperties summaries * update SlashCommandBuilder boolean field names, summaries, and choice parameters * Update SelectMenuOption summaries, Rename Default to IsDefault in SelectMenuOption * update SelectMenuComponent summaries. Rename Disabled to IsDisabled in SelectMenuComponent * update ComponentBuilder summaries and boolean fields. * Update ButtonComponent summaries and boolean fields * update ActionRowComponent summaries * Update UserCommandBuilder * Update MessageCommandBuilder summaries and boolean properties * Update IGuild summary * Update IGuild summaries * Update StagePrivacyLevel summary * update IThreadChannel summaries * Update IStageChannel summaries * Refactor summaries and boolean property names * General cleanup (#223) * General cleanup * Add Async suffix to SendAutocompleteResult * Fix more formatting * Fix unused RequestOptions in GetActiveThreadsAsync * Add message to ArgumentNullException * Ephemeral attachments * Add missing jsonproperty attribute * Add IMessage.Interaction * Update attachment checks for embed urls * meta: bump version * Remove old package configs and update image * Update package logos * Fix logo reference for azure * Deprecate old package definitions in favor for target file * Deprecate old package definitions in favor for target file Co-authored-by: Jared L <48422312+lhjt@users.noreply.github.com> * Update package ids * Fix url validation * meta: bump version * Fix assignment of UserMentions (#233) * Fix CleanContent (#231) * Fix SocketSlashCommandData access modifier. (#237) Fixes #229 * Update README with better header (#232) * Update README with better header Adds HTML elements that implement the main logo & improve the redirection tag positions. * Resolving border issue in light-mode * Update sponsor section * Implement checks for interaction respond times and multiple interaction responses. closes #236, #235 * Add response check to socket auto complete * meta: bump versions * Fix #239 * meta: bump version * meta: update logo * meta: bump versions * Revert received at time, confirmed by discord staff to be accurate * Merge branch 'release/3.x' of https://github.com/Discord-Net-Labs/Discord.Net-Labs into merger-labs Update requested changes of obsolete and references to labs. Added `Interaction` to `IMessage` Fixed grammar Fixed bugs relating to interactions. * Update docs * Update CHANGELOG.md * meta: docs building * Update docs.yml * Update docs.yml * Fix docfx version * Update docs.yml * Update docs.bat * Rename docs repo for clone * update docfx version * Update docs.bat * Update docfx version * Remove docs from pipeline * FAQ revamped, metadata updated (#241) * FAQ revamped, metadata updated * Update FAQ.md * Update README.md * Docs index improvement * Fix InvalidOperationException in modify channel * feature: guild avatars, closes #238 * feature: modify role icons * meta: changelog * meta: bump version * Update README.md * Fix non value type options not being included in autocomplete * Add new activity flags (#254) * Add new activity flags * Add missing commas * Added support for GUILD_JOIN_REQUEST_DELETE event (#253) Fixes #247 * Adding BotHTTPInteraction user flag (#252) * animated guild banner support (#255) * Docs work (WIP) (#242) * Main page work * Metadata logo dir * More main page edits * Naming change * Dnet guide entries pruned * Add student hub guild directory channel (#256) * animated guild banner support * Add guild directory channel * Fix followup with file overwrite having incorrect parameter locations * Merge labs 3.x * Update GUILD_JOIN_REQUEST_DELETE event * Update head.tmpl.partial * Removed BannerId and AccentColor (#260) * Removed BannerId property, GetBannerURL method, and AccentColor property from IUser and socket entities. * Fixed errors in IUser.cs * Added back summary for GetAvatarUrl method in IUser.cs * Support Guild Boost Progress Bars (#262) * Support Guild Boost Progress Bars * Update SocketChannel.cs * Fix non-optional and unnecessary values. * Spelling * Reordering and consistency. * Remove log for reconnect * Add missing flags to SystemChannelMessageDeny (#267) * Fix labs reference in analyzer project and provider project * Rename new activity flags * Guild feature revamp and smart gateway intent checks * Get thread user implementation * Amend creating slash command guide (#269) * Adding BotHTTPInteraction user flag * Added comments explaining the Global command create stipulations. * Fix numeric type check for options * Add state checking to ConnectionManager.StartAsync (#272) * initial interface changes * Multi file upload + attachment editing * meta: bump versions * Update CHANGELOG.md * Update CHANGELOG.md * Support Min and Max values on ApplicationCommandOptions (#273) * Support Min and Max values on ApplicationCommandOptions * Support decimal min/max values * Docs imrpovments + use ToNullable * Logomark, doc settings edit (#258) * Logomark, doc settings edit * Replace standard logo * Bumping docfx plugins to latest release * Bump version metadata * Logo svg fix * Change default sticker behavior and add AlwaysResolveSticker to the config * Implement rest based interactions. Added ED25519 checks. Updated summaries. * Update package logo * Automatically fix ordering of optional command options (#276) * auto fix optional command option order * clean up indentation * Fix maximum number of Select Menu Options (#282) As of https://discord.com/developers/docs/interactions/message-components#select-menu-object-select-menu-structure the maximum number of options is 25, not less than 25. Hopefully the change catches all necessary locations * Add voice region to modify voice channels * Update summaries on rest interactions * Interaction Specific Interfaces (#283) * added interaction specific interfaces * fix build error * implement change requests * Update application * Add Guild Scheduled Events (#279) * guild events initial * sharded events * Add new gateway intents and fix bugs * More work on new changes to guild events * Update guild scheduled events * Added events to extended guild and add event start event * Update preconditions * Implement breaking changes guild guild events. Add guild event permissions * Update tests and change privacy level requirements * Update summaries and add docs for guild events * meta: bump version * Increment meta version (#285) * Increment meta version * Update docfx.json * Fix #289 and add configureawaits to rest based interactions * meta: bump version * Add GUILD_SCHEDULED_EVENT_USER_ADD and GUILD_SCHEDULED_EVENT_USER_REMOVE (#287) * Remove newline * Fix autocomplete result value * meta: bump versions * Add `GuildScheduledEventUserAdd` and `GuildScheduledEventUserRemove` to sharded client * Make RestUserCommand public (#292) * Fix Components not showing on FUWF (#288) (#293) Adds Components to Payload JSON Generation * Implement smarter rest resolvable interaction data. Fixes #294 * Add UseInteractionSnowflakeDate to config #286 * Implement Better Discord Errors (#291) * Initial error parsing * Implement better errors * Add missing error codes * Add voice disconnect opcodes * Remove unused class, add summaries to discordjsonerror, and remove public constructor of slash command properties * Add error code summary * Update error message summary * Update src/Discord.Net.Core/DiscordJsonError.cs Co-authored-by: Jared L <48422312+lhjt@users.noreply.github.com> * Update src/Discord.Net.WebSocket/API/Voice/VoiceCloseCode.cs Co-authored-by: Jared L <48422312+lhjt@users.noreply.github.com> * Fix autocomplete result value Co-authored-by: Jared L <48422312+lhjt@users.noreply.github.com> * Change the minimum length of slash commands to 1 (#284) * Change the minimum length of slash commands to 1. This is the correct value according to the docs and it has been changed after user feedback. * Fix the limit in 3 other places Co-authored-by: quin lynch <lynchquin@gmail.com> * Add new thread creation properties * Add role emoji. Fixes #295 * Fix mocked text channel * Fix precondition checks. Closes #281 * Initial fix (#297) * meta: bump version * Update from release/3.x * Remove more labs references * Remove doc file for Discord.Net.Analyzers Co-authored-by: Simon Hjorthøj <sh2@live.dk> Co-authored-by: drobbins329 <drobbins329@gmail.com> Co-authored-by: MrCakeSlayer <13650699+MrCakeSlayer@users.noreply.github.com> Co-authored-by: d4n3436 <dan3436@hotmail.com> Co-authored-by: Will <WilliamWelsh@users.noreply.github.com> Co-authored-by: Eugene Garbuzov <kkxo.mail@gmail.com> Co-authored-by: CottageDwellingCat <80918250+CottageDwellingCat@users.noreply.github.com> Co-authored-by: Emily <89871431+emillly-b@users.noreply.github.com> Co-authored-by: marens101 <marens101@gmail.com> Co-authored-by: Jared L <48422312+lhjt@users.noreply.github.com> Co-authored-by: Armano den Boef <68127614+Rozen4334@users.noreply.github.com> Co-authored-by: Bill <billchirico@gmail.com> Co-authored-by: Liege72 <65319395+Liege72@users.noreply.github.com> Co-authored-by: Floowey <floowey@gmx.at> Co-authored-by: Cenk Ergen <57065323+Cenngo@users.noreply.github.com> Co-authored-by: exsersewo <exsersewo@systemexit.co.uk> Co-authored-by: Dennis Fischer <fischer_dennis@live.de>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="../../Discord.Net.targets" />
|
||||
<PropertyGroup>
|
||||
<AssemblyName>Discord.Net.Analyzers</AssemblyName>
|
||||
@@ -7,7 +7,7 @@
|
||||
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis" Version="3.3.1" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis" Version="3.11.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Discord.Net.Commands\Discord.Net.Commands.csproj" />
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Discord.Commands
|
||||
/// <code language="cs">
|
||||
/// [Command("stats")]
|
||||
/// [Alias("stat", "info")]
|
||||
/// public async Task GetStatsAsync(IUser user)
|
||||
/// public <see langword="async"/> Task GetStatsAsync(IUser user)
|
||||
/// {
|
||||
/// // ...pull stats
|
||||
/// }
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace Discord.Commands.Builders
|
||||
{
|
||||
public class CommandBuilder
|
||||
{
|
||||
#region CommandBuilder
|
||||
private readonly List<PreconditionAttribute> _preconditions;
|
||||
private readonly List<ParameterBuilder> _parameters;
|
||||
private readonly List<Attribute> _attributes;
|
||||
@@ -27,8 +28,9 @@ namespace Discord.Commands.Builders
|
||||
public IReadOnlyList<ParameterBuilder> Parameters => _parameters;
|
||||
public IReadOnlyList<Attribute> Attributes => _attributes;
|
||||
public IReadOnlyList<string> Aliases => _aliases;
|
||||
#endregion
|
||||
|
||||
//Automatic
|
||||
#region Automatic
|
||||
internal CommandBuilder(ModuleBuilder module)
|
||||
{
|
||||
Module = module;
|
||||
@@ -38,7 +40,9 @@ namespace Discord.Commands.Builders
|
||||
_attributes = new List<Attribute>();
|
||||
_aliases = new List<string>();
|
||||
}
|
||||
//User-defined
|
||||
#endregion
|
||||
|
||||
#region User-defined
|
||||
internal CommandBuilder(ModuleBuilder module, string primaryAlias, Func<ICommandContext, object[], IServiceProvider, CommandInfo, Task> callback)
|
||||
: this(module)
|
||||
{
|
||||
@@ -132,7 +136,7 @@ namespace Discord.Commands.Builders
|
||||
var firstMultipleParam = _parameters.FirstOrDefault(x => x.IsMultiple);
|
||||
if ((firstMultipleParam != null) && (firstMultipleParam != lastParam))
|
||||
throw new InvalidOperationException($"Only the last parameter in a command may have the Multiple flag. Parameter: {firstMultipleParam.Name} in {PrimaryAlias}");
|
||||
|
||||
|
||||
var firstRemainderParam = _parameters.FirstOrDefault(x => x.IsRemainder);
|
||||
if ((firstRemainderParam != null) && (firstRemainderParam != lastParam))
|
||||
throw new InvalidOperationException($"Only the last parameter in a command may have the Remainder flag. Parameter: {firstRemainderParam.Name} in {PrimaryAlias}");
|
||||
@@ -140,5 +144,6 @@ namespace Discord.Commands.Builders
|
||||
|
||||
return new CommandInfo(this, info, service);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace Discord.Commands.Builders
|
||||
{
|
||||
public class ModuleBuilder
|
||||
{
|
||||
#region ModuleBuilder
|
||||
private readonly List<CommandBuilder> _commands;
|
||||
private readonly List<ModuleBuilder> _submodules;
|
||||
private readonly List<PreconditionAttribute> _preconditions;
|
||||
@@ -27,8 +28,9 @@ namespace Discord.Commands.Builders
|
||||
public IReadOnlyList<string> Aliases => _aliases;
|
||||
|
||||
internal TypeInfo TypeInfo { get; set; }
|
||||
#endregion
|
||||
|
||||
//Automatic
|
||||
#region Automatic
|
||||
internal ModuleBuilder(CommandService service, ModuleBuilder parent)
|
||||
{
|
||||
Service = service;
|
||||
@@ -40,7 +42,9 @@ namespace Discord.Commands.Builders
|
||||
_attributes = new List<Attribute>();
|
||||
_aliases = new List<string>();
|
||||
}
|
||||
//User-defined
|
||||
#endregion
|
||||
|
||||
#region User-defined
|
||||
internal ModuleBuilder(CommandService service, ModuleBuilder parent, string primaryAlias)
|
||||
: this(service, parent)
|
||||
{
|
||||
@@ -132,5 +136,6 @@ namespace Discord.Commands.Builders
|
||||
public ModuleInfo Build(CommandService service, IServiceProvider services) => BuildImpl(service, services);
|
||||
|
||||
internal ModuleInfo Build(CommandService service, IServiceProvider services, ModuleInfo parent) => BuildImpl(service, services, parent);
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace Discord.Commands
|
||||
builder.AddAliases(alias.Aliases);
|
||||
break;
|
||||
case GroupAttribute group:
|
||||
builder.Name = builder.Name ?? group.Prefix;
|
||||
builder.Name ??= group.Prefix;
|
||||
builder.Group = group.Prefix;
|
||||
builder.AddAliases(group.Prefix);
|
||||
break;
|
||||
@@ -158,7 +158,7 @@ namespace Discord.Commands
|
||||
case CommandAttribute command:
|
||||
builder.AddAliases(command.Text);
|
||||
builder.RunMode = command.RunMode;
|
||||
builder.Name = builder.Name ?? command.Text;
|
||||
builder.Name ??= command.Text;
|
||||
builder.IgnoreExtraArgs = command.IgnoreExtraArgs ?? service._ignoreExtraArgs;
|
||||
break;
|
||||
case NameAttribute name:
|
||||
@@ -291,7 +291,7 @@ namespace Discord.Commands
|
||||
return reader;
|
||||
}
|
||||
|
||||
//We dont have a cached type reader, create one
|
||||
//We don't have a cached type reader, create one
|
||||
reader = ReflectionUtils.CreateObject<TypeReader>(typeReaderType.GetTypeInfo(), service, services);
|
||||
service.AddTypeReader(paramType, reader, false);
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace Discord.Commands.Builders
|
||||
{
|
||||
public class ParameterBuilder
|
||||
{
|
||||
#region ParameterBuilder
|
||||
private readonly List<ParameterPreconditionAttribute> _preconditions;
|
||||
private readonly List<Attribute> _attributes;
|
||||
|
||||
@@ -24,8 +25,9 @@ namespace Discord.Commands.Builders
|
||||
|
||||
public IReadOnlyList<ParameterPreconditionAttribute> Preconditions => _preconditions;
|
||||
public IReadOnlyList<Attribute> Attributes => _attributes;
|
||||
#endregion
|
||||
|
||||
//Automatic
|
||||
#region Automatic
|
||||
internal ParameterBuilder(CommandBuilder command)
|
||||
{
|
||||
_preconditions = new List<ParameterPreconditionAttribute>();
|
||||
@@ -33,7 +35,9 @@ namespace Discord.Commands.Builders
|
||||
|
||||
Command = command;
|
||||
}
|
||||
//User-defined
|
||||
#endregion
|
||||
|
||||
#region User-defined
|
||||
internal ParameterBuilder(CommandBuilder command, string name, Type type)
|
||||
: this(command)
|
||||
{
|
||||
@@ -127,10 +131,11 @@ namespace Discord.Commands.Builders
|
||||
|
||||
internal ParameterInfo Build(CommandInfo info)
|
||||
{
|
||||
if ((TypeReader ?? (TypeReader = GetReader(ParameterType))) == null)
|
||||
if ((TypeReader ??= GetReader(ParameterType)) == null)
|
||||
throw new InvalidOperationException($"No type reader found for type {ParameterType.Name}, one must be specified");
|
||||
|
||||
return new ParameterInfo(this, info, Command.Module.Service);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace Discord.Commands
|
||||
/// </remarks>
|
||||
public class CommandService : IDisposable
|
||||
{
|
||||
#region CommandService
|
||||
/// <summary>
|
||||
/// Occurs when a command-related information is received.
|
||||
/// </summary>
|
||||
@@ -131,8 +132,9 @@ namespace Discord.Commands
|
||||
entityTypeReaders.Add((typeof(IUser), typeof(UserTypeReader<>)));
|
||||
_entityTypeReaders = entityTypeReaders.ToImmutable();
|
||||
}
|
||||
#endregion
|
||||
|
||||
//Modules
|
||||
#region Modules
|
||||
public async Task<ModuleInfo> CreateModuleAsync(string primaryAlias, Action<ModuleBuilder> buildFunc)
|
||||
{
|
||||
await _moduleLock.WaitAsync().ConfigureAwait(false);
|
||||
@@ -187,7 +189,7 @@ namespace Discord.Commands
|
||||
/// </returns>
|
||||
public async Task<ModuleInfo> AddModuleAsync(Type type, IServiceProvider services)
|
||||
{
|
||||
services = services ?? EmptyServiceProvider.Instance;
|
||||
services ??= EmptyServiceProvider.Instance;
|
||||
|
||||
await _moduleLock.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
@@ -222,7 +224,7 @@ namespace Discord.Commands
|
||||
/// </returns>
|
||||
public async Task<IEnumerable<ModuleInfo>> AddModulesAsync(Assembly assembly, IServiceProvider services)
|
||||
{
|
||||
services = services ?? EmptyServiceProvider.Instance;
|
||||
services ??= EmptyServiceProvider.Instance;
|
||||
|
||||
await _moduleLock.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
@@ -322,8 +324,9 @@ namespace Discord.Commands
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
//Type Readers
|
||||
#region Type Readers
|
||||
/// <summary>
|
||||
/// Adds a custom <see cref="TypeReader" /> to this <see cref="CommandService" /> for the supplied object
|
||||
/// type.
|
||||
@@ -448,8 +451,9 @@ namespace Discord.Commands
|
||||
}
|
||||
return null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
//Execution
|
||||
#region Execution
|
||||
/// <summary>
|
||||
/// Searches for the command.
|
||||
/// </summary>
|
||||
@@ -503,7 +507,7 @@ namespace Discord.Commands
|
||||
/// </returns>
|
||||
public async Task<IResult> ExecuteAsync(ICommandContext context, string input, IServiceProvider services, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
|
||||
{
|
||||
services = services ?? EmptyServiceProvider.Instance;
|
||||
services ??= EmptyServiceProvider.Instance;
|
||||
|
||||
var searchResult = Search(input);
|
||||
if (!searchResult.IsSuccess)
|
||||
@@ -598,11 +602,13 @@ namespace Discord.Commands
|
||||
//If we get this far, at least one parse was successful. Execute the most likely overload.
|
||||
var chosenOverload = successfulParses[0];
|
||||
var result = await chosenOverload.Key.ExecuteAsync(context, chosenOverload.Value, services).ConfigureAwait(false);
|
||||
if (!result.IsSuccess && !(result is RuntimeResult || result is ExecuteResult)) // succesful results raise the event in CommandInfo#ExecuteInternalAsync (have to raise it there b/c deffered execution)
|
||||
if (!result.IsSuccess && !(result is RuntimeResult || result is ExecuteResult)) // successful results raise the event in CommandInfo#ExecuteInternalAsync (have to raise it there b/c deferred execution)
|
||||
await _commandExecutedEvent.InvokeAsync(chosenOverload.Key.Command, context, result);
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Dispose
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_isDisposed)
|
||||
@@ -620,5 +626,6 @@ namespace Discord.Commands
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,4 +12,4 @@
|
||||
<ProjectReference Include="..\Discord.Net.Core\Discord.Net.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -51,8 +51,7 @@ namespace Discord.Commands
|
||||
if (endPos == -1) return false;
|
||||
if (text.Length < endPos + 2 || text[endPos + 1] != ' ') return false; //Must end in "> "
|
||||
|
||||
ulong userId;
|
||||
if (!MentionUtils.TryParseUser(text.Substring(0, endPos + 1), out userId)) return false;
|
||||
if (!MentionUtils.TryParseUser(text.Substring(0, endPos + 1), out ulong userId)) return false;
|
||||
if (userId == user.Id)
|
||||
{
|
||||
argPos = endPos + 2;
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace Discord.Commands
|
||||
|
||||
public async Task<PreconditionResult> CheckPreconditionsAsync(ICommandContext context, IServiceProvider services = null)
|
||||
{
|
||||
services = services ?? EmptyServiceProvider.Instance;
|
||||
services ??= EmptyServiceProvider.Instance;
|
||||
|
||||
async Task<PreconditionResult> CheckGroups(IEnumerable<PreconditionAttribute> preconditions, string type)
|
||||
{
|
||||
@@ -164,7 +164,7 @@ namespace Discord.Commands
|
||||
|
||||
public async Task<ParseResult> ParseAsync(ICommandContext context, int startIndex, SearchResult searchResult, PreconditionResult preconditionResult = null, IServiceProvider services = null)
|
||||
{
|
||||
services = services ?? EmptyServiceProvider.Instance;
|
||||
services ??= EmptyServiceProvider.Instance;
|
||||
|
||||
if (!searchResult.IsSuccess)
|
||||
return ParseResult.FromError(searchResult);
|
||||
@@ -201,7 +201,7 @@ namespace Discord.Commands
|
||||
}
|
||||
public async Task<IResult> ExecuteAsync(ICommandContext context, IEnumerable<object> argList, IEnumerable<object> paramList, IServiceProvider services)
|
||||
{
|
||||
services = services ?? EmptyServiceProvider.Instance;
|
||||
services ??= EmptyServiceProvider.Instance;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace Discord.Commands
|
||||
|
||||
public async Task<PreconditionResult> CheckPreconditionsAsync(ICommandContext context, object arg, IServiceProvider services = null)
|
||||
{
|
||||
services = services ?? EmptyServiceProvider.Instance;
|
||||
services ??= EmptyServiceProvider.Instance;
|
||||
|
||||
foreach (var precondition in Preconditions)
|
||||
{
|
||||
@@ -89,7 +89,7 @@ namespace Discord.Commands
|
||||
|
||||
public async Task<TypeReaderResult> ParseAsync(ICommandContext context, string input, IServiceProvider services = null)
|
||||
{
|
||||
services = services ?? EmptyServiceProvider.Instance;
|
||||
services ??= EmptyServiceProvider.Instance;
|
||||
return await _reader.ReadAsync(context, input, services).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Discord.Commands
|
||||
public abstract class ModuleBase<T> : IModuleBase
|
||||
where T : class, ICommandContext
|
||||
{
|
||||
#region ModuleBase
|
||||
/// <summary>
|
||||
/// The underlying context of the command.
|
||||
/// </summary>
|
||||
@@ -35,10 +36,14 @@ namespace Discord.Commands
|
||||
/// Specifies if notifications are sent for mentioned users and roles in the <paramref name="message"/>.
|
||||
/// If <c>null</c>, all mentioned roles and users will be notified.
|
||||
/// </param>
|
||||
/// <param name="options">The request options for this <see langword="async"/> request.</param>
|
||||
/// <param name="messageReference">The message references to be included. Used to reply to specific messages.</param>
|
||||
protected virtual async Task<IUserMessage> ReplyAsync(string message = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null)
|
||||
/// <param name="component">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>
|
||||
protected virtual async Task<IUserMessage> ReplyAsync(string message = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null)
|
||||
{
|
||||
return await Context.Channel.SendMessageAsync(message, isTTS, embed, options, allowedMentions, messageReference).ConfigureAwait(false);
|
||||
return await Context.Channel.SendMessageAsync(message, isTTS, embed, options, allowedMentions, messageReference, component, stickers, embeds).ConfigureAwait(false);
|
||||
}
|
||||
/// <summary>
|
||||
/// The method to execute before executing the command.
|
||||
@@ -63,8 +68,9 @@ namespace Discord.Commands
|
||||
protected virtual void OnModuleBuilding(CommandService commandService, ModuleBuilder builder)
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
//IModuleBase
|
||||
#region IModuleBase
|
||||
void IModuleBase.SetContext(ICommandContext context)
|
||||
{
|
||||
var newValue = context as T;
|
||||
@@ -73,5 +79,6 @@ namespace Discord.Commands
|
||||
void IModuleBase.BeforeExecute(CommandInfo command) => BeforeExecute(command);
|
||||
void IModuleBase.AfterExecute(CommandInfo command) => AfterExecute(command);
|
||||
void IModuleBase.OnModuleBuilding(CommandService commandService, ModuleBuilder builder) => OnModuleBuilding(commandService, builder);
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Discord.Commands
|
||||
public enum RunMode
|
||||
{
|
||||
/// <summary>
|
||||
/// The default behaviour set in <see cref="CommandServiceConfig"/>.
|
||||
/// The default behavior set in <see cref="CommandServiceConfig"/>.
|
||||
/// </summary>
|
||||
Default,
|
||||
/// <summary>
|
||||
|
||||
@@ -46,6 +46,32 @@ namespace Discord
|
||||
string extension = FormatToExtension(format, avatarId);
|
||||
return $"{DiscordConfig.CDNUrl}avatars/{userId}/{avatarId}.{extension}?size={size}";
|
||||
}
|
||||
|
||||
public static string GetGuildUserAvatarUrl(ulong userId, ulong guildId, string avatarId, ushort size, ImageFormat format)
|
||||
{
|
||||
if (avatarId == null)
|
||||
return null;
|
||||
string extension = FormatToExtension(format, avatarId);
|
||||
return $"{DiscordConfig.CDNUrl}guilds/{guildId}/users/{userId}/avatars/{avatarId}.{extension}?size={size}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a user banner URL.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user snowflake identifier.</param>
|
||||
/// <param name="bannerId">The banner identifier.</param>
|
||||
/// <param name="size">The size of the image to return in horizontal pixels. This can be any power of two between 16 and 2048.</param>
|
||||
/// <param name="format">The format to return.</param>
|
||||
/// <returns>
|
||||
/// A URL pointing to the user's banner in the specified size.
|
||||
/// </returns>
|
||||
public static string GetUserBannerUrl(ulong userId, string bannerId, ushort size, ImageFormat format)
|
||||
{
|
||||
if (bannerId == null)
|
||||
return null;
|
||||
string extension = FormatToExtension(format, bannerId);
|
||||
return $"{DiscordConfig.CDNUrl}banners/{userId}/{bannerId}.{extension}?size={size}";
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the default user avatar URL.
|
||||
/// </summary>
|
||||
@@ -68,6 +94,16 @@ namespace Discord
|
||||
public static string GetGuildIconUrl(ulong guildId, string iconId)
|
||||
=> iconId != null ? $"{DiscordConfig.CDNUrl}icons/{guildId}/{iconId}.jpg" : null;
|
||||
/// <summary>
|
||||
/// Returns a guild role's icon URL.
|
||||
/// </summary>
|
||||
/// <param name="roleId">The role identifier.</param>
|
||||
/// <param name="roleHash">The icon hash.</param>
|
||||
/// <returns>
|
||||
/// A URL pointing to the guild role's icon.
|
||||
/// </returns>
|
||||
public static string GetGuildRoleIconUrl(ulong roleId, string roleHash)
|
||||
=> roleHash != null ? $"{DiscordConfig.CDNUrl}role-icons/{roleId}/{roleHash}.png" : null;
|
||||
/// <summary>
|
||||
/// Returns a guild splash URL.
|
||||
/// </summary>
|
||||
/// <param name="guildId">The guild snowflake identifier.</param>
|
||||
@@ -103,15 +139,17 @@ namespace Discord
|
||||
/// </summary>
|
||||
/// <param name="guildId">The guild snowflake identifier.</param>
|
||||
/// <param name="bannerId">The banner image identifier.</param>
|
||||
/// <param name="format">The format to return.</param>
|
||||
/// <param name="size">The size of the image to return in horizontal pixels. This can be any power of two between 16 and 2048 inclusive.</param>
|
||||
/// <returns>
|
||||
/// A URL pointing to the guild's banner image.
|
||||
/// </returns>
|
||||
public static string GetGuildBannerUrl(ulong guildId, string bannerId, ushort? size = null)
|
||||
public static string GetGuildBannerUrl(ulong guildId, string bannerId, ImageFormat format, ushort? size = null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(bannerId))
|
||||
return $"{DiscordConfig.CDNUrl}banners/{guildId}/{bannerId}.jpg" + (size.HasValue ? $"?size={size}" : string.Empty);
|
||||
return null;
|
||||
if (string.IsNullOrEmpty(bannerId))
|
||||
return null;
|
||||
string extension = FormatToExtension(format, bannerId);
|
||||
return $"{DiscordConfig.CDNUrl}banners/{guildId}/{bannerId}.{extension}" + (size.HasValue ? $"?size={size}" : string.Empty);
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns an emoji URL.
|
||||
@@ -159,23 +197,39 @@ namespace Discord
|
||||
public static string GetSpotifyDirectUrl(string trackId)
|
||||
=> $"https://open.spotify.com/track/{trackId}";
|
||||
|
||||
/// <summary>
|
||||
/// Gets a stickers url based off the id and format.
|
||||
/// </summary>
|
||||
/// <param name="stickerId">The id of the sticker.</param>
|
||||
/// <param name="format">The format of the sticker.</param>
|
||||
/// <returns>
|
||||
/// A URL to the sticker.
|
||||
/// </returns>
|
||||
public static string GetStickerUrl(ulong stickerId, StickerFormatType format = StickerFormatType.Png)
|
||||
=> $"{DiscordConfig.CDNUrl}stickers/{stickerId}.{FormatToExtension(format)}";
|
||||
|
||||
private static string FormatToExtension(StickerFormatType format)
|
||||
{
|
||||
return format switch
|
||||
{
|
||||
StickerFormatType.None or StickerFormatType.Png or StickerFormatType.Apng => "png", // In the case of the Sticker endpoint, the sticker will be available as PNG if its format_type is PNG or APNG, and as Lottie if its format_type is LOTTIE.
|
||||
StickerFormatType.Lottie => "lottie",
|
||||
_ => throw new ArgumentException(nameof(format)),
|
||||
};
|
||||
}
|
||||
|
||||
private static string FormatToExtension(ImageFormat format, string imageId)
|
||||
{
|
||||
if (format == ImageFormat.Auto)
|
||||
format = imageId.StartsWith("a_") ? ImageFormat.Gif : ImageFormat.Png;
|
||||
switch (format)
|
||||
return format switch
|
||||
{
|
||||
case ImageFormat.Gif:
|
||||
return "gif";
|
||||
case ImageFormat.Jpeg:
|
||||
return "jpeg";
|
||||
case ImageFormat.Png:
|
||||
return "png";
|
||||
case ImageFormat.WebP:
|
||||
return "webp";
|
||||
default:
|
||||
throw new ArgumentException(nameof(format));
|
||||
}
|
||||
ImageFormat.Gif => "gif",
|
||||
ImageFormat.Jpeg => "jpeg",
|
||||
ImageFormat.Png => "png",
|
||||
ImageFormat.WebP => "webp",
|
||||
_ => throw new ArgumentException(nameof(format)),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="../../Discord.Net.targets" />
|
||||
<Import Project="../../StyleAnalyzer.targets"/>
|
||||
<PropertyGroup>
|
||||
@@ -16,4 +16,4 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -94,6 +94,13 @@ namespace Discord
|
||||
/// The maximum number of users that can be gotten per-batch.
|
||||
/// </returns>
|
||||
public const int MaxUsersPerBatch = 1000;
|
||||
/// <summary>
|
||||
/// Returns the max users allowed to be in a request for guild event users.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The maximum number of users that can be gotten per-batch.
|
||||
/// </returns>
|
||||
public const int MaxGuildEventUsersPerBatch = 100;
|
||||
/// <summary>
|
||||
/// Returns the max guilds allowed to be in a request.
|
||||
/// </summary>
|
||||
@@ -158,5 +165,17 @@ namespace Discord
|
||||
/// clock. Your system will still need a stable clock.
|
||||
/// </remarks>
|
||||
public bool UseSystemClock { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether or not the internal experation check uses the system date
|
||||
/// + snowflake date to check if an interaction can be responded to.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If set to <see langword="false"/> then the CreatedAt property in an interaction
|
||||
/// will be set to when it was received instead of the snowflakes date.
|
||||
/// <br/>
|
||||
/// <b>This will still require a stable clock on your system.</b>
|
||||
/// </remarks>
|
||||
public bool UseInteractionSnowflakeDate { get; set; } = true;
|
||||
}
|
||||
}
|
||||
|
||||
197
src/Discord.Net.Core/DiscordErrorCode.cs
Normal file
197
src/Discord.Net.Core/DiscordErrorCode.cs
Normal file
@@ -0,0 +1,197 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a set of json error codes received by discord.
|
||||
/// </summary>
|
||||
public enum DiscordErrorCode
|
||||
{
|
||||
GeneralError = 0,
|
||||
|
||||
#region UnknownXYZ (10XXX)
|
||||
UnknownAccount = 10001,
|
||||
UnknownApplication = 10002,
|
||||
UnknownChannel = 10003,
|
||||
UnknownGuild = 10004,
|
||||
UnknownIntegration = 10005,
|
||||
UnknownInvite = 10006,
|
||||
UnknownMember = 10007,
|
||||
UnknownMessage = 10008,
|
||||
UnknownPermissionOverwrite = 10009,
|
||||
UnknownProvider = 10010,
|
||||
UnknownRole = 10011,
|
||||
UnknownToken = 10012,
|
||||
UnknownUser = 10013,
|
||||
UnknownEmoji = 10014,
|
||||
UnknownWebhook = 10015,
|
||||
UnknownWebhookService = 10016,
|
||||
UnknownSession = 10020,
|
||||
UnknownBan = 10026,
|
||||
UnknownSKU = 10027,
|
||||
UnknownStoreListing = 10028,
|
||||
UnknownEntitlement = 10029,
|
||||
UnknownBuild = 10030,
|
||||
UnknownLobby = 10031,
|
||||
UnknownBranch = 10032,
|
||||
UnknownStoreDirectoryLayout = 10033,
|
||||
UnknownRedistributable = 10036,
|
||||
UnknownGiftCode = 10038,
|
||||
UnknownStream = 10049,
|
||||
UnknownPremiumServerSubscribeCooldown = 10050,
|
||||
UnknownGuildTemplate = 10057,
|
||||
UnknownDiscoverableServerCategory = 10059,
|
||||
UnknownSticker = 10060,
|
||||
UnknownInteraction = 10062,
|
||||
UnknownApplicationCommand = 10063,
|
||||
UnknownApplicationCommandPermissions = 10066,
|
||||
UnknownStageInstance = 10067,
|
||||
UnknownGuildMemberVerificationForm = 10068,
|
||||
UnknownGuildWelcomeScreen = 10069,
|
||||
UnknownGuildScheduledEvent = 10070,
|
||||
UnknownGuildScheduledEventUser = 10071,
|
||||
#endregion
|
||||
|
||||
#region General Actions (20XXX)
|
||||
BotsCannotUse = 20001,
|
||||
OnlyBotsCanUse = 20002,
|
||||
CannotSendExplicitContent = 20009,
|
||||
ApplicationActionUnauthorized = 20012,
|
||||
ActionSlowmode = 20016,
|
||||
OnlyOwnerAction = 20018,
|
||||
AnnouncementEditRatelimit = 20022,
|
||||
ChannelWriteRatelimit = 20028,
|
||||
WordsNotAllowed = 20031,
|
||||
GuildPremiumTooLow = 20035,
|
||||
#endregion
|
||||
|
||||
#region Numeric Limits Reached (30XXX)
|
||||
MaximumGuildsReached = 30001,
|
||||
MaximumFriendsReached = 30002,
|
||||
MaximumPinsReached = 30003,
|
||||
MaximumRecipientsReached = 30004,
|
||||
MaximumGuildRolesReached = 30005,
|
||||
MaximumWebhooksReached = 30007,
|
||||
MaximumEmojisReached = 30008,
|
||||
MaximumReactionsReached = 30010,
|
||||
MaximumGuildChannelsReached = 30013,
|
||||
MaximumAttachmentsReached = 30015,
|
||||
MaximumInvitesReached = 30016,
|
||||
MaximumAnimatedEmojisReached = 30018,
|
||||
MaximumServerMembersReached = 30019,
|
||||
MaximumServerCategoriesReached = 30030,
|
||||
GuildTemplateAlreadyExists = 30031,
|
||||
MaximumThreadMembersReached = 30033,
|
||||
MaximumBansForNonGuildMembersReached = 30035,
|
||||
MaximumBanFetchesReached = 30037,
|
||||
MaximumUncompleteGuildScheduledEvents = 30038,
|
||||
MaximumStickersReached = 30039,
|
||||
MaximumPruneRequestReached = 30040,
|
||||
MaximumGuildWigitsReached = 30042,
|
||||
#endregion
|
||||
|
||||
#region General Request Errors (40XXX)
|
||||
TokenUnauthorized = 40001,
|
||||
InvalidVerification = 40002,
|
||||
OpeningDMTooFast = 40003,
|
||||
RequestEntityTooLarge = 40005,
|
||||
FeatureDisabled = 40006,
|
||||
UserBanned = 40007,
|
||||
TargetUserNotInVoice = 40032,
|
||||
MessageAlreadyCrossposted = 40033,
|
||||
ApplicationNameAlreadyExists = 40041,
|
||||
#endregion
|
||||
|
||||
#region Action Preconditions/Checks (50XXX)
|
||||
MissingPermissions = 50001,
|
||||
InvalidAccountType = 50002,
|
||||
CannotExecuteForDM = 50003,
|
||||
GuildWigitDisabled = 50004,
|
||||
CannotEditOtherUsersMessage = 50005,
|
||||
CannotSendEmptyMessage = 50006,
|
||||
CannotSendMessageToUser = 50007,
|
||||
CannotSendMessageToVoiceChannel = 50008,
|
||||
ChannelVerificationTooHight = 50009,
|
||||
OAuth2ApplicationDoesntHaveBot = 50010,
|
||||
OAuth2ApplicationLimitReached = 50011,
|
||||
InvalidOAuth2State = 50012,
|
||||
InsufficientPermissions = 50013,
|
||||
InvalidAuthenticationToken = 50014,
|
||||
NoteTooLong = 50015,
|
||||
ProvidedMessageDeleteCountOutOfBounds = 50016,
|
||||
InvalidPinChannel = 50019,
|
||||
InvalidInvite = 50020,
|
||||
CannotExecuteOnSystemMessage = 50021,
|
||||
CannotExecuteOnChannelType = 50024,
|
||||
InvalidOAuth2Token = 50025,
|
||||
MissingOAuth2Scope = 50026,
|
||||
InvalidWebhookToken = 50027,
|
||||
InvalidRole = 50028,
|
||||
InvalidRecipients = 50033,
|
||||
BulkDeleteMessageTooOld = 50034,
|
||||
InvalidFormBody = 50035,
|
||||
InviteAcceptedForGuildThatBotIsntIn = 50036,
|
||||
InvalidAPIVersion = 50041,
|
||||
FileUploadTooBig = 50045,
|
||||
InvalidFileUpload = 50046,
|
||||
CannotSelfRedeemGift = 50054,
|
||||
PaymentSourceRequiredForGift = 50070,
|
||||
CannotDeleteRequiredCommunityChannel = 50074,
|
||||
InvalidSticker = 50081,
|
||||
CannotExecuteOnArchivedThread = 50083,
|
||||
InvalidThreadNotificationSettings = 50084,
|
||||
BeforeValueEarlierThanThreadCreation = 50085,
|
||||
ServerLocaleUnavailable = 50095,
|
||||
ServerRequiresMonetization = 50097,
|
||||
ServerRequiresBoosts = 50101,
|
||||
|
||||
#endregion
|
||||
|
||||
#region 2FA (60XXX)
|
||||
Requires2FA = 60003,
|
||||
#endregion
|
||||
|
||||
#region User Searches (80XXX)
|
||||
NoUsersWithTag = 80004,
|
||||
#endregion
|
||||
|
||||
#region Reactions (90XXX)
|
||||
ReactionBlocked = 90001,
|
||||
#endregion
|
||||
|
||||
#region API Status (130XXX)
|
||||
APIOverloaded = 130000,
|
||||
#endregion
|
||||
|
||||
#region Stage Errors (150XXX)
|
||||
StageAlreadyOpened = 150006,
|
||||
#endregion
|
||||
|
||||
#region Reply and Thread Errors (160XXX)
|
||||
CannotReplyWithoutReadMessageHistory = 160002,
|
||||
MessageAlreadyContainsThread = 160004,
|
||||
ThreadIsLocked = 160005,
|
||||
MaximumActiveThreadsReached = 160006,
|
||||
MaximumAnnouncementThreadsReached = 160007,
|
||||
#endregion
|
||||
|
||||
#region Sticker Uploads (170XXX)
|
||||
InvalidJSONLottie = 170001,
|
||||
LottieCantContainRasters = 170002,
|
||||
StickerMaximumFramerateExceeded = 170003,
|
||||
StickerMaximumFrameCountExceeded = 170004,
|
||||
LottieMaximumDimentionsExceeded = 170005,
|
||||
StickerFramerateBoundsExceeed = 170006,
|
||||
StickerAnimationDurationTooLong = 170007,
|
||||
#endregion
|
||||
|
||||
#region Guild Scheduled Events
|
||||
CannotUpdateFinishedEvent = 180000,
|
||||
FailedStageCreation = 180002,
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
53
src/Discord.Net.Core/DiscordJsonError.cs
Normal file
53
src/Discord.Net.Core/DiscordJsonError.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a generic parsed json error received from discord after performing a rest request.
|
||||
/// </summary>
|
||||
public struct DiscordJsonError
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the json path of the error.
|
||||
/// </summary>
|
||||
public string Path { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of errors associated with the specific property at the path.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<DiscordError> Errors { get; }
|
||||
|
||||
internal DiscordJsonError(string path, DiscordError[] errors)
|
||||
{
|
||||
Path = path;
|
||||
Errors = errors.ToImmutableArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an error with a property.
|
||||
/// </summary>
|
||||
public struct DiscordError
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the code of the error.
|
||||
/// </summary>
|
||||
public string Code { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the message describing what went wrong.
|
||||
/// </summary>
|
||||
public string Message { get; }
|
||||
|
||||
internal DiscordError(string code, string message)
|
||||
{
|
||||
Code = code;
|
||||
Message = message;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,18 @@ namespace Discord
|
||||
/// <summary>
|
||||
/// Indicates that a user can play this song.
|
||||
/// </summary>
|
||||
Play = 0b100000
|
||||
Play = 0b100000,
|
||||
/// <summary>
|
||||
/// Indicates that a user is playing an activity in a voice channel with friends.
|
||||
/// </summary>
|
||||
PartyPrivacyFriends = 0b1000000,
|
||||
/// <summary>
|
||||
/// Indicates that a user is playing an activity in a voice channel.
|
||||
/// </summary>
|
||||
PartyPrivacyVoiceChannel = 0b10000000,
|
||||
/// <summary>
|
||||
/// Indicates that a user is playing an activity in a voice channel.
|
||||
/// </summary>
|
||||
Embedded = 0b10000000
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,5 +25,9 @@ namespace Discord
|
||||
/// The user has set a custom status.
|
||||
/// </summary>
|
||||
CustomStatus = 4,
|
||||
/// <summary>
|
||||
/// The user is competing in a game.
|
||||
/// </summary>
|
||||
Competing = 5,
|
||||
}
|
||||
}
|
||||
|
||||
23
src/Discord.Net.Core/Entities/ApplicationFlags.cs
Normal file
23
src/Discord.Net.Core/Entities/ApplicationFlags.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents public flags for an application.
|
||||
/// </summary>
|
||||
public enum ApplicationFlags
|
||||
{
|
||||
GatewayPresence = 1 << 12,
|
||||
GatewayPresenceLimited = 1 << 13,
|
||||
GatewayGuildMembers = 1 << 14,
|
||||
GatewayGuildMembersLimited = 1 << 15,
|
||||
VerificationPendingGuildLimit = 1 << 16,
|
||||
Embedded = 1 << 17,
|
||||
GatewayMessageContent = 1 << 18,
|
||||
GatewayMessageContentLimited = 1 << 19
|
||||
}
|
||||
}
|
||||
31
src/Discord.Net.Core/Entities/ApplicationInstallParams.cs
Normal file
31
src/Discord.Net.Core/Entities/ApplicationInstallParams.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents install parameters for an application.
|
||||
/// </summary>
|
||||
public class ApplicationInstallParams
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the scopes to install this application.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<string> Scopes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default permissions to install this application
|
||||
/// </summary>
|
||||
public GuildPermission? Permission { get; }
|
||||
|
||||
internal ApplicationInstallParams(string[] scopes, GuildPermission? permission)
|
||||
{
|
||||
Scopes = scopes.ToImmutableArray();
|
||||
Permission = permission;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,5 +142,55 @@ namespace Discord
|
||||
/// A message was unpinned from this guild.
|
||||
/// </summary>
|
||||
MessageUnpinned = 75,
|
||||
|
||||
/// <summary>
|
||||
/// A integration was created
|
||||
/// </summary>
|
||||
IntegrationCreated = 80,
|
||||
/// <summary>
|
||||
/// A integration was updated
|
||||
/// </summary>
|
||||
IntegrationUpdated = 81,
|
||||
/// <summary>
|
||||
/// An integration was deleted
|
||||
/// </summary>
|
||||
IntegrationDeleted = 82,
|
||||
/// <summary>
|
||||
/// A stage instance was created.
|
||||
/// </summary>
|
||||
StageInstanceCreated = 83,
|
||||
/// <summary>
|
||||
/// A stage instance was updated.
|
||||
/// </summary>
|
||||
StageInstanceUpdated = 84,
|
||||
/// <summary>
|
||||
/// A stage instance was deleted.
|
||||
/// </summary>
|
||||
StageInstanceDeleted = 85,
|
||||
|
||||
/// <summary>
|
||||
/// A sticker was created.
|
||||
/// </summary>
|
||||
StickerCreated = 90,
|
||||
/// <summary>
|
||||
/// A sticker was updated.
|
||||
/// </summary>
|
||||
StickerUpdated = 91,
|
||||
/// <summary>
|
||||
/// A sticker was deleted.
|
||||
/// </summary>
|
||||
StickerDeleted = 92,
|
||||
/// <summary>
|
||||
/// A thread was created.
|
||||
/// </summary>
|
||||
ThreadCreate = 110,
|
||||
/// <summary>
|
||||
/// A thread was updated.
|
||||
/// </summary>
|
||||
ThreadUpdate = 111,
|
||||
/// <summary>
|
||||
/// A thread was deleted.
|
||||
/// </summary>
|
||||
ThreadDelete = 112
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,18 @@ namespace Discord
|
||||
/// <summary> The channel is a category channel. </summary>
|
||||
Category = 4,
|
||||
/// <summary> The channel is a news channel. </summary>
|
||||
News = 5
|
||||
News = 5,
|
||||
/// <summary> The channel is a store channel. </summary>
|
||||
Store = 6,
|
||||
/// <summary> The channel is a temporary thread channel under a news channel. </summary>
|
||||
NewsThread = 10,
|
||||
/// <summary> The channel is a temporary thread channel under a text channel. </summary>
|
||||
PublicThread = 11,
|
||||
/// <summary> The channel is a private temporary thread channel under a text channel. </summary>
|
||||
PrivateThread = 12,
|
||||
/// <summary> The channel is a stage voice channel. </summary>
|
||||
Stage = 13,
|
||||
/// <summary> The channel is a guild directory used in hub servers. (Unreleased)</summary>
|
||||
GuildDirectory = 14
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,11 +28,14 @@ namespace Discord
|
||||
/// If <c>null</c>, all mentioned roles and users will be notified.
|
||||
/// </param>
|
||||
/// <param name="messageReference">The message references to be included. Used to reply to specific messages.</param>
|
||||
/// <param name="component">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>
|
||||
/// <returns>
|
||||
/// A task that represents an asynchronous send operation for delivering the message. The task result
|
||||
/// contains the sent message.
|
||||
/// </returns>
|
||||
Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null);
|
||||
Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null);
|
||||
/// <summary>
|
||||
/// Sends a file to this message channel with an optional caption.
|
||||
/// </summary>
|
||||
@@ -65,11 +68,14 @@ namespace Discord
|
||||
/// If <c>null</c>, all mentioned roles and users will be notified.
|
||||
/// </param>
|
||||
/// <param name="messageReference">The message references to be included. Used to reply to specific messages.</param>
|
||||
/// <param name="component">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>
|
||||
/// <returns>
|
||||
/// A task that represents an asynchronous send operation for delivering the message. The task result
|
||||
/// contains the sent message.
|
||||
/// </returns>
|
||||
Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null);
|
||||
Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null);
|
||||
/// <summary>
|
||||
/// Sends a file to this message channel with an optional caption.
|
||||
/// </summary>
|
||||
@@ -99,11 +105,72 @@ namespace Discord
|
||||
/// If <c>null</c>, all mentioned roles and users will be notified.
|
||||
/// </param>
|
||||
/// <param name="messageReference">The message references to be included. Used to reply to specific messages.</param>
|
||||
/// <param name="component">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>
|
||||
/// <returns>
|
||||
/// A task that represents an asynchronous send operation for delivering the message. The task result
|
||||
/// contains the sent message.
|
||||
/// </returns>
|
||||
Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null);
|
||||
Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null);
|
||||
/// <summary>
|
||||
/// Sends a file to this message channel with an optional caption.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method sends a file as if you are uploading an attachment directly from your Discord client.
|
||||
/// <note>
|
||||
/// If you wish to upload an image and have it embedded in a <see cref="Discord.EmbedType.Rich"/> embed,
|
||||
/// you may upload the file and refer to the file with "attachment://filename.ext" in the
|
||||
/// <see cref="Discord.EmbedBuilder.ImageUrl"/>. See the example section for its usage.
|
||||
/// </note>
|
||||
/// </remarks>
|
||||
/// <param name="attachment">The attachment containing the file and description.</param>
|
||||
/// <param name="text">The message to be sent.</param>
|
||||
/// <param name="isTTS">Whether the message should be read aloud by Discord or not.</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="messageReference">The message references to be included. Used to reply to specific messages.</param>
|
||||
/// <param name="component">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>
|
||||
/// <returns>
|
||||
/// A task that represents an asynchronous send operation for delivering the message. The task result
|
||||
/// contains the sent message.
|
||||
/// </returns>
|
||||
Task<IUserMessage> SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null);
|
||||
/// <summary>
|
||||
/// Sends a collection of files to this message channel.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method sends files as if you are uploading attachments directly from your Discord client.
|
||||
/// <note>
|
||||
/// If you wish to upload an image and have it embedded in a <see cref="Discord.EmbedType.Rich"/> embed,
|
||||
/// you may upload the file and refer to the file with "attachment://filename.ext" in the
|
||||
/// <see cref="Discord.EmbedBuilder.ImageUrl"/>. See the example section for its usage.
|
||||
/// </note>
|
||||
/// </remarks>
|
||||
/// <param name="attachments">A collection of attachments to upload.</param>
|
||||
/// <param name="text">The message to be sent.</param>
|
||||
/// <param name="isTTS">Whether the message should be read aloud by Discord or not.</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="messageReference">The message references to be included. Used to reply to specific messages.</param>
|
||||
/// <param name="component">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>
|
||||
/// <returns>
|
||||
/// A task that represents an asynchronous send operation for delivering the message. The task result
|
||||
/// contains the sent message.
|
||||
/// </returns>
|
||||
Task<IUserMessage> SendFilesAsync(IEnumerable<FileAttachment> attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a message from this message channel.
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Discord
|
||||
/// Gets the parent (category) ID of this channel in the guild's channel list.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ulong"/> representing the snowflake identifier of the parent of this channel;
|
||||
/// A <see cref="ulong"/> representing the snowflake identifier of the parent of this channel;
|
||||
/// <c>null</c> if none is set.
|
||||
/// </returns>
|
||||
ulong? CategoryId { get; }
|
||||
@@ -56,6 +56,50 @@ namespace Discord
|
||||
/// metadata object containing information for the created invite.
|
||||
/// </returns>
|
||||
Task<IInviteMetadata> CreateInviteAsync(int? maxAge = 86400, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new invite to this channel.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <para>The following example creates a new invite to this channel; the invite lasts for 12 hours and can only
|
||||
/// be used 3 times throughout its lifespan.</para>
|
||||
/// <code language="cs">
|
||||
/// await guildChannel.CreateInviteAsync(maxAge: 43200, maxUses: 3);
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// <param name="applicationId">The id of the embedded application to open for this invite.</param>
|
||||
/// <param name="maxAge">The time (in seconds) until the invite expires. Set to <c>null</c> to never expire.</param>
|
||||
/// <param name="maxUses">The max amount of times this invite may be used. Set to <c>null</c> to have unlimited uses.</param>
|
||||
/// <param name="isTemporary">If <c>true</c>, the user accepting this invite will be kicked from the guild after closing their client.</param>
|
||||
/// <param name="isUnique">If <c>true</c>, don't try to reuse a similar invite (useful for creating many unique one time use invites).</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous invite creation operation. The task result contains an invite
|
||||
/// metadata object containing information for the created invite.
|
||||
/// </returns>
|
||||
Task<IInviteMetadata> CreateInviteToApplicationAsync(ulong applicationId, int? maxAge = 86400, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new invite to this channel.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <para>The following example creates a new invite to this channel; the invite lasts for 12 hours and can only
|
||||
/// be used 3 times throughout its lifespan.</para>
|
||||
/// <code language="cs">
|
||||
/// await guildChannel.CreateInviteAsync(maxAge: 43200, maxUses: 3);
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// <param name="user">The id of the user whose stream to display for this invite.</param>
|
||||
/// <param name="maxAge">The time (in seconds) until the invite expires. Set to <c>null</c> to never expire.</param>
|
||||
/// <param name="maxUses">The max amount of times this invite may be used. Set to <c>null</c> to have unlimited uses.</param>
|
||||
/// <param name="isTemporary">If <c>true</c>, the user accepting this invite will be kicked from the guild after closing their client.</param>
|
||||
/// <param name="isUnique">If <c>true</c>, don't try to reuse a similar invite (useful for creating many unique one time use invites).</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous invite creation operation. The task result contains an invite
|
||||
/// metadata object containing information for the created invite.
|
||||
/// </returns>
|
||||
Task<IInviteMetadata> CreateInviteToStreamAsync(IUser user, int? maxAge = 86400, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null);
|
||||
/// <summary>
|
||||
/// Gets a collection of all invites to this channel.
|
||||
/// </summary>B
|
||||
|
||||
114
src/Discord.Net.Core/Entities/Channels/IStageChannel.cs
Normal file
114
src/Discord.Net.Core/Entities/Channels/IStageChannel.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a generic Stage Channel.
|
||||
/// </summary>
|
||||
public interface IStageChannel : IVoiceChannel
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the topic of the Stage instance.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the stage isn't live then this property will be set to <see langword="null"/>.
|
||||
/// </remarks>
|
||||
string Topic { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="StagePrivacyLevel"/> of the current stage.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the stage isn't live then this property will be set to <see langword="null"/>.
|
||||
/// </remarks>
|
||||
StagePrivacyLevel? PrivacyLevel { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not stage discovery is disabled.
|
||||
/// </summary>
|
||||
bool? IsDiscoverableDisabled { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the stage is live.
|
||||
/// </summary>
|
||||
bool IsLive { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Starts the stage, creating a stage instance.
|
||||
/// </summary>
|
||||
/// <param name="topic">The topic for the stage/</param>
|
||||
/// <param name="privacyLevel">The privacy level of the stage.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous start operation.
|
||||
/// </returns>
|
||||
Task StartStageAsync(string topic, StagePrivacyLevel privacyLevel = StagePrivacyLevel.GuildOnly, RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Modifies the current stage instance.
|
||||
/// </summary>
|
||||
/// <param name="func">The properties to modify the stage instance with.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous modify operation.
|
||||
/// </returns>
|
||||
Task ModifyInstanceAsync(Action<StageInstanceProperties> func, RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Stops the stage, deleting the stage instance.
|
||||
/// </summary>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous stop operation.
|
||||
/// </returns>
|
||||
Task StopStageAsync(RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the bot would like to speak within a stage channel.
|
||||
/// </summary>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous request to speak operation.
|
||||
/// </returns>
|
||||
Task RequestToSpeakAsync(RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Makes the current user become a speaker within a stage.
|
||||
/// </summary>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous speaker modify operation.
|
||||
/// </returns>
|
||||
Task BecomeSpeakerAsync(RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Makes the current user a listener.
|
||||
/// </summary>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous stop operation.
|
||||
/// </returns>
|
||||
Task StopSpeakingAsync(RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Makes a user a speaker within a stage.
|
||||
/// </summary>
|
||||
/// <param name="user">The user to make the speaker.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous move operation.
|
||||
/// </returns>
|
||||
Task MoveToSpeakerAsync(IGuildUser user, RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a user from speaking.
|
||||
/// </summary>
|
||||
/// <param name="user">The user to remove from speaking.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous remove operation.
|
||||
/// </returns>
|
||||
Task RemoveFromSpeakerAsync(IGuildUser user, RequestOptions options = null);
|
||||
}
|
||||
}
|
||||
@@ -114,5 +114,40 @@ namespace Discord
|
||||
/// of webhooks that is available in this channel.
|
||||
/// </returns>
|
||||
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="invitable">Whether non-moderators can add other non-moderators to a thread; only available when creating a private thread</param>
|
||||
/// <param name="slowmode">The amount of seconds a user has to wait before sending another message (0-21600)</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, bool? invitable = null, int? slowmode = null, RequestOptions options = null);
|
||||
}
|
||||
}
|
||||
|
||||
89
src/Discord.Net.Core/Entities/Channels/IThreadChannel.cs
Normal file
89
src/Discord.Net.Core/Entities/Channels/IThreadChannel.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a thread channel inside of a guild.
|
||||
/// </summary>
|
||||
public interface IThreadChannel : ITextChannel
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the type of the current thread channel.
|
||||
/// </summary>
|
||||
ThreadType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the current user has joined this thread.
|
||||
/// </summary>
|
||||
bool HasJoined { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the current thread is archived.
|
||||
/// </summary>
|
||||
bool IsArchived { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the duration of time before the thread is automatically archived after no activity.
|
||||
/// </summary>
|
||||
ThreadArchiveDuration AutoArchiveDuration { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the timestamp when the thread's archive status was last changed, used for calculating recent activity.
|
||||
/// </summary>
|
||||
DateTimeOffset ArchiveTimestamp { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the current thread is locked.
|
||||
/// </summary>
|
||||
bool IsLocked { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets an approximate count of users in a thread, stops counting after 50.
|
||||
/// </summary>
|
||||
int MemberCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets an approximate count of messages in a thread, stops counting after 50.
|
||||
/// </summary>
|
||||
int MessageCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Joins the current thread.
|
||||
/// </summary>
|
||||
/// <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>
|
||||
/// Leaves the current thread.
|
||||
/// </summary>
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents properties to use when modifying a stage instance.
|
||||
/// </summary>
|
||||
public class StageInstanceProperties
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the topic of the stage.
|
||||
/// </summary>
|
||||
public Optional<string> Topic { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the privacy level of the stage.
|
||||
/// </summary>
|
||||
public Optional<StagePrivacyLevel> PrivacyLevel { get; set; }
|
||||
}
|
||||
}
|
||||
17
src/Discord.Net.Core/Entities/Channels/StagePrivacyLevel.cs
Normal file
17
src/Discord.Net.Core/Entities/Channels/StagePrivacyLevel.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the privacy level of a stage.
|
||||
/// </summary>
|
||||
public enum StagePrivacyLevel
|
||||
{
|
||||
/// <summary>
|
||||
/// The Stage instance is visible publicly, such as on Stage Discovery.
|
||||
/// </summary>
|
||||
Public = 1,
|
||||
/// <summary>
|
||||
/// The Stage instance is visible to only guild members.
|
||||
/// </summary>
|
||||
GuildOnly = 2
|
||||
}
|
||||
}
|
||||
@@ -38,5 +38,21 @@ namespace Discord
|
||||
/// </remarks>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown if the value does not fall within [0, 21600].</exception>
|
||||
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; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the thread auto archive duration.
|
||||
/// </summary>
|
||||
public enum ThreadArchiveDuration
|
||||
{
|
||||
/// <summary>
|
||||
/// One hour (60 minutes).
|
||||
/// </summary>
|
||||
OneHour = 60,
|
||||
|
||||
/// <summary>
|
||||
/// One day (1440 minutes).
|
||||
/// </summary>
|
||||
OneDay = 1440,
|
||||
|
||||
/// <summary>
|
||||
/// Three days (4320 minutes).
|
||||
/// <remarks>
|
||||
/// This option is explicitly available to nitro users.
|
||||
/// </remarks>
|
||||
/// </summary>
|
||||
ThreeDays = 4320,
|
||||
|
||||
/// <summary>
|
||||
/// One week (10080 minutes).
|
||||
/// <remarks>
|
||||
/// This option is explicitly available to nitro users.
|
||||
/// </remarks>
|
||||
/// </summary>
|
||||
OneWeek = 10080
|
||||
}
|
||||
}
|
||||
23
src/Discord.Net.Core/Entities/Channels/ThreadType.cs
Normal file
23
src/Discord.Net.Core/Entities/Channels/ThreadType.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -13,5 +13,9 @@ namespace Discord
|
||||
/// Gets or sets the maximum number of users that can be present in a channel, or <c>null</c> if none.
|
||||
/// </summary>
|
||||
public Optional<int?> UserLimit { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the channel voice region id, automatic when set to <see langword="null"/>.
|
||||
/// </summary>
|
||||
public Optional<string> RTCRegion { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -102,5 +102,7 @@ namespace Discord
|
||||
/// A string representing the raw presentation of the emote (e.g. <c><:thonkang:282745590985523200></c>).
|
||||
/// </returns>
|
||||
public override string ToString() => $"<{(Animated ? "a" : "")}:{Name}:{Id}>";
|
||||
|
||||
public static implicit operator Emote(string s) => Parse(s);
|
||||
}
|
||||
}
|
||||
|
||||
105
src/Discord.Net.Core/Entities/Guilds/GuildFeature.cs
Normal file
105
src/Discord.Net.Core/Entities/Guilds/GuildFeature.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
[Flags]
|
||||
public enum GuildFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// The guild has no features.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
/// <summary>
|
||||
/// The guild has access to set an animated guild icon.
|
||||
/// </summary>
|
||||
AnimatedIcon = 1 << 0,
|
||||
/// <summary>
|
||||
/// The guild has access to set a guild banner image.
|
||||
/// </summary>
|
||||
Banner = 1 << 1,
|
||||
/// <summary>
|
||||
/// The guild has access to use commerce features (i.e. create store channels).
|
||||
/// </summary>
|
||||
Commerce = 1 << 2,
|
||||
/// <summary>
|
||||
/// The guild can enable welcome screen, Membership Screening, stage channels and discovery, and receives community updates.
|
||||
/// </summary>
|
||||
Community = 1 << 3,
|
||||
/// <summary>
|
||||
/// The guild is able to be discovered in the directory.
|
||||
/// </summary>
|
||||
Discoverable = 1 << 4,
|
||||
/// <summary>
|
||||
/// The guild is able to be featured in the directory.
|
||||
/// </summary>
|
||||
Featureable = 1 << 5,
|
||||
/// <summary>
|
||||
/// The guild has access to set an invite splash background.
|
||||
/// </summary>
|
||||
InviteSplash = 1 << 6,
|
||||
/// <summary>
|
||||
/// The guild has enabled <seealso href="https://discord.com/developers/docs/resources/guild#membership-screening-object">Membership Screening</seealso>.
|
||||
/// </summary>
|
||||
MemberVerificationGateEnabled = 1 << 7,
|
||||
/// <summary>
|
||||
/// The guild has enabled monetization.
|
||||
/// </summary>
|
||||
MonetizationEnabled = 1 << 8,
|
||||
/// <summary>
|
||||
/// The guild has increased custom sticker slots.
|
||||
/// </summary>
|
||||
MoreStickers = 1 << 9,
|
||||
/// <summary>
|
||||
/// The guild has access to create news channels.
|
||||
/// </summary>
|
||||
News = 1 << 10,
|
||||
/// <summary>
|
||||
/// The guild is partnered.
|
||||
/// </summary>
|
||||
Partnered = 1 << 11,
|
||||
/// <summary>
|
||||
/// The guild can be previewed before joining via Membership Screening or the directory.
|
||||
/// </summary>
|
||||
PreviewEnabled = 1 << 12,
|
||||
/// <summary>
|
||||
/// The guild has access to create private threads.
|
||||
/// </summary>
|
||||
PrivateThreads = 1 << 13,
|
||||
/// <summary>
|
||||
/// The guild is able to set role icons.
|
||||
/// </summary>
|
||||
RoleIcons = 1 << 14,
|
||||
/// <summary>
|
||||
/// The guild has access to the seven day archive time for threads.
|
||||
/// </summary>
|
||||
SevenDayThreadArchive = 1 << 15,
|
||||
/// <summary>
|
||||
/// The guild has access to the three day archive time for threads.
|
||||
/// </summary>
|
||||
ThreeDayThreadArchive = 1 << 16,
|
||||
/// <summary>
|
||||
/// The guild has enabled ticketed events.
|
||||
/// </summary>
|
||||
TicketedEventsEnabled = 1 << 17,
|
||||
/// <summary>
|
||||
/// The guild has access to set a vanity URL.
|
||||
/// </summary>
|
||||
VanityUrl = 1 << 18,
|
||||
/// <summary>
|
||||
/// The guild is verified.
|
||||
/// </summary>
|
||||
Verified = 1 << 19,
|
||||
/// <summary>
|
||||
/// The guild has access to set 384kbps bitrate in voice (previously VIP voice servers).
|
||||
/// </summary>
|
||||
VIPRegions = 1 << 20,
|
||||
/// <summary>
|
||||
/// The guild has enabled the welcome screen.
|
||||
/// </summary>
|
||||
WelcomeScreenEnabled = 1 << 21,
|
||||
}
|
||||
}
|
||||
46
src/Discord.Net.Core/Entities/Guilds/GuildFeatures.cs
Normal file
46
src/Discord.Net.Core/Entities/Guilds/GuildFeatures.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
public class GuildFeatures
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the flags of recognized features for this guild.
|
||||
/// </summary>
|
||||
public GuildFeature Value { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of experimental features for this guild.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<string> Experimental { get; }
|
||||
|
||||
|
||||
internal GuildFeatures(GuildFeature value, string[] experimental)
|
||||
{
|
||||
Value = value;
|
||||
Experimental = experimental.ToImmutableArray();
|
||||
}
|
||||
|
||||
public bool HasFeature(GuildFeature feature)
|
||||
=> Value.HasFlag(feature);
|
||||
public bool HasFeature(string feature)
|
||||
=> Experimental.Contains(feature);
|
||||
|
||||
internal void EnsureFeature(GuildFeature feature)
|
||||
{
|
||||
if (!HasFeature(feature))
|
||||
{
|
||||
var vals = Enum.GetValues(typeof(GuildFeature)).Cast<GuildFeature>();
|
||||
|
||||
var missingValues = vals.Where(x => feature.HasFlag(x) && !Value.HasFlag(x));
|
||||
|
||||
throw new InvalidOperationException($"Missing required guild feature{(missingValues.Count() > 1 ? "s" : "")} {string.Join(", ", missingValues.Select(x => x.ToString()))} in order to execute this operation.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,8 +85,9 @@ namespace Discord
|
||||
/// given that the <see cref="SystemChannelId"/> has also been set.
|
||||
/// A value of <see cref="SystemChannelMessageDeny.GuildBoost"/> will deny guild boost messages from being sent, and allow all
|
||||
/// other types of messages.
|
||||
/// Refer to the extension methods <see cref="GuildExtensions.GetGuildBoostMessagesEnabled(IGuild)"/> and
|
||||
/// <see cref="GuildExtensions.GetWelcomeMessagesEnabled(IGuild)"/> to check if these system channel message types
|
||||
/// Refer to the extension methods <see cref="GuildExtensions.GetGuildBoostMessagesEnabled(IGuild)"/>,
|
||||
/// <see cref="GuildExtensions.GetWelcomeMessagesEnabled(IGuild)"/>, <see cref="GuildExtensions.GetGuildSetupTipMessagesEnabled(IGuild)"/>,
|
||||
/// and <see cref="GuildExtensions.GetGuildWelcomeMessageReplyEnabled(IGuild)"/> to check if these system channel message types
|
||||
/// are enabled, without the need to manipulate the logic of the flag.
|
||||
/// </remarks>
|
||||
public Optional<SystemChannelMessageDeny> SystemChannelFlags { get; set; }
|
||||
@@ -108,5 +109,9 @@ namespace Discord
|
||||
/// the value of <see cref="PreferredCulture"/> will be unused.
|
||||
/// </remarks>
|
||||
public Optional<CultureInfo> PreferredCulture { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets if the boost progress bar is enabled.
|
||||
/// </summary>
|
||||
public Optional<bool> IsBoostProgressBarEnabled { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the privacy level of a guild scheduled event.
|
||||
/// </summary>
|
||||
public enum GuildScheduledEventPrivacyLevel
|
||||
{
|
||||
/// <summary>
|
||||
/// The scheduled event is public and available in discovery.
|
||||
/// </summary>
|
||||
[Obsolete("This event type isn't supported yet! check back later.", true)]
|
||||
Public = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The scheduled event is only accessible to guild members.
|
||||
/// </summary>
|
||||
Private = 2,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the status of a guild event.
|
||||
/// </summary>
|
||||
public enum GuildScheduledEventStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// The event is scheduled for a set time.
|
||||
/// </summary>
|
||||
Scheduled = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The event has started.
|
||||
/// </summary>
|
||||
Active = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The event was completed.
|
||||
/// </summary>
|
||||
Completed = 3,
|
||||
|
||||
/// <summary>
|
||||
/// The event was canceled.
|
||||
/// </summary>
|
||||
Cancelled = 4,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the type of a guild scheduled event.
|
||||
/// </summary>
|
||||
public enum GuildScheduledEventType
|
||||
{
|
||||
/// <summary>
|
||||
/// The event doesn't have a set type.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The event is set in a stage channel.
|
||||
/// </summary>
|
||||
Stage = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The event is set in a voice channel.
|
||||
/// </summary>
|
||||
Voice = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The event is set for somewhere externally from discord.
|
||||
/// </summary>
|
||||
External = 3,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides properties that are used to modify an <see cref="IGuildScheduledEvent" /> with the specified changes.
|
||||
/// </summary>
|
||||
public class GuildScheduledEventsProperties
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the channel id of the event.
|
||||
/// </summary>
|
||||
public Optional<ulong?> ChannelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the location of this event.
|
||||
/// </summary>
|
||||
public Optional<string> Location { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the event.
|
||||
/// </summary>
|
||||
public Optional<string> Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the privacy level of the event.
|
||||
/// </summary>
|
||||
public Optional<GuildScheduledEventPrivacyLevel> PrivacyLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the start time of the event.
|
||||
/// </summary>
|
||||
public Optional<DateTimeOffset> StartTime { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the end time of the event.
|
||||
/// </summary>
|
||||
public Optional<DateTimeOffset> EndTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the description of the event.
|
||||
/// </summary>
|
||||
public Optional<string> Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the event.
|
||||
/// </summary>
|
||||
public Optional<GuildScheduledEventType> Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the status of the event.
|
||||
/// </summary>
|
||||
public Optional<GuildScheduledEventStatus> Status { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using Discord.Audio;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
@@ -199,12 +200,19 @@ namespace Discord
|
||||
/// </returns>
|
||||
IReadOnlyCollection<GuildEmote> Emotes { get; }
|
||||
/// <summary>
|
||||
/// Gets a collection of all extra features added to this guild.
|
||||
/// Gets a collection of all custom stickers for this guild.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A read-only collection of enabled features in this guild.
|
||||
/// A read-only collection of all custom stickers for this guild.
|
||||
/// </returns>
|
||||
IReadOnlyCollection<string> Features { get; }
|
||||
IReadOnlyCollection<ICustomSticker> Stickers { get; }
|
||||
/// <summary>
|
||||
/// Gets the features for this guild.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A flags enum containing all the features for the guild.
|
||||
/// </returns>
|
||||
GuildFeatures Features { get; }
|
||||
/// <summary>
|
||||
/// Gets a collection of all roles in this guild.
|
||||
/// </summary>
|
||||
@@ -316,6 +324,14 @@ namespace Discord
|
||||
/// </returns>
|
||||
string PreferredLocale { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the NSFW level of this guild.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The NSFW level of this guild.
|
||||
/// </returns>
|
||||
NsfwLevel NsfwLevel { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the preferred culture of this guild.
|
||||
/// </summary>
|
||||
@@ -323,6 +339,13 @@ namespace Discord
|
||||
/// The preferred culture information of this guild.
|
||||
/// </returns>
|
||||
CultureInfo PreferredCulture { get; }
|
||||
/// <summary>
|
||||
/// Gets whether the guild has the boost progress bar enabled.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if the boost progress bar is enabled; otherwise <see langword="false"/>.
|
||||
/// </returns>
|
||||
bool IsBoostProgressBarEnabled { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Modifies this guild.
|
||||
@@ -522,6 +545,27 @@ namespace Discord
|
||||
/// </returns>
|
||||
Task<IVoiceChannel> GetVoiceChannelAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
|
||||
/// <summary>
|
||||
/// Gets a stage channel in this guild.
|
||||
/// </summary>
|
||||
/// <param name="id">The snowflake identifier for the stage channel.</param>
|
||||
/// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous get operation. The task result contains the stage channel associated
|
||||
/// with the specified <paramref name="id"/>; <see langword="null" /> if none is found.
|
||||
/// </returns>
|
||||
Task<IStageChannel> GetStageChannelAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
|
||||
/// <summary>
|
||||
/// Gets a collection of all stage channels in this guild.
|
||||
/// </summary>
|
||||
/// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous get operation. The task result contains a read-only collection of
|
||||
/// stage channels found within this guild.
|
||||
/// </returns>
|
||||
Task<IReadOnlyCollection<IStageChannel>> GetStageChannelsAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
|
||||
/// <summary>
|
||||
/// Gets the AFK voice channel in this guild.
|
||||
/// </summary>
|
||||
/// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param>
|
||||
@@ -572,15 +616,35 @@ namespace Discord
|
||||
/// </returns>
|
||||
Task<ITextChannel> GetRulesChannelAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
|
||||
/// <summary>
|
||||
/// Gets the text channel channel where admins and moderators of Community guilds receive notices from Discord.
|
||||
/// Gets the text channel where admins and moderators of Community guilds receive notices from Discord.
|
||||
/// </summary>
|
||||
/// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous get operation. The task result contains the text channel channel where
|
||||
/// A task that represents the asynchronous get operation. The task result contains the text channel where
|
||||
/// admins and moderators of Community guilds receive notices from Discord; <see langword="null" /> if none is set.
|
||||
/// </returns>
|
||||
Task<ITextChannel> GetPublicUpdatesChannelAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
|
||||
/// <summary>
|
||||
/// Gets a thread channel within this guild.
|
||||
/// </summary>
|
||||
/// <param name="id">The id of the thread channel.</param>
|
||||
/// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous get operation. The task result contains the thread channel.
|
||||
/// </returns>
|
||||
Task<IThreadChannel> GetThreadChannelAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
|
||||
/// <summary>
|
||||
/// Gets a collection of all thread channels in this guild.
|
||||
/// </summary>
|
||||
/// <param name="mode">The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous get operation. The task result contains a read-only collection of
|
||||
/// thread channels found within this guild.
|
||||
/// </returns>
|
||||
Task<IReadOnlyCollection<IThreadChannel>> GetThreadChannelsAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new text channel in this guild.
|
||||
@@ -610,6 +674,17 @@ namespace Discord
|
||||
/// </returns>
|
||||
Task<IVoiceChannel> CreateVoiceChannelAsync(string name, Action<VoiceChannelProperties> func = null, RequestOptions options = null);
|
||||
/// <summary>
|
||||
/// Creates a new stage channel in this guild.
|
||||
/// </summary>
|
||||
/// <param name="name">The new name for the stage channel.</param>
|
||||
/// <param name="func">The delegate containing the properties to be applied to the channel upon its creation.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous creation operation. The task result contains the newly created
|
||||
/// stage channel.
|
||||
/// </returns>
|
||||
Task<IStageChannel> CreateStageChannelAsync(string name, Action<VoiceChannelProperties> func = null, RequestOptions options = null);
|
||||
/// <summary>
|
||||
/// Creates a new channel category in this guild.
|
||||
/// </summary>
|
||||
/// <param name="name">The new name for the category.</param>
|
||||
@@ -703,6 +778,12 @@ namespace Discord
|
||||
/// <returns>A guild user associated with the specified <paramref name="userId" />; <see langword="null" /> if the user is already in the guild.</returns>
|
||||
Task<IGuildUser> AddGuildUserAsync(ulong userId, string accessToken, Action<AddGuildUserProperties> func = null, RequestOptions options = null);
|
||||
/// <summary>
|
||||
/// Disconnects the user from its current voice channel.
|
||||
/// </summary>
|
||||
/// <param name="user">The user to disconnect.</param>
|
||||
/// <returns>A task that represents the asynchronous operation for disconnecting a user.</returns>
|
||||
Task DisconnectAsync(IGuildUser user);
|
||||
/// <summary>
|
||||
/// Gets a collection of all users in this guild.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
@@ -760,7 +841,7 @@ namespace Discord
|
||||
/// Downloads all users for this guild if the current list is incomplete.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method downloads all users found within this guild throught the Gateway and caches them.
|
||||
/// This method downloads all users found within this guild through the Gateway and caches them.
|
||||
/// </remarks>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous download operation.
|
||||
@@ -883,6 +964,15 @@ namespace Discord
|
||||
/// emote.
|
||||
/// </returns>
|
||||
Task<GuildEmote> ModifyEmoteAsync(GuildEmote emote, Action<EmoteProperties> func, RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Moves the user to the voice channel.
|
||||
/// </summary>
|
||||
/// <param name="user">The user to move.</param>
|
||||
/// <param name="targetChannel">the channel where the user gets moved to.</param>
|
||||
/// <returns>A task that represents the asynchronous operation for moving a user.</returns>
|
||||
Task MoveAsync(IGuildUser user, IVoiceChannel targetChannel);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes an existing <see cref="GuildEmote"/> from this guild.
|
||||
/// </summary>
|
||||
@@ -892,5 +982,174 @@ namespace Discord
|
||||
/// A task that represents the asynchronous removal operation.
|
||||
/// </returns>
|
||||
Task DeleteEmoteAsync(GuildEmote emote, RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new sticker in this guild.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the sticker.</param>
|
||||
/// <param name="description">The description of the sticker.</param>
|
||||
/// <param name="tags">The tags of the sticker.</param>
|
||||
/// <param name="image">The image of the new emote.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous creation operation. The task result contains the created sticker.
|
||||
/// </returns>
|
||||
Task<ICustomSticker> CreateStickerAsync(string name, string description, IEnumerable<string> tags, Image image, RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new sticker in this guild.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the sticker.</param>
|
||||
/// <param name="description">The description of the sticker.</param>
|
||||
/// <param name="tags">The tags of the sticker.</param>
|
||||
/// <param name="path">The path of the file to upload.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous creation operation. The task result contains the created sticker.
|
||||
/// </returns>
|
||||
Task<ICustomSticker> CreateStickerAsync(string name, string description, IEnumerable<string> tags, string path, RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new sticker in this guild.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the sticker.</param>
|
||||
/// <param name="description">The description of the sticker.</param>
|
||||
/// <param name="tags">The tags of the sticker.</param>
|
||||
/// <param name="stream">The stream containing the file data.</param>
|
||||
/// <param name="filename">The name of the file <b>with</b> the extension, ex: image.png.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous creation operation. The task result contains the created sticker.
|
||||
/// </returns>
|
||||
Task<ICustomSticker> CreateStickerAsync(string name, string description, IEnumerable<string> tags, Stream stream, string filename, RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a specific sticker within this guild.
|
||||
/// </summary>
|
||||
/// <param name="id">The id of the sticker to get.</param>
|
||||
/// <param name="mode">The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous get operation. The task result contains the sticker found with the
|
||||
/// specified <paramref name="id"/>; <see langword="null" /> if none is found.
|
||||
/// </returns>
|
||||
Task<ICustomSticker> GetStickerAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of all stickers within this guild.
|
||||
/// </summary>
|
||||
/// <param name="mode">The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous get operation. The task result contains a read-only collection
|
||||
/// of stickers found within the guild.
|
||||
/// </returns>
|
||||
Task<IReadOnlyCollection<ICustomSticker>> GetStickersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a sticker within this guild.
|
||||
/// </summary>
|
||||
/// <param name="sticker">The sticker to delete.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous removal operation.
|
||||
/// </returns>
|
||||
Task DeleteStickerAsync(ICustomSticker sticker, RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a event within this guild.
|
||||
/// </summary>
|
||||
/// <param name="id">The id of the event.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous get operation.
|
||||
/// </returns>
|
||||
Task<IGuildScheduledEvent> GetEventAsync(ulong id, RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of events within this guild.
|
||||
/// </summary>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous get operation.
|
||||
/// </returns>
|
||||
Task<IReadOnlyCollection<IGuildScheduledEvent>> GetEventsAsync(RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an event within this guild.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the event.</param>
|
||||
/// <param name="privacyLevel">The privacy level of the event.</param>
|
||||
/// <param name="startTime">The start time of the event.</param>
|
||||
/// <param name="type">The type of the event.</param>
|
||||
/// <param name="description">The description of the event.</param>
|
||||
/// <param name="endTime">The end time of the event.</param>
|
||||
/// <param name="channelId">
|
||||
/// The channel id of the event.
|
||||
/// <remarks>
|
||||
/// The event must have a type of <see cref="GuildScheduledEventType.Stage"/> or <see cref="GuildScheduledEventType.Voice"/>
|
||||
/// in order to use this property.
|
||||
/// </remarks>
|
||||
/// </param>
|
||||
/// <param name="speakers">A collection of speakers for the event.</param>
|
||||
/// <param name="location">The location of the event; links are supported</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous create operation.
|
||||
/// </returns>
|
||||
Task<IGuildScheduledEvent> CreateEventAsync(
|
||||
string name,
|
||||
DateTimeOffset startTime,
|
||||
GuildScheduledEventType type,
|
||||
GuildScheduledEventPrivacyLevel privacyLevel = GuildScheduledEventPrivacyLevel.Private,
|
||||
string description = null,
|
||||
DateTimeOffset? endTime = null,
|
||||
ulong? channelId = null,
|
||||
string location = null,
|
||||
RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets this guilds application commands.
|
||||
/// </summary>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous get operation. The task result contains a read-only collection
|
||||
/// of application commands found within the guild.
|
||||
/// </returns>
|
||||
Task<IReadOnlyCollection<IApplicationCommand>> GetApplicationCommandsAsync(RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an application command within this guild with the specified id.
|
||||
/// </summary>
|
||||
/// <param name="id">The id of the application command to get.</param>
|
||||
/// <param name="mode">The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A ValueTask that represents the asynchronous get operation. The task result contains a <see cref="IApplicationCommand"/>
|
||||
/// if found, otherwise <see langword="null"/>.
|
||||
/// </returns>
|
||||
Task<IApplicationCommand> GetApplicationCommandAsync(ulong id, CacheMode mode = CacheMode.AllowDownload,
|
||||
RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an application command within this guild.
|
||||
/// </summary>
|
||||
/// <param name="properties">The properties to use when creating the command.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous creation operation. The task result contains the command that was created.
|
||||
/// </returns>
|
||||
Task<IApplicationCommand> CreateApplicationCommandAsync(ApplicationCommandProperties properties, RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Overwrites the application commands within this guild.
|
||||
/// </summary>
|
||||
/// <param name="properties">A collection of properties to use when creating the commands.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous creation operation. The task result contains a collection of commands that was created.
|
||||
/// </returns>
|
||||
Task<IReadOnlyCollection<IApplicationCommand>> BulkOverwriteApplicationCommandsAsync(ApplicationCommandProperties[] properties,
|
||||
RequestOptions options = null);
|
||||
}
|
||||
}
|
||||
|
||||
170
src/Discord.Net.Core/Entities/Guilds/IGuildScheduledEvent.cs
Normal file
170
src/Discord.Net.Core/Entities/Guilds/IGuildScheduledEvent.cs
Normal file
@@ -0,0 +1,170 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a generic guild scheduled event.
|
||||
/// </summary>
|
||||
public interface IGuildScheduledEvent : IEntity<ulong>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the guild this event is scheduled in.
|
||||
/// </summary>
|
||||
IGuild Guild { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the optional channel id where this event will be hosted.
|
||||
/// </summary>
|
||||
ulong? ChannelId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user who created the event.
|
||||
/// </summary>
|
||||
IUser Creator { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the event.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description of the event.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field is <see langword="null"/> when the event doesn't have a discription.
|
||||
/// </remarks>
|
||||
string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the start time of the event.
|
||||
/// </summary>
|
||||
DateTimeOffset StartTime { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the optional end time of the event.
|
||||
/// </summary>
|
||||
DateTimeOffset? EndTime { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the privacy level of the event.
|
||||
/// </summary>
|
||||
GuildScheduledEventPrivacyLevel PrivacyLevel { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the status of the event.
|
||||
/// </summary>
|
||||
GuildScheduledEventStatus Status { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the event.
|
||||
/// </summary>
|
||||
GuildScheduledEventType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the optional entity id of the event. The "entity" of the event
|
||||
/// can be a stage instance event as is seperate from <see cref="ChannelId"/>.
|
||||
/// </summary>
|
||||
ulong? EntityId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the location of the event if the <see cref="Type"/> is external.
|
||||
/// </summary>
|
||||
string Location { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user count of the event.
|
||||
/// </summary>
|
||||
int? UserCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Starts the event.
|
||||
/// </summary>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous start operation.
|
||||
/// </returns>
|
||||
Task StartAsync(RequestOptions options = null);
|
||||
/// <summary>
|
||||
/// Ends or canceles the event.
|
||||
/// </summary>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous end operation.
|
||||
/// </returns>
|
||||
Task EndAsync(RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Modifies the guild event.
|
||||
/// </summary>
|
||||
/// <param name="func">The delegate containing the properties to modify the event with.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous modification operation.
|
||||
/// </returns>
|
||||
Task ModifyAsync(Action<GuildScheduledEventsProperties> func, RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the current event.
|
||||
/// </summary>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous delete operation.
|
||||
/// </returns>
|
||||
Task DeleteAsync(RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of N users interested in the event.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <note type="important">
|
||||
/// The returned collection is an asynchronous enumerable object; one must call
|
||||
/// <see cref="AsyncEnumerableExtensions.FlattenAsync{T}"/> to access the individual messages as a
|
||||
/// collection.
|
||||
/// </note>
|
||||
/// This method will attempt to fetch all users that are interested in the event.
|
||||
/// The library will attempt to split up the requests according to and <see cref="DiscordConfig.MaxGuildEventUsersPerBatch"/>.
|
||||
/// In other words, if there are 300 users, and the <see cref="Discord.DiscordConfig.MaxGuildEventUsersPerBatch"/> constant
|
||||
/// is <c>100</c>, the request will be split into 3 individual requests; thus returning 3 individual asynchronous
|
||||
/// responses, hence the need of flattening.
|
||||
/// </remarks>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// Paged collection of users.
|
||||
/// </returns>
|
||||
IAsyncEnumerable<IReadOnlyCollection<IUser>> GetUsersAsync(RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of N users interested in the event.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <note type="important">
|
||||
/// The returned collection is an asynchronous enumerable object; one must call
|
||||
/// <see cref="AsyncEnumerableExtensions.FlattenAsync{T}"/> to access the individual users as a
|
||||
/// collection.
|
||||
/// </note>
|
||||
/// <note type="warning">
|
||||
/// Do not fetch too many users at once! This may cause unwanted preemptive rate limit or even actual
|
||||
/// rate limit, causing your bot to freeze!
|
||||
/// </note>
|
||||
/// This method will attempt to fetch the number of users specified under <paramref name="limit"/> around
|
||||
/// the user <paramref name="fromUserId"/> depending on the <paramref name="dir"/>. The library will
|
||||
/// attempt to split up the requests according to your <paramref name="limit"/> and
|
||||
/// <see cref="DiscordConfig.MaxGuildEventUsersPerBatch"/>. In other words, should the user request 500 users,
|
||||
/// and the <see cref="Discord.DiscordConfig.MaxGuildEventUsersPerBatch"/> constant is <c>100</c>, the request will
|
||||
/// be split into 5 individual requests; thus returning 5 individual asynchronous responses, hence the need
|
||||
/// of flattening.
|
||||
/// </remarks>
|
||||
/// <param name="fromUserId">The ID of the starting user to get the users from.</param>
|
||||
/// <param name="dir">The direction of the users to be gotten from.</param>
|
||||
/// <param name="limit">The numbers of users to be gotten from.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// Paged collection of users.
|
||||
/// </returns>
|
||||
IAsyncEnumerable<IReadOnlyCollection<IUser>> GetUsersAsync(ulong fromUserId, Direction dir, int limit = DiscordConfig.MaxGuildEventUsersPerBatch, RequestOptions options = null);
|
||||
}
|
||||
}
|
||||
22
src/Discord.Net.Core/Entities/Guilds/NsfwLevel.cs
Normal file
22
src/Discord.Net.Core/Entities/Guilds/NsfwLevel.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
namespace Discord
|
||||
{
|
||||
public enum NsfwLevel
|
||||
{
|
||||
/// <summary>
|
||||
/// Default or unset.
|
||||
/// </summary>
|
||||
Default = 0,
|
||||
/// <summary>
|
||||
/// Guild has extremely suggestive or mature content that would only be suitable for users 18 or over.
|
||||
/// </summary>
|
||||
Explicit = 1,
|
||||
/// <summary>
|
||||
/// Guild has no content that could be deemed NSFW; in other words, SFW.
|
||||
/// </summary>
|
||||
Safe = 2,
|
||||
/// <summary>
|
||||
/// Guild has mildly NSFW content that may not be suitable for users under 18.
|
||||
/// </summary>
|
||||
AgeRestricted = 3
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,14 @@ namespace Discord
|
||||
/// <summary>
|
||||
/// Deny the messages that are sent when a user boosts the guild.
|
||||
/// </summary>
|
||||
GuildBoost = 0b10
|
||||
GuildBoost = 0b10,
|
||||
/// <summary>
|
||||
/// Deny the messages that are related to guild setup.
|
||||
/// </summary>
|
||||
GuildSetupTip = 0b100,
|
||||
/// <summary>
|
||||
/// Deny the reply with sticker button on welcome messages.
|
||||
/// </summary>
|
||||
WelcomeMessageReply = 0b1000
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
@@ -16,8 +18,16 @@ namespace Discord
|
||||
/// <summary>
|
||||
/// Gets the RPC origins of the application.
|
||||
/// </summary>
|
||||
string[] RPCOrigins { get; }
|
||||
ulong Flags { get; }
|
||||
IReadOnlyCollection<string> RPCOrigins { get; }
|
||||
ApplicationFlags Flags { get; }
|
||||
/// <summary>
|
||||
/// Gets a collection of install parameters for this application.
|
||||
/// </summary>
|
||||
ApplicationInstallParams InstallParams { get; }
|
||||
/// <summary>
|
||||
/// Gets a collection of tags related to the application.
|
||||
/// </summary>
|
||||
IReadOnlyCollection<string> Tags { get; }
|
||||
/// <summary>
|
||||
/// Gets the icon URL of the application.
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a <see cref="IApplicationCommandOption"/> for making slash commands.
|
||||
/// </summary>
|
||||
public class ApplicationCommandOptionProperties
|
||||
{
|
||||
private string _name;
|
||||
private string _description;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of this option.
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException(nameof(value), $"{nameof(Name)} cannot be null.");
|
||||
|
||||
if (value.Length > 32)
|
||||
throw new ArgumentOutOfRangeException(nameof(value), "Name length must be less than or equal to 32.");
|
||||
|
||||
if (!Regex.IsMatch(value, @"^[\w-]{1,32}$"))
|
||||
throw new FormatException($"{nameof(value)} must match the regex ^[\\w-]{{1,32}}$");
|
||||
|
||||
_name = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the description of this option.
|
||||
/// </summary>
|
||||
public string Description
|
||||
{
|
||||
get => _description;
|
||||
set => _description = value?.Length switch
|
||||
{
|
||||
> 100 => throw new ArgumentOutOfRangeException(nameof(value), "Description length must be less than or equal to 100."),
|
||||
0 => throw new ArgumentOutOfRangeException(nameof(value), "Description length must be at least 1."),
|
||||
_ => value
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of this option.
|
||||
/// </summary>
|
||||
public ApplicationCommandOptionType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether or not this options is the first required option for the user to complete. only one option can be default.
|
||||
/// </summary>
|
||||
public bool? IsDefault { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if the option is required.
|
||||
/// </summary>
|
||||
public bool? IsRequired { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether or not this option supports autocomplete.
|
||||
/// </summary>
|
||||
public bool IsAutocomplete { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the smallest number value the user can input.
|
||||
/// </summary>
|
||||
public double? MinValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the largest number value the user can input.
|
||||
/// </summary>
|
||||
public double? MaxValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the choices for string and int types for the user to pick from.
|
||||
/// </summary>
|
||||
public List<ApplicationCommandOptionChoiceProperties> Choices { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if this option is a subcommand or subcommand group type, these nested options will be the parameters.
|
||||
/// </summary>
|
||||
public List<ApplicationCommandOptionProperties> Options { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the allowed channel types for this option.
|
||||
/// </summary>
|
||||
public List<ChannelType> ChannelTypes { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a choice for a <see cref="IApplicationCommandInteractionDataOption"/>. This class is used when making new commands.
|
||||
/// </summary>
|
||||
public class ApplicationCommandOptionChoiceProperties
|
||||
{
|
||||
private string _name;
|
||||
private object _value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of this choice.
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set => _name = value?.Length switch
|
||||
{
|
||||
> 100 => throw new ArgumentOutOfRangeException(nameof(value), "Name length must be less than or equal to 100."),
|
||||
0 => throw new ArgumentOutOfRangeException(nameof(value), "Name length must at least 1."),
|
||||
_ => value
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of this choice.
|
||||
/// <note type="warning">
|
||||
/// Discord only accepts int, double/floats, and string as the input.
|
||||
/// </note>
|
||||
/// </summary>
|
||||
public object Value
|
||||
{
|
||||
get => _value;
|
||||
set
|
||||
{
|
||||
if (value != null && value is not string && !value.IsNumericType())
|
||||
throw new ArgumentException("The value of a choice must be a string or a numeric type!");
|
||||
_value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// The option type of the Slash command parameter, See <see href="https://discord.com/developers/docs/interactions/slash-commands#applicationcommandoptiontype">the discord docs</see>.
|
||||
/// </summary>
|
||||
public enum ApplicationCommandOptionType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// A sub command.
|
||||
/// </summary>
|
||||
SubCommand = 1,
|
||||
|
||||
/// <summary>
|
||||
/// A group of sub commands.
|
||||
/// </summary>
|
||||
SubCommandGroup = 2,
|
||||
|
||||
/// <summary>
|
||||
/// A <see langword="string"/> of text.
|
||||
/// </summary>
|
||||
String = 3,
|
||||
|
||||
/// <summary>
|
||||
/// An <see langword="int"/>.
|
||||
/// </summary>
|
||||
Integer = 4,
|
||||
|
||||
/// <summary>
|
||||
/// A <see langword="bool"/>.
|
||||
/// </summary>
|
||||
Boolean = 5,
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="IUser"/>.
|
||||
/// </summary>
|
||||
User = 6,
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="IGuildChannel"/>.
|
||||
/// </summary>
|
||||
Channel = 7,
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="IRole"/>.
|
||||
/// </summary>
|
||||
Role = 8,
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="IUser"/> or <see cref="IRole"/>.
|
||||
/// </summary>
|
||||
Mentionable = 9,
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="double"/>.
|
||||
/// </summary>
|
||||
Number = 10
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the base class to create/modify application commands.
|
||||
/// </summary>
|
||||
public abstract class ApplicationCommandProperties
|
||||
{
|
||||
internal abstract ApplicationCommandType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of this command.
|
||||
/// </summary>
|
||||
public Optional<string> Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether the command is enabled by default when the app is added to a guild. Default is <see langword="true"/>
|
||||
/// </summary>
|
||||
public Optional<bool> IsDefaultPermission { get; set; }
|
||||
|
||||
internal ApplicationCommandProperties() { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the types of application commands.
|
||||
/// </summary>
|
||||
public enum ApplicationCommandType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// A Slash command type
|
||||
/// </summary>
|
||||
Slash = 1,
|
||||
|
||||
/// <summary>
|
||||
/// A Context Menu User command type
|
||||
/// </summary>
|
||||
User = 2,
|
||||
|
||||
/// <summary>
|
||||
/// A Context Menu Message command type
|
||||
/// </summary>
|
||||
Message = 3
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an autocomplete option.
|
||||
/// </summary>
|
||||
public class AutocompleteOption
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the type of this option.
|
||||
/// </summary>
|
||||
public ApplicationCommandOptionType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the option.
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the option.
|
||||
/// </summary>
|
||||
public object Value { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not this option is focused by the executing user.
|
||||
/// </summary>
|
||||
public bool Focused { get; }
|
||||
|
||||
internal AutocompleteOption(ApplicationCommandOptionType type, string name, object value, bool focused)
|
||||
{
|
||||
Type = type;
|
||||
Name = name;
|
||||
Value = value;
|
||||
Focused = focused;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a result to an autocomplete interaction.
|
||||
/// </summary>
|
||||
public class AutocompleteResult
|
||||
{
|
||||
private object _value;
|
||||
private string _name;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the result.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Name cannot be null and has to be between 1-100 characters in length.
|
||||
/// </remarks>
|
||||
/// <exception cref="ArgumentNullException"/>
|
||||
/// <exception cref="ArgumentException"/>
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException(nameof(value), $"{nameof(Name)} cannot be null.");
|
||||
_name = value.Length switch
|
||||
{
|
||||
> 100 => throw new ArgumentOutOfRangeException(nameof(value), "Name length must be less than or equal to 100."),
|
||||
0 => throw new ArgumentOutOfRangeException(nameof(value), "Name length must be at least 1."),
|
||||
_ => value
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the result.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Only <see cref="string"/>, <see cref="int"/>, and <see cref="double"/> are allowed for a value.
|
||||
/// </remarks>
|
||||
/// <exception cref="ArgumentNullException"/>
|
||||
/// <exception cref="ArgumentException"/>
|
||||
public object Value
|
||||
{
|
||||
get => _value;
|
||||
set
|
||||
{
|
||||
if (value is not string && !value.IsNumericType())
|
||||
throw new ArgumentException($"{nameof(value)} must be a numeric type or a string!");
|
||||
|
||||
_value = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="AutocompleteResult"/>.
|
||||
/// </summary>
|
||||
public AutocompleteResult() { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="AutocompleteResult"/> with the passed in <paramref name="name"/> and <paramref name="value"/>.
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentNullException"/>
|
||||
/// <exception cref="ArgumentException"/>
|
||||
public AutocompleteResult(string name, object value)
|
||||
{
|
||||
Name = name;
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a Message Command interaction.
|
||||
/// </summary>
|
||||
public interface IMessageCommandInteraction : IDiscordInteraction
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the data associated with this interaction.
|
||||
/// </summary>
|
||||
new IMessageCommandInteractionData Data { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the data tied with the <see cref="IMessageCommandInteraction"/> interaction.
|
||||
/// </summary>
|
||||
public interface IMessageCommandInteractionData : IApplicationCommandInteractionData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the message associated with this message command.
|
||||
/// </summary>
|
||||
IMessage Message { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a User Command interaction.
|
||||
/// </summary>
|
||||
public interface IUserCommandInteraction : IDiscordInteraction
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the data associated with this interaction.
|
||||
/// </summary>
|
||||
new IUserCommandInteractionData Data { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the data tied with the <see cref="IUserCommandInteraction"/> interaction.
|
||||
/// </summary>
|
||||
public interface IUserCommandInteractionData : IApplicationCommandInteractionData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the user who this command targets.
|
||||
/// </summary>
|
||||
IUser User { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// A class used to build Message commands.
|
||||
/// </summary>
|
||||
public class MessageCommandBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the maximum length a commands name allowed by Discord
|
||||
/// </summary>
|
||||
public const int MaxNameLength = 32;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of this Message command.
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set
|
||||
{
|
||||
Preconditions.NotNullOrEmpty(value, nameof(Name));
|
||||
Preconditions.AtLeast(value.Length, 1, nameof(Name));
|
||||
Preconditions.AtMost(value.Length, MaxNameLength, nameof(Name));
|
||||
|
||||
_name = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether the command is enabled by default when the app is added to a guild
|
||||
/// </summary>
|
||||
public bool IsDefaultPermission { get; set; } = true;
|
||||
|
||||
private string _name;
|
||||
|
||||
/// <summary>
|
||||
/// Build the current builder into a <see cref="MessageCommandProperties"/> class.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="MessageCommandProperties"/> that can be used to create message commands.
|
||||
/// </returns>
|
||||
public MessageCommandProperties Build()
|
||||
{
|
||||
var props = new MessageCommandProperties
|
||||
{
|
||||
Name = Name,
|
||||
IsDefaultPermission = IsDefaultPermission
|
||||
};
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the field name.
|
||||
/// </summary>
|
||||
/// <param name="name">The value to set the field name to.</param>
|
||||
/// <returns>
|
||||
/// The current builder.
|
||||
/// </returns>
|
||||
public MessageCommandBuilder WithName(string name)
|
||||
{
|
||||
Name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the default permission of the current command.
|
||||
/// </summary>
|
||||
/// <param name="isDefaultPermission">The default permission value to set.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public MessageCommandBuilder WithDefaultPermission(bool isDefaultPermission)
|
||||
{
|
||||
IsDefaultPermission = isDefaultPermission;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// A class used to create message commands.
|
||||
/// </summary>
|
||||
public class MessageCommandProperties : ApplicationCommandProperties
|
||||
{
|
||||
internal override ApplicationCommandType Type => ApplicationCommandType.Message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// A class used to build user commands.
|
||||
/// </summary>
|
||||
public class UserCommandBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the maximum length a commands name allowed by Discord.
|
||||
/// </summary>
|
||||
public const int MaxNameLength = 32;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of this User command.
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set
|
||||
{
|
||||
Preconditions.NotNullOrEmpty(value, nameof(Name));
|
||||
Preconditions.AtLeast(value.Length, 1, nameof(Name));
|
||||
Preconditions.AtMost(value.Length, MaxNameLength, nameof(Name));
|
||||
|
||||
_name = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether the command is enabled by default when the app is added to a guild.
|
||||
/// </summary>
|
||||
public bool IsDefaultPermission { get; set; } = true;
|
||||
|
||||
private string _name;
|
||||
|
||||
/// <summary>
|
||||
/// Build the current builder into a <see cref="UserCommandProperties"/> class.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="UserCommandProperties"/> that can be used to create user commands.</returns>
|
||||
public UserCommandProperties Build()
|
||||
{
|
||||
var props = new UserCommandProperties
|
||||
{
|
||||
Name = Name,
|
||||
IsDefaultPermission = IsDefaultPermission
|
||||
};
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the field name.
|
||||
/// </summary>
|
||||
/// <param name="name">The value to set the field name to.</param>
|
||||
/// <returns>
|
||||
/// The current builder.
|
||||
/// </returns>
|
||||
public UserCommandBuilder WithName(string name)
|
||||
{
|
||||
Name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the default permission of the current command.
|
||||
/// </summary>
|
||||
/// <param name="isDefaultPermission">The default permission value to set.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public UserCommandBuilder WithDefaultPermission(bool isDefaultPermission)
|
||||
{
|
||||
IsDefaultPermission = isDefaultPermission;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// A class used to create User commands.
|
||||
/// </summary>
|
||||
public class UserCommandProperties : ApplicationCommandProperties
|
||||
{
|
||||
internal override ApplicationCommandType Type => ApplicationCommandType.User;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// The base command model that belongs to an application.
|
||||
/// </summary>
|
||||
public interface IApplicationCommand : ISnowflakeEntity, IDeletable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the unique id of the parent application.
|
||||
/// </summary>
|
||||
ulong ApplicationId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the command.
|
||||
/// </summary>
|
||||
ApplicationCommandType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the command.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description of the command.
|
||||
/// </summary>
|
||||
string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the command is enabled by default when the app is added to a guild.
|
||||
/// </summary>
|
||||
bool IsDefaultPermission { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of options for this application command.
|
||||
/// </summary>
|
||||
IReadOnlyCollection<IApplicationCommandOption> Options { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Modifies the current application command.
|
||||
/// </summary>
|
||||
/// <param name="func">The new properties to use when modifying the command.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous modification operation.
|
||||
/// </returns>
|
||||
Task ModifyAsync(Action<ApplicationCommandProperties> func, RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Modifies the current application command.
|
||||
/// </summary>
|
||||
/// <param name="func">The new properties to use when modifying the command.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous modification operation.
|
||||
/// </returns>
|
||||
/// <exception cref="InvalidOperationException">Thrown when you pass in an invalid <see cref="ApplicationCommandProperties"/> type.</exception>
|
||||
Task ModifyAsync<TArg>(Action<TArg> func, RequestOptions options = null)
|
||||
where TArg : ApplicationCommandProperties;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents data of an Interaction Command, see <see href="https://discord.com/developers/docs/interactions/slash-commands#interaction-applicationcommandinteractiondata"/>.
|
||||
/// </summary>
|
||||
public interface IApplicationCommandInteractionData : IDiscordInteractionData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the snowflake id of this command.
|
||||
/// </summary>
|
||||
ulong Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of this command.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the options that the user has provided.
|
||||
/// </summary>
|
||||
IReadOnlyCollection<IApplicationCommandInteractionDataOption> Options { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a option group for a command.
|
||||
/// </summary>
|
||||
public interface IApplicationCommandInteractionDataOption
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name of the parameter.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the pair.
|
||||
/// <note>
|
||||
/// This objects type can be any one of the option types in <see cref="ApplicationCommandOptionType"/>.
|
||||
/// </note>
|
||||
/// </summary>
|
||||
object Value { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of this data's option.
|
||||
/// </summary>
|
||||
ApplicationCommandOptionType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the nested options of this option.
|
||||
/// </summary>
|
||||
IReadOnlyCollection<IApplicationCommandInteractionDataOption> Options { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for the <see cref="IApplicationCommand"/>.
|
||||
/// </summary>
|
||||
public interface IApplicationCommandOption
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the type of this <see cref="IApplicationCommandOption"/>.
|
||||
/// </summary>
|
||||
ApplicationCommandOptionType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of this command option.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description of this command option.
|
||||
/// </summary>
|
||||
string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not this is the first required option for the user to complete.
|
||||
/// </summary>
|
||||
bool? IsDefault { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the parameter is required or optional.
|
||||
/// </summary>
|
||||
bool? IsRequired { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the smallest number value the user can input.
|
||||
/// </summary>
|
||||
double? MinValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the largest number value the user can input.
|
||||
/// </summary>
|
||||
double? MaxValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the choices for string and int types for the user to pick from.
|
||||
/// </summary>
|
||||
IReadOnlyCollection<IApplicationCommandOptionChoice> Choices { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sub-options for this command option.
|
||||
/// </summary>
|
||||
IReadOnlyCollection<IApplicationCommandOption> Options { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the allowed channel types for this option.
|
||||
/// </summary>
|
||||
IReadOnlyCollection<ChannelType> ChannelTypes { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies choices for command group.
|
||||
/// </summary>
|
||||
public interface IApplicationCommandOptionChoice
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the choice name.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the choice.
|
||||
/// </summary>
|
||||
object Value { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a discord interaction.
|
||||
/// </summary>
|
||||
public interface IDiscordInteraction : ISnowflakeEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the id of the interaction.
|
||||
/// </summary>
|
||||
new ulong Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of this <see cref="IDiscordInteraction"/>.
|
||||
/// </summary>
|
||||
InteractionType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data sent within this interaction.
|
||||
/// </summary>
|
||||
IDiscordInteractionData Data { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the continuation token for responding to the interaction.
|
||||
/// </summary>
|
||||
string Token { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the version of the interaction, always 1.
|
||||
/// </summary>
|
||||
int Version { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Responds to an Interaction with type <see cref="InteractionResponseType.ChannelMessageWithSource"/>.
|
||||
/// </summary>
|
||||
/// <param name="text">The text of the message to be sent.</param>
|
||||
/// <param name="embeds">A array of embeds to send with this response. Max 10.</param>
|
||||
/// <param name="isTTS"><see langword="true"/> if the message should be read out by a text-to-speech reader, otherwise <see langword="false"/>.</param>
|
||||
/// <param name="ephemeral"><see langword="true"/> if the response should be hidden to everyone besides the invoker of the command, otherwise <see langword="false"/>.</param>
|
||||
/// <param name="allowedMentions">The allowed mentions for this response.</param>
|
||||
/// <param name="options">The request options for this response.</param>
|
||||
/// <param name="component">A <see cref="MessageComponent"/> to be sent with this response.</param>
|
||||
/// <param name="embed">A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored.</param>
|
||||
Task RespondAsync(string text = null, Embed[] embeds = null, bool isTTS = false,
|
||||
bool ephemeral = false, AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent component = null, Embed embed = null);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a followup message for this interaction.
|
||||
/// </summary>
|
||||
/// <param name="text">The text of the message to be sent.</param>
|
||||
/// <param name="embeds">A array of embeds to send with this response. Max 10.</param>
|
||||
/// <param name="isTTS"><see langword="true"/> if the message should be read out by a text-to-speech reader, otherwise <see langword="false"/>.</param>
|
||||
/// <param name="ephemeral"><see langword="true"/> if the response should be hidden to everyone besides the invoker of the command, otherwise <see langword="false"/>.</param>
|
||||
/// <param name="allowedMentions">The allowed mentions for this response.</param>
|
||||
/// <param name="options">The request options for this response.</param>
|
||||
/// <param name="component">A <see cref="MessageComponent"/> to be sent with this response.</param>
|
||||
/// <param name="embed">A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored.</param>
|
||||
/// <returns>
|
||||
/// The sent message.
|
||||
/// </returns>
|
||||
Task<IUserMessage> FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false,
|
||||
AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent component = null, Embed embed = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the original response for this interaction.
|
||||
/// </summary>
|
||||
/// <param name="options">The request options for this <see langword="async"/> request.</param>
|
||||
/// <returns>A <see cref="IUserMessage"/> that represents the initial response.</returns>
|
||||
Task<IUserMessage> GetOriginalResponseAsync(RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Edits original response for this interaction.
|
||||
/// </summary>
|
||||
/// <param name="func">A delegate containing the properties to modify the message with.</param>
|
||||
/// <param name="options">The request options for this <see langword="async"/> request.</param>
|
||||
/// <returns>A <see cref="IUserMessage"/> that represents the initial response.</returns>
|
||||
Task<IUserMessage> ModifyOriginalResponseAsync(Action<MessageProperties> func, RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Acknowledges this interaction.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous operation of acknowledging the interaction.
|
||||
/// </returns>
|
||||
Task DeferAsync(bool ephemeral = false, RequestOptions options = null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an interface used to specify classes that they are a valid data type of a <see cref="IDiscordInteraction"/> class.
|
||||
/// </summary>
|
||||
public interface IDiscordInteractionData { }
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// The response type for an <see cref="IDiscordInteraction"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// After receiving an interaction, you must respond to acknowledge it. You can choose to respond with a message immediately using <see cref="ChannelMessageWithSource"/>
|
||||
/// or you can choose to send a deferred response with <see cref="DeferredChannelMessageWithSource"/>. If choosing a deferred response, the user will see a loading state for the interaction,
|
||||
/// and you'll have up to 15 minutes to edit the original deferred response using Edit Original Interaction Response.
|
||||
/// You can read more about Response types <see href="https://discord.com/developers/docs/interactions/slash-commands#interaction-response">Here</see>.
|
||||
/// </remarks>
|
||||
public enum InteractionResponseType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// ACK a Ping.
|
||||
/// </summary>
|
||||
Pong = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Respond to an interaction with a message.
|
||||
/// </summary>
|
||||
ChannelMessageWithSource = 4,
|
||||
|
||||
/// <summary>
|
||||
/// ACK an interaction and edit a response later, the user sees a loading state.
|
||||
/// </summary>
|
||||
DeferredChannelMessageWithSource = 5,
|
||||
|
||||
/// <summary>
|
||||
/// For components: ACK an interaction and edit the original message later; the user does not see a loading state.
|
||||
/// </summary>
|
||||
DeferredUpdateMessage = 6,
|
||||
|
||||
/// <summary>
|
||||
/// For components: edit the message the component was attached to.
|
||||
/// </summary>
|
||||
UpdateMessage = 7,
|
||||
|
||||
/// <summary>
|
||||
/// Respond with a set of choices to a autocomplete interaction.
|
||||
/// </summary>
|
||||
ApplicationCommandAutocompleteResult = 8
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a type of Interaction from discord.
|
||||
/// </summary>
|
||||
public enum InteractionType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// A ping from discord.
|
||||
/// </summary>
|
||||
Ping = 1,
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="IApplicationCommand"/> sent from discord.
|
||||
/// </summary>
|
||||
ApplicationCommand = 2,
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="IMessageComponent"/> sent from discord.
|
||||
/// </summary>
|
||||
MessageComponent = 3,
|
||||
|
||||
/// <summary>
|
||||
/// An autocomplete request sent from discord.
|
||||
/// </summary>
|
||||
ApplicationCommandAutocomplete = 4
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a <see cref="IMessageComponent"/> Row for child components to live in.
|
||||
/// </summary>
|
||||
public class ActionRowComponent : IMessageComponent
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type => ComponentType.ActionRow;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the child components in this row.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<IMessageComponent> Components { get; internal set; }
|
||||
|
||||
internal ActionRowComponent() { }
|
||||
|
||||
internal ActionRowComponent(List<IMessageComponent> components)
|
||||
{
|
||||
Components = components;
|
||||
}
|
||||
|
||||
string IMessageComponent.CustomId => null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a <see cref="IMessageComponent"/> Button.
|
||||
/// </summary>
|
||||
public class ButtonComponent : IMessageComponent
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type => ComponentType.Button;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ButtonStyle"/> of this button, example buttons with each style can be found <see href="https://discord.com/assets/7bb017ce52cfd6575e21c058feb3883b.png">Here</see>.
|
||||
/// </summary>
|
||||
public ButtonStyle Style { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the label of the button, this is the text that is shown.
|
||||
/// </summary>
|
||||
public string Label { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IEmote"/> displayed with this button.
|
||||
/// </summary>
|
||||
public IEmote Emote { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string CustomId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the URL for a <see cref="ButtonStyle.Link"/> button.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// You cannot have a button with a <b>URL</b> and a <b>CustomId</b>.
|
||||
/// </remarks>
|
||||
public string Url { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether this button is disabled or not.
|
||||
/// </summary>
|
||||
public bool IsDisabled { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Turns this button into a button builder.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A newly created button builder with the same properties as this button.
|
||||
/// </returns>
|
||||
public ButtonBuilder ToBuilder()
|
||||
=> new ButtonBuilder(Label, CustomId, Style, Url, Emote, IsDisabled);
|
||||
|
||||
internal ButtonComponent(ButtonStyle style, string label, IEmote emote, string customId, string url, bool isDisabled)
|
||||
{
|
||||
Style = style;
|
||||
Label = label;
|
||||
Emote = emote;
|
||||
CustomId = customId;
|
||||
Url = url;
|
||||
IsDisabled = isDisabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents different styles to use with buttons. You can see an example of the different styles at <see href="https://discord.com/developers/docs/interactions/message-components#buttons-button-styles"/>
|
||||
/// </summary>
|
||||
public enum ButtonStyle
|
||||
{
|
||||
/// <summary>
|
||||
/// A Blurple button
|
||||
/// </summary>
|
||||
Primary = 1,
|
||||
|
||||
/// <summary>
|
||||
/// A Grey (or gray) button
|
||||
/// </summary>
|
||||
Secondary = 2,
|
||||
|
||||
/// <summary>
|
||||
/// A Green button
|
||||
/// </summary>
|
||||
Success = 3,
|
||||
|
||||
/// <summary>
|
||||
/// A Red button
|
||||
/// </summary>
|
||||
Danger = 4,
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="Secondary"/> button with a little popup box indicating that this button is a link.
|
||||
/// </summary>
|
||||
Link = 5
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a type of a component.
|
||||
/// </summary>
|
||||
public enum ComponentType
|
||||
{
|
||||
/// <summary>
|
||||
/// A container for other components.
|
||||
/// </summary>
|
||||
ActionRow = 1,
|
||||
|
||||
/// <summary>
|
||||
/// A clickable button.
|
||||
/// </summary>
|
||||
Button = 2,
|
||||
|
||||
/// <summary>
|
||||
/// A select menu for picking from choices.
|
||||
/// </summary>
|
||||
SelectMenu = 3
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an interaction type for Message Components.
|
||||
/// </summary>
|
||||
public interface IComponentInteraction : IDiscordInteraction
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the data received with this interaction, contains the button that was clicked.
|
||||
/// </summary>
|
||||
new IComponentInteractionData Data { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the message that contained the trigger for this interaction.
|
||||
/// </summary>
|
||||
IUserMessage Message { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the data sent with the <see cref="IComponentInteraction"/>.
|
||||
/// </summary>
|
||||
public interface IComponentInteractionData : IDiscordInteractionData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the components Custom Id that was clicked.
|
||||
/// </summary>
|
||||
string CustomId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the component clicked.
|
||||
/// </summary>
|
||||
ComponentType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value(s) of a <see cref="SelectMenuComponent"/> interaction response.
|
||||
/// </summary>
|
||||
IReadOnlyCollection<string> Values { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a message component on a message.
|
||||
/// </summary>
|
||||
public interface IMessageComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ComponentType"/> of this Message Component.
|
||||
/// </summary>
|
||||
ComponentType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the custom id of the component if possible; otherwise <see langword="null"/>.
|
||||
/// </summary>
|
||||
string CustomId { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a component object used to send components with messages.
|
||||
/// </summary>
|
||||
public class MessageComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the components to be used in a message.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<ActionRowComponent> Components { get; }
|
||||
|
||||
internal MessageComponent(List<ActionRowComponent> components)
|
||||
{
|
||||
Components = components;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a empty <see cref="MessageComponent"/>.
|
||||
/// </summary>
|
||||
internal static MessageComponent Empty
|
||||
=> new MessageComponent(new List<ActionRowComponent>());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a select menu component defined at <see href="https://discord.com/developers/docs/interactions/message-components#select-menu-object"/>
|
||||
/// </summary>
|
||||
public class SelectMenuComponent : IMessageComponent
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type => ComponentType.SelectMenu;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string CustomId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the menus options to select from.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<SelectMenuOption> Options { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the custom placeholder text if nothing is selected.
|
||||
/// </summary>
|
||||
public string Placeholder { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the minimum number of items that must be chosen.
|
||||
/// </summary>
|
||||
public int MinValues { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum number of items that can be chosen.
|
||||
/// </summary>
|
||||
public int MaxValues { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether this menu is disabled or not.
|
||||
/// </summary>
|
||||
public bool IsDisabled { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Turns this select menu into a builder.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A newly create builder with the same properties as this select menu.
|
||||
/// </returns>
|
||||
public SelectMenuBuilder ToBuilder()
|
||||
=> new SelectMenuBuilder(
|
||||
CustomId,
|
||||
Options.Select(x => new SelectMenuOptionBuilder(x.Label, x.Value, x.Description, x.Emote, x.IsDefault)).ToList(),
|
||||
Placeholder,
|
||||
MaxValues,
|
||||
MinValues,
|
||||
IsDisabled);
|
||||
|
||||
internal SelectMenuComponent(string customId, List<SelectMenuOption> options, string placeholder, int minValues, int maxValues, bool disabled)
|
||||
{
|
||||
CustomId = customId;
|
||||
Options = options;
|
||||
Placeholder = placeholder;
|
||||
MinValues = minValues;
|
||||
MaxValues = maxValues;
|
||||
IsDisabled = disabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a choice for a <see cref="SelectMenuComponent"/>.
|
||||
/// </summary>
|
||||
public class SelectMenuOption
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the user-facing name of the option.
|
||||
/// </summary>
|
||||
public string Label { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the dev-define value of the option.
|
||||
/// </summary>
|
||||
public string Value { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a description of the option.
|
||||
/// </summary>
|
||||
public string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IEmote"/> displayed with this menu option.
|
||||
/// </summary>
|
||||
public IEmote Emote { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not this option will render as selected by default.
|
||||
/// </summary>
|
||||
public bool? IsDefault { get; }
|
||||
|
||||
internal SelectMenuOption(string label, string value, string description, IEmote emote, bool? defaultValue)
|
||||
{
|
||||
Label = label;
|
||||
Value = value;
|
||||
Description = description;
|
||||
Emote = emote;
|
||||
IsDefault = defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a <see cref="InteractionType.ApplicationCommandAutocomplete"/>.
|
||||
/// </summary>
|
||||
public interface IAutocompleteInteraction : IDiscordInteraction
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the autocomplete data of this interaction.
|
||||
/// </summary>
|
||||
new IAutocompleteInteractionData Data { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents data for a slash commands autocomplete interaction.
|
||||
/// </summary>
|
||||
public interface IAutocompleteInteractionData : IDiscordInteractionData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name of the invoked command.
|
||||
/// </summary>
|
||||
string CommandName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the id of the invoked command.
|
||||
/// </summary>
|
||||
ulong CommandId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the invoked command.
|
||||
/// </summary>
|
||||
ApplicationCommandType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the version of the invoked command.
|
||||
/// </summary>
|
||||
ulong Version { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current autocomplete option that is actively being filled out.
|
||||
/// </summary>
|
||||
AutocompleteOption Current { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of all the other options the executing users has filled out.
|
||||
/// </summary>
|
||||
IReadOnlyCollection<AutocompleteOption> Options { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a slash command interaction.
|
||||
/// </summary>
|
||||
public interface ISlashCommandInteraction : IDiscordInteraction
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the data associated with this interaction.
|
||||
/// </summary>
|
||||
new IApplicationCommandInteractionData Data { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,640 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a class used to build slash commands.
|
||||
/// </summary>
|
||||
public class SlashCommandBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the maximum length a commands name allowed by Discord
|
||||
/// </summary>
|
||||
public const int MaxNameLength = 32;
|
||||
/// <summary>
|
||||
/// Returns the maximum length of a commands description allowed by Discord.
|
||||
/// </summary>
|
||||
public const int MaxDescriptionLength = 100;
|
||||
/// <summary>
|
||||
/// Returns the maximum count of command options allowed by Discord
|
||||
/// </summary>
|
||||
public const int MaxOptionsCount = 25;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of this slash command.
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set
|
||||
{
|
||||
Preconditions.NotNullOrEmpty(value, nameof(value));
|
||||
Preconditions.AtLeast(value.Length, 1, nameof(value));
|
||||
Preconditions.AtMost(value.Length, MaxNameLength, nameof(value));
|
||||
|
||||
// Discord updated the docs, this regex prevents special characters like @!$%(... etc,
|
||||
// https://discord.com/developers/docs/interactions/slash-commands#applicationcommand
|
||||
if (!Regex.IsMatch(value, @"^[\w-]{1,32}$"))
|
||||
throw new ArgumentException("Command name cannot contain any special characters or whitespaces!", nameof(value));
|
||||
|
||||
_name = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a 1-100 length description of this slash command
|
||||
/// </summary>
|
||||
public string Description
|
||||
{
|
||||
get => _description;
|
||||
set
|
||||
{
|
||||
Preconditions.NotNullOrEmpty(value, nameof(Description));
|
||||
Preconditions.AtLeast(value.Length, 1, nameof(Description));
|
||||
Preconditions.AtMost(value.Length, MaxDescriptionLength, nameof(Description));
|
||||
|
||||
_description = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the options for this command.
|
||||
/// </summary>
|
||||
public List<SlashCommandOptionBuilder> Options
|
||||
{
|
||||
get => _options;
|
||||
set
|
||||
{
|
||||
Preconditions.AtMost(value?.Count ?? 0, MaxOptionsCount, nameof(value));
|
||||
_options = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether the command is enabled by default when the app is added to a guild
|
||||
/// </summary>
|
||||
public bool IsDefaultPermission { get; set; } = true;
|
||||
|
||||
private string _name;
|
||||
private string _description;
|
||||
private List<SlashCommandOptionBuilder> _options;
|
||||
|
||||
/// <summary>
|
||||
/// Build the current builder into a <see cref="SlashCommandProperties"/> class.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="SlashCommandProperties"/> that can be used to create slash commands.</returns>
|
||||
public SlashCommandProperties Build()
|
||||
{
|
||||
var props = new SlashCommandProperties
|
||||
{
|
||||
Name = Name,
|
||||
Description = Description,
|
||||
IsDefaultPermission = IsDefaultPermission,
|
||||
};
|
||||
|
||||
if (Options != null && Options.Any())
|
||||
{
|
||||
var options = new List<ApplicationCommandOptionProperties>();
|
||||
|
||||
Options.OrderByDescending(x => x.IsRequired ?? false).ToList().ForEach(x => options.Add(x.Build()));
|
||||
|
||||
props.Options = options;
|
||||
}
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the field name.
|
||||
/// </summary>
|
||||
/// <param name="name">The value to set the field name to.</param>
|
||||
/// <returns>
|
||||
/// The current builder.
|
||||
/// </returns>
|
||||
public SlashCommandBuilder WithName(string name)
|
||||
{
|
||||
Name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the description of the current command.
|
||||
/// </summary>
|
||||
/// <param name="description">The description of this command.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandBuilder WithDescription(string description)
|
||||
{
|
||||
Description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the default permission of the current command.
|
||||
/// </summary>
|
||||
/// <param name="value">The default permission value to set.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandBuilder WithDefaultPermission(bool value)
|
||||
{
|
||||
IsDefaultPermission = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an option to the current slash command.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the option to add.</param>
|
||||
/// <param name="type">The type of this option.</param>
|
||||
/// <param name="description">The description of this option.</param>
|
||||
/// <param name="isRequired">If this option is required for this command.</param>
|
||||
/// <param name="isDefault">If this option is the default option.</param>
|
||||
/// <param name="isAutocomplete">If this option is set to autocomplete.</param>
|
||||
/// <param name="options">The options of the option to add.</param>
|
||||
/// <param name="channelTypes">The allowed channel types for this option.</param>
|
||||
/// <param name="choices">The choices of this option.</param>
|
||||
/// <param name="minValue">The smallest number value the user can input.</param>
|
||||
/// <param name="maxValue">The largest number value the user can input.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandBuilder AddOption(string name, ApplicationCommandOptionType type,
|
||||
string description, bool? isRequired = null, bool? isDefault = null, bool isAutocomplete = false, double? minValue = null, double? maxValue = null,
|
||||
List<SlashCommandOptionBuilder> options = null, List<ChannelType> channelTypes = null, params ApplicationCommandOptionChoiceProperties[] choices)
|
||||
{
|
||||
// Make sure the name matches the requirements from discord
|
||||
Preconditions.NotNullOrEmpty(name, nameof(name));
|
||||
Preconditions.AtLeast(name.Length, 1, nameof(name));
|
||||
Preconditions.AtMost(name.Length, MaxNameLength, nameof(name));
|
||||
|
||||
// Discord updated the docs, this regex prevents special characters like @!$%( and s p a c e s.. etc,
|
||||
// https://discord.com/developers/docs/interactions/slash-commands#applicationcommand
|
||||
if (!Regex.IsMatch(name, @"^[\w-]{1,32}$"))
|
||||
throw new ArgumentException("Command name cannot contain any special characters or whitespaces!", nameof(name));
|
||||
|
||||
// same with description
|
||||
Preconditions.NotNullOrEmpty(description, nameof(description));
|
||||
Preconditions.AtLeast(description.Length, 1, nameof(description));
|
||||
Preconditions.AtMost(description.Length, MaxDescriptionLength, nameof(description));
|
||||
|
||||
// make sure theres only one option with default set to true
|
||||
if (isDefault == true && Options?.Any(x => x.IsDefault == true) == true)
|
||||
throw new ArgumentException("There can only be one command option with default set to true!", nameof(isDefault));
|
||||
|
||||
var option = new SlashCommandOptionBuilder
|
||||
{
|
||||
Name = name,
|
||||
Description = description,
|
||||
IsRequired = isRequired,
|
||||
IsDefault = isDefault,
|
||||
Options = options,
|
||||
Type = type,
|
||||
IsAutocomplete = isAutocomplete,
|
||||
Choices = (choices ?? Array.Empty<ApplicationCommandOptionChoiceProperties>()).ToList(),
|
||||
ChannelTypes = channelTypes,
|
||||
MinValue = minValue,
|
||||
MaxValue = maxValue,
|
||||
};
|
||||
|
||||
return AddOption(option);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an option to this slash command.
|
||||
/// </summary>
|
||||
/// <param name="option">The option to add.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandBuilder AddOption(SlashCommandOptionBuilder option)
|
||||
{
|
||||
Options ??= new List<SlashCommandOptionBuilder>();
|
||||
|
||||
if (Options.Count >= MaxOptionsCount)
|
||||
throw new InvalidOperationException($"Cannot have more than {MaxOptionsCount} options!");
|
||||
|
||||
Preconditions.NotNull(option, nameof(option));
|
||||
|
||||
Options.Add(option);
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a collection of options to the current slash command.
|
||||
/// </summary>
|
||||
/// <param name="options">The collection of options to add.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandBuilder AddOptions(params SlashCommandOptionBuilder[] options)
|
||||
{
|
||||
if (options == null)
|
||||
throw new ArgumentNullException(nameof(options), "Options cannot be null!");
|
||||
|
||||
if (options.Length == 0)
|
||||
throw new ArgumentException("Options cannot be empty!", nameof(options));
|
||||
|
||||
Options ??= new List<SlashCommandOptionBuilder>();
|
||||
|
||||
if (Options.Count + options.Length > MaxOptionsCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(options), $"Cannot have more than {MaxOptionsCount} options!");
|
||||
|
||||
Options.AddRange(options);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a class used to build options for the <see cref="SlashCommandBuilder"/>.
|
||||
/// </summary>
|
||||
public class SlashCommandOptionBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// The max length of a choice's name allowed by Discord.
|
||||
/// </summary>
|
||||
public const int ChoiceNameMaxLength = 100;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum number of choices allowed by Discord.
|
||||
/// </summary>
|
||||
public const int MaxChoiceCount = 25;
|
||||
|
||||
private string _name;
|
||||
private string _description;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of this option.
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
Preconditions.AtLeast(value.Length, 1, nameof(value));
|
||||
Preconditions.AtMost(value.Length, SlashCommandBuilder.MaxNameLength, nameof(value));
|
||||
if (!Regex.IsMatch(value, @"^[\w-]{1,32}$"))
|
||||
throw new ArgumentException("Option name cannot contain any special characters or whitespaces!", nameof(value));
|
||||
}
|
||||
|
||||
_name = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the description of this option.
|
||||
/// </summary>
|
||||
public string Description
|
||||
{
|
||||
get => _description;
|
||||
set
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
Preconditions.AtLeast(value.Length, 1, nameof(value));
|
||||
Preconditions.AtMost(value.Length, SlashCommandBuilder.MaxDescriptionLength, nameof(value));
|
||||
}
|
||||
|
||||
_description = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of this option.
|
||||
/// </summary>
|
||||
public ApplicationCommandOptionType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether or not this options is the first required option for the user to complete. only one option can be default.
|
||||
/// </summary>
|
||||
public bool? IsDefault { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if the option is required.
|
||||
/// </summary>
|
||||
public bool? IsRequired { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether or not this option supports autocomplete.
|
||||
/// </summary>
|
||||
public bool IsAutocomplete { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the smallest number value the user can input.
|
||||
/// </summary>
|
||||
public double? MinValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the largest number value the user can input.
|
||||
/// </summary>
|
||||
public double? MaxValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the choices for string and int types for the user to pick from.
|
||||
/// </summary>
|
||||
public List<ApplicationCommandOptionChoiceProperties> Choices { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if this option is a subcommand or subcommand group type, these nested options will be the parameters.
|
||||
/// </summary>
|
||||
public List<SlashCommandOptionBuilder> Options { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the allowed channel types for this option.
|
||||
/// </summary>
|
||||
public List<ChannelType> ChannelTypes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Builds the current option.
|
||||
/// </summary>
|
||||
/// <returns>The built version of this option.</returns>
|
||||
public ApplicationCommandOptionProperties Build()
|
||||
{
|
||||
bool isSubType = Type == ApplicationCommandOptionType.SubCommandGroup;
|
||||
bool isIntType = Type == ApplicationCommandOptionType.Integer;
|
||||
|
||||
if (isSubType && (Options == null || !Options.Any()))
|
||||
throw new InvalidOperationException("SubCommands/SubCommandGroups must have at least one option");
|
||||
|
||||
if (!isSubType && Options != null && Options.Any() && Type != ApplicationCommandOptionType.SubCommand)
|
||||
throw new InvalidOperationException($"Cannot have options on {Type} type");
|
||||
|
||||
if (isIntType && MinValue != null && MinValue % 1 != 0)
|
||||
throw new InvalidOperationException("MinValue cannot have decimals on Integer command options.");
|
||||
|
||||
if (isIntType && MaxValue != null && MaxValue % 1 != 0)
|
||||
throw new InvalidOperationException("MaxValue cannot have decimals on Integer command options.");
|
||||
|
||||
return new ApplicationCommandOptionProperties
|
||||
{
|
||||
Name = Name,
|
||||
Description = Description,
|
||||
IsDefault = IsDefault,
|
||||
IsRequired = IsRequired,
|
||||
Type = Type,
|
||||
Options = Options?.Count > 0
|
||||
? Options.OrderByDescending(x => x.IsRequired ?? false).Select(x => x.Build()).ToList()
|
||||
: new List<ApplicationCommandOptionProperties>(),
|
||||
Choices = Choices,
|
||||
IsAutocomplete = IsAutocomplete,
|
||||
ChannelTypes = ChannelTypes,
|
||||
MinValue = MinValue,
|
||||
MaxValue = MaxValue
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an option to the current slash command.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the option to add.</param>
|
||||
/// <param name="type">The type of this option.</param>
|
||||
/// <param name="description">The description of this option.</param>
|
||||
/// <param name="isRequired">If this option is required for this command.</param>
|
||||
/// <param name="isDefault">If this option is the default option.</param>
|
||||
/// <param name="isAutocomplete">If this option supports autocomplete.</param>
|
||||
/// <param name="options">The options of the option to add.</param>
|
||||
/// <param name="channelTypes">The allowed channel types for this option.</param>
|
||||
/// <param name="choices">The choices of this option.</param>
|
||||
/// <param name="minValue">The smallest number value the user can input.</param>
|
||||
/// <param name="maxValue">The largest number value the user can input.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandOptionBuilder AddOption(string name, ApplicationCommandOptionType type,
|
||||
string description, bool? required = null, bool isDefault = false, bool isAutocomplete = false, double? minValue = null, double? maxValue = null,
|
||||
List<SlashCommandOptionBuilder> options = null, List<ChannelType> channelTypes = null, params ApplicationCommandOptionChoiceProperties[] choices)
|
||||
{
|
||||
// Make sure the name matches the requirements from discord
|
||||
Preconditions.NotNullOrEmpty(name, nameof(name));
|
||||
Preconditions.AtLeast(name.Length, 1, nameof(name));
|
||||
Preconditions.AtMost(name.Length, SlashCommandBuilder.MaxNameLength, nameof(name));
|
||||
|
||||
// Discord updated the docs, this regex prevents special characters like @!$%( and s p a c e s.. etc,
|
||||
// https://discord.com/developers/docs/interactions/slash-commands#applicationcommand
|
||||
if (!Regex.IsMatch(name, @"^[\w-]{1,32}$"))
|
||||
throw new ArgumentException("Command name cannot contain any special characters or whitespaces!", nameof(name));
|
||||
|
||||
// same with description
|
||||
Preconditions.NotNullOrEmpty(description, nameof(description));
|
||||
Preconditions.AtLeast(description.Length, 1, nameof(description));
|
||||
Preconditions.AtMost(description.Length, SlashCommandBuilder.MaxDescriptionLength, nameof(description));
|
||||
|
||||
// make sure theres only one option with default set to true
|
||||
if (isDefault && Options?.Any(x => x.IsDefault == true) == true)
|
||||
throw new ArgumentException("There can only be one command option with default set to true!", nameof(isDefault));
|
||||
|
||||
var option = new SlashCommandOptionBuilder
|
||||
{
|
||||
Name = name,
|
||||
Description = description,
|
||||
IsRequired = required,
|
||||
IsDefault = isDefault,
|
||||
IsAutocomplete = isAutocomplete,
|
||||
MinValue = minValue,
|
||||
MaxValue = maxValue,
|
||||
Options = options,
|
||||
Type = type,
|
||||
Choices = (choices ?? Array.Empty<ApplicationCommandOptionChoiceProperties>()).ToList(),
|
||||
ChannelTypes = channelTypes
|
||||
};
|
||||
|
||||
return AddOption(option);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a sub option to the current option.
|
||||
/// </summary>
|
||||
/// <param name="option">The sub option to add.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandOptionBuilder AddOption(SlashCommandOptionBuilder option)
|
||||
{
|
||||
Options ??= new List<SlashCommandOptionBuilder>();
|
||||
|
||||
if (Options.Count >= SlashCommandBuilder.MaxOptionsCount)
|
||||
throw new InvalidOperationException($"There can only be {SlashCommandBuilder.MaxOptionsCount} options per sub command group!");
|
||||
|
||||
Preconditions.NotNull(option, nameof(option));
|
||||
|
||||
Options.Add(option);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a choice to the current option.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the choice.</param>
|
||||
/// <param name="value">The value of the choice.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandOptionBuilder AddChoice(string name, int value)
|
||||
{
|
||||
return AddChoiceInternal(name, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a choice to the current option.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the choice.</param>
|
||||
/// <param name="value">The value of the choice.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandOptionBuilder AddChoice(string name, string value)
|
||||
{
|
||||
return AddChoiceInternal(name, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a choice to the current option.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the choice.</param>
|
||||
/// <param name="value">The value of the choice.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandOptionBuilder AddChoice(string name, double value)
|
||||
{
|
||||
return AddChoiceInternal(name, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a choice to the current option.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the choice.</param>
|
||||
/// <param name="value">The value of the choice.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandOptionBuilder AddChoice(string name, float value)
|
||||
{
|
||||
return AddChoiceInternal(name, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a choice to the current option.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the choice.</param>
|
||||
/// <param name="value">The value of the choice.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandOptionBuilder AddChoice(string name, long value)
|
||||
{
|
||||
return AddChoiceInternal(name, value);
|
||||
}
|
||||
|
||||
private SlashCommandOptionBuilder AddChoiceInternal(string name, object value)
|
||||
{
|
||||
Choices ??= new List<ApplicationCommandOptionChoiceProperties>();
|
||||
|
||||
if (Choices.Count >= MaxChoiceCount)
|
||||
throw new InvalidOperationException($"Cannot add more than {MaxChoiceCount} choices!");
|
||||
|
||||
Preconditions.NotNull(name, nameof(name));
|
||||
Preconditions.NotNull(value, nameof(value));
|
||||
|
||||
Preconditions.AtLeast(name.Length, 1, nameof(name));
|
||||
Preconditions.AtMost(name.Length, 100, nameof(name));
|
||||
|
||||
if(value is string str)
|
||||
{
|
||||
Preconditions.AtLeast(str.Length, 1, nameof(value));
|
||||
Preconditions.AtMost(str.Length, 100, nameof(value));
|
||||
}
|
||||
|
||||
Choices.Add(new ApplicationCommandOptionChoiceProperties
|
||||
{
|
||||
Name = name,
|
||||
Value = value
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a channel type to the current option.
|
||||
/// </summary>
|
||||
/// <param name="channelType">The <see cref="ChannelType"/> to add.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandOptionBuilder AddChannelType(ChannelType channelType)
|
||||
{
|
||||
ChannelTypes ??= new List<ChannelType>();
|
||||
|
||||
ChannelTypes.Add(channelType);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current builders name.
|
||||
/// </summary>
|
||||
/// <param name="name">The name to set the current option builder.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandOptionBuilder WithName(string name)
|
||||
{
|
||||
Name = name;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current builders description.
|
||||
/// </summary>
|
||||
/// <param name="description">The description to set.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandOptionBuilder WithDescription(string description)
|
||||
{
|
||||
Description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current builders required field.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to set.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandOptionBuilder WithRequired(bool value)
|
||||
{
|
||||
IsRequired = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current builders default field.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to set.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandOptionBuilder WithDefault(bool value)
|
||||
{
|
||||
IsDefault = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current builders autocomplete field.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to set.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandOptionBuilder WithAutocomplete(bool value)
|
||||
{
|
||||
IsAutocomplete = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current builders min value field.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to set.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandOptionBuilder WithMinValue(double value)
|
||||
{
|
||||
MinValue = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current builders max value field.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to set.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandOptionBuilder WithMaxValue(double value)
|
||||
{
|
||||
MaxValue = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current type of this builder.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to set.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public SlashCommandOptionBuilder WithType(ApplicationCommandOptionType type)
|
||||
{
|
||||
Type = type;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a class used to create slash commands.
|
||||
/// </summary>
|
||||
public class SlashCommandProperties : ApplicationCommandProperties
|
||||
{
|
||||
internal override ApplicationCommandType Type => ApplicationCommandType.Slash;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the discription of this command.
|
||||
/// </summary>
|
||||
public Optional<string> Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the options for this command.
|
||||
/// </summary>
|
||||
public Optional<List<ApplicationCommandOptionProperties>> Options { get; set; }
|
||||
|
||||
internal SlashCommandProperties() { }
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,10 @@ namespace Discord
|
||||
/// <summary>
|
||||
/// The invite is for a Go Live stream.
|
||||
/// </summary>
|
||||
Stream = 1
|
||||
Stream = 1,
|
||||
/// <summary>
|
||||
/// The invite is for embedded application.
|
||||
/// </summary>
|
||||
EmbeddedApplication = 2
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using Discord.Utils;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
@@ -16,20 +17,20 @@ namespace Discord
|
||||
private EmbedThumbnail? _thumbnail;
|
||||
private List<EmbedFieldBuilder> _fields;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the maximum number of fields allowed by Discord.
|
||||
/// <summary>
|
||||
/// Returns the maximum number of fields allowed by Discord.
|
||||
/// </summary>
|
||||
public const int MaxFieldCount = 25;
|
||||
/// <summary>
|
||||
/// Returns the maximum length of title allowed by Discord.
|
||||
/// <summary>
|
||||
/// Returns the maximum length of title allowed by Discord.
|
||||
/// </summary>
|
||||
public const int MaxTitleLength = 256;
|
||||
/// <summary>
|
||||
/// Returns the maximum length of description allowed by Discord.
|
||||
/// <summary>
|
||||
/// Returns the maximum length of description allowed by Discord.
|
||||
/// </summary>
|
||||
public const int MaxDescriptionLength = 4096;
|
||||
/// <summary>
|
||||
/// Returns the maximum length of total characters allowed by Discord.
|
||||
/// <summary>
|
||||
/// Returns the maximum length of total characters allowed by Discord.
|
||||
/// </summary>
|
||||
public const int MaxEmbedLength = 6000;
|
||||
|
||||
@@ -88,9 +89,9 @@ namespace Discord
|
||||
}
|
||||
|
||||
/// <summary> Gets or sets the list of <see cref="EmbedFieldBuilder"/> of an <see cref="Embed"/>. </summary>
|
||||
/// <exception cref="ArgumentNullException" accessor="set">An embed builder's fields collection is set to
|
||||
/// <exception cref="ArgumentNullException" accessor="set">An embed builder's fields collection is set to
|
||||
/// <c>null</c>.</exception>
|
||||
/// <exception cref="ArgumentException" accessor="set">Description length exceeds <see cref="MaxFieldCount"/>.
|
||||
/// <exception cref="ArgumentException" accessor="set">Fields count exceeds <see cref="MaxFieldCount"/>.
|
||||
/// </exception>
|
||||
/// <returns> The list of existing <see cref="EmbedFieldBuilder"/>.</returns>
|
||||
public List<EmbedFieldBuilder> Fields
|
||||
@@ -137,7 +138,7 @@ namespace Discord
|
||||
/// Gets the total length of all embed properties.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The combined length of <see cref="Title"/>, <see cref="EmbedAuthor.Name"/>, <see cref="Description"/>,
|
||||
/// The combined length of <see cref="Title"/>, <see cref="EmbedAuthor.Name"/>, <see cref="Description"/>,
|
||||
/// <see cref="EmbedFooter.Text"/>, <see cref="EmbedField.Name"/>, and <see cref="EmbedField.Value"/>.
|
||||
/// </returns>
|
||||
public int Length
|
||||
@@ -166,7 +167,7 @@ namespace Discord
|
||||
Title = title;
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Sets the description of an <see cref="Embed"/>.
|
||||
/// </summary>
|
||||
/// <param name="description"> The description to be set. </param>
|
||||
@@ -178,7 +179,7 @@ namespace Discord
|
||||
Description = description;
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Sets the URL of an <see cref="Embed"/>.
|
||||
/// </summary>
|
||||
/// <param name="url"> The URL to be set. </param>
|
||||
@@ -190,7 +191,7 @@ namespace Discord
|
||||
Url = url;
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Sets the thumbnail URL of an <see cref="Embed"/>.
|
||||
/// </summary>
|
||||
/// <param name="thumbnailUrl"> The thumbnail URL to be set. </param>
|
||||
@@ -401,11 +402,29 @@ namespace Discord
|
||||
/// The built embed object.
|
||||
/// </returns>
|
||||
/// <exception cref="InvalidOperationException">Total embed length exceeds <see cref="MaxEmbedLength"/>.</exception>
|
||||
/// <exception cref="InvalidOperationException">Any Url must include its protocols (i.e http:// or https://).</exception>
|
||||
public Embed Build()
|
||||
{
|
||||
if (Length > MaxEmbedLength)
|
||||
throw new InvalidOperationException($"Total embed length must be less than or equal to {MaxEmbedLength}.");
|
||||
|
||||
if (!string.IsNullOrEmpty(Url))
|
||||
UrlValidation.Validate(Url, true);
|
||||
if (!string.IsNullOrEmpty(ThumbnailUrl))
|
||||
UrlValidation.Validate(ThumbnailUrl, true);
|
||||
if (!string.IsNullOrEmpty(ImageUrl))
|
||||
UrlValidation.Validate(ImageUrl, true);
|
||||
if (Author != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Author.Url))
|
||||
UrlValidation.Validate(Author.Url, true);
|
||||
if (!string.IsNullOrEmpty(Author.IconUrl))
|
||||
UrlValidation.Validate(Author.IconUrl, true);
|
||||
}
|
||||
if(Footer != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Footer.IconUrl))
|
||||
UrlValidation.Validate(Footer.IconUrl, true);
|
||||
}
|
||||
var fields = ImmutableArray.CreateBuilder<EmbedField>(Fields.Count);
|
||||
for (int i = 0; i < Fields.Count; i++)
|
||||
fields.Add(Fields[i].Build());
|
||||
|
||||
83
src/Discord.Net.Core/Entities/Messages/FileAttachment.cs
Normal file
83
src/Discord.Net.Core/Entities/Messages/FileAttachment.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
public struct FileAttachment : IDisposable
|
||||
{
|
||||
public string FileName { get; set; }
|
||||
public string Description { get; set; }
|
||||
public bool IsSpoiler { get; set; }
|
||||
|
||||
#pragma warning disable IDISP008
|
||||
public Stream Stream { get; }
|
||||
#pragma warning restore IDISP008
|
||||
|
||||
private bool _isDisposed;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a file attachment from a stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to create the attachment from.</param>
|
||||
/// <param name="fileName">The name of the attachment.</param>
|
||||
/// <param name="description">The description of the attachment.</param>
|
||||
public FileAttachment(Stream stream, string fileName, string description = null, bool isSpoiler = false)
|
||||
{
|
||||
_isDisposed = false;
|
||||
FileName = fileName;
|
||||
Description = description;
|
||||
Stream = stream;
|
||||
IsSpoiler = isSpoiler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the file attachment from a file path.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This file path is NOT validated and is passed directly into a
|
||||
/// <see cref="File.OpenRead"/>.
|
||||
/// </remarks>
|
||||
/// <param name="path">The path to the file.</param>
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// <paramref name="path" /> is a zero-length string, contains only white space, or contains one or more invalid
|
||||
/// characters as defined by <see cref="Path.GetInvalidPathChars"/>.
|
||||
/// </exception>
|
||||
/// <exception cref="System.ArgumentNullException"><paramref name="path" /> is <c>null</c>.</exception>
|
||||
/// <exception cref="PathTooLongException">
|
||||
/// The specified path, file name, or both exceed the system-defined maximum length. For example, on
|
||||
/// Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260
|
||||
/// characters.
|
||||
/// </exception>
|
||||
/// <exception cref="System.NotSupportedException"><paramref name="path" /> is in an invalid format.</exception>
|
||||
/// <exception cref="DirectoryNotFoundException">
|
||||
/// The specified <paramref name="path"/> is invalid, (for example, it is on an unmapped drive).
|
||||
/// </exception>
|
||||
/// <exception cref="System.UnauthorizedAccessException">
|
||||
/// <paramref name="path" /> specified a directory.-or- The caller does not have the required permission.
|
||||
/// </exception>
|
||||
/// <exception cref="FileNotFoundException">The file specified in <paramref name="path" /> was not found.
|
||||
/// </exception>
|
||||
/// <exception cref="IOException">An I/O error occurred while opening the file. </exception>
|
||||
public FileAttachment(string path, string description = null, bool isSpoiler = false)
|
||||
{
|
||||
_isDisposed = false;
|
||||
Stream = File.OpenRead(path);
|
||||
FileName = Path.GetFileName(path);
|
||||
Description = description;
|
||||
IsSpoiler = isSpoiler;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!_isDisposed)
|
||||
{
|
||||
Stream?.Dispose();
|
||||
_isDisposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,5 +55,12 @@ namespace Discord
|
||||
/// The width of this attachment if it is a picture; otherwise <c>null</c>.
|
||||
/// </returns>
|
||||
int? Width { get; }
|
||||
/// <summary>
|
||||
/// Gets whether or not this attachment is ephemeral.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if the attachment is ephemeral; otherwise <see langword="false"/>.
|
||||
/// </returns>
|
||||
bool Ephemeral { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,13 @@ namespace Discord
|
||||
/// </returns>
|
||||
string Content { get; }
|
||||
/// <summary>
|
||||
/// Gets the clean content for this message.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A string that contains the body of the message stripped of mentions, markdown, emojis and pings; note that this field may be empty if there is an embed.
|
||||
/// </returns>
|
||||
string CleanContent { get; }
|
||||
/// <summary>
|
||||
/// Gets the time this message was sent.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
@@ -165,12 +172,17 @@ namespace Discord
|
||||
IReadOnlyDictionary<IEmote, ReactionMetadata> Reactions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets all stickers included in this message.
|
||||
/// The <see cref="IMessageComponent"/>'s attached to this message
|
||||
/// </summary>
|
||||
IReadOnlyCollection<IMessageComponent> Components { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets all stickers items included in this message.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A read-only collection of sticker objects.
|
||||
/// A read-only collection of sticker item objects.
|
||||
/// </returns>
|
||||
IReadOnlyCollection<ISticker> Stickers { get; }
|
||||
IReadOnlyCollection<IStickerItem> Stickers { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the flags related to this message.
|
||||
@@ -183,6 +195,14 @@ namespace Discord
|
||||
/// </returns>
|
||||
MessageFlags? Flags { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the interaction this message is a response to.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="IMessageInteraction"/> if the message is a response to an interaction; otherwise <see langword="null"/>.
|
||||
/// </returns>
|
||||
IMessageInteraction Interaction { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a reaction to this message.
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a partial <see cref="IDiscordInteraction"/> within a message.
|
||||
/// </summary>
|
||||
public interface IMessageInteraction
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the snowflake id of the interaction.
|
||||
/// </summary>
|
||||
ulong Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the interaction.
|
||||
/// </summary>
|
||||
InteractionType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the application command used.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <seealso cref="IUser"/> who invoked the interaction.
|
||||
/// </summary>
|
||||
IUser User { get; }
|
||||
}
|
||||
}
|
||||
@@ -32,5 +32,17 @@ namespace Discord
|
||||
/// Flag given to messages that came from the urgent message system.
|
||||
/// </summary>
|
||||
Urgent = 1 << 4,
|
||||
/// <summary>
|
||||
/// Flag given to messages has an associated thread, with the same id as the message
|
||||
/// </summary>
|
||||
HasThread = 1 << 5,
|
||||
/// <summary>
|
||||
/// Flag given to messages that is only visible to the user who invoked the Interaction.
|
||||
/// </summary>
|
||||
Ephemeral = 1 << 6,
|
||||
/// <summary>
|
||||
/// Flag given to messages that is an Interaction Response and the bot is "thinking"
|
||||
/// </summary>
|
||||
Loading = 1 << 7
|
||||
}
|
||||
}
|
||||
|
||||
45
src/Discord.Net.Core/Entities/Messages/MessageInteraction.cs
Normal file
45
src/Discord.Net.Core/Entities/Messages/MessageInteraction.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a partial <see cref="IDiscordInteraction"/> within a message.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUser">The type of the user.</typeparam>
|
||||
public class MessageInteraction<TUser> : IMessageInteraction where TUser : IUser
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the snowflake id of the interaction.
|
||||
/// </summary>
|
||||
public ulong Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the interaction.
|
||||
/// </summary>
|
||||
public InteractionType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the application command used.
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <typeparamref name="TUser"/> who invoked the interaction.
|
||||
/// </summary>
|
||||
public TUser User { get; }
|
||||
|
||||
internal MessageInteraction(ulong id, InteractionType type, string name, TUser user)
|
||||
{
|
||||
Id = id;
|
||||
Type = type;
|
||||
Name = name;
|
||||
User = user;
|
||||
}
|
||||
|
||||
IUser IMessageInteraction.User => User;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Properties that are used to modify an <see cref="IUserMessage" /> with the specified changes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The content of a message can be cleared with <see cref="System.String.Empty"/> if and only if an
|
||||
/// The content of a message can be cleared with <see cref="System.String.Empty"/> if and only if an
|
||||
/// <see cref="Discord.Embed"/> is present.
|
||||
/// </remarks>
|
||||
/// <seealso cref="IUserMessage.ModifyAsync"/>
|
||||
@@ -17,10 +19,25 @@ namespace Discord
|
||||
/// This must be less than the constant defined by <see cref="DiscordConfig.MaxMessageSize"/>.
|
||||
/// </remarks>
|
||||
public Optional<string> Content { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the embed the message should display.
|
||||
/// Gets or sets a single embed for this message.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This property will be added to the <see cref="Embeds"/> array, in the future please use the array rather than this property.
|
||||
/// </remarks>
|
||||
public Optional<Embed> Embed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the embeds of the message.
|
||||
/// </summary>
|
||||
public Optional<Embed[]> Embeds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the components for this message.
|
||||
/// </summary>
|
||||
public Optional<MessageComponent> Components { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the flags of the message.
|
||||
/// </summary>
|
||||
@@ -33,5 +50,10 @@ namespace Discord
|
||||
/// Gets or sets the allowed mentions of the message.
|
||||
/// </summary>
|
||||
public Optional<AllowedMentions> AllowedMentions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the attachments for the message.
|
||||
/// </summary>
|
||||
public Optional<IEnumerable<FileAttachment>> Attachments { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,8 +58,53 @@ namespace Discord
|
||||
/// </summary>
|
||||
ChannelFollowAdd = 12,
|
||||
/// <summary>
|
||||
/// The message for when a guild is disqualified from discovery.
|
||||
/// </summary>
|
||||
GuildDiscoveryDisqualified = 14,
|
||||
/// <summary>
|
||||
/// The message for when a guild is requalified for discovery.
|
||||
/// </summary>
|
||||
GuildDiscoveryRequalified = 15,
|
||||
/// <summary>
|
||||
/// The message for when the initial warning is sent for the initial grace period discovery.
|
||||
/// </summary>
|
||||
GuildDiscoveryGracePeriodInitialWarning = 16,
|
||||
/// <summary>
|
||||
/// The message for when the final warning is sent for the initial grace period discovery.
|
||||
/// </summary>
|
||||
GuildDiscoveryGracePeriodFinalWarning = 17,
|
||||
/// <summary>
|
||||
/// The message for when a thread is created.
|
||||
/// </summary>
|
||||
ThreadCreated = 18,
|
||||
/// <summary>
|
||||
/// The message is an inline reply.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Only available in API v8.
|
||||
/// </remarks>
|
||||
Reply = 19,
|
||||
/// <summary>
|
||||
/// The message is an Application Command.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Only available in API v8.
|
||||
/// </remarks>
|
||||
ApplicationCommand = 20,
|
||||
/// <summary>
|
||||
/// The message that starts a thread.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Only available in API v9.
|
||||
/// </remarks>
|
||||
ThreadStarterMessage = 21,
|
||||
/// <summary>
|
||||
/// The message for a invite reminder.
|
||||
/// </summary>
|
||||
GuildInviteReminder = 22,
|
||||
/// <summary>
|
||||
/// The message for a context menu command.
|
||||
/// </summary>
|
||||
ContextMenuCommand = 23,
|
||||
}
|
||||
}
|
||||
|
||||
25
src/Discord.Net.Core/Entities/Messages/StickerFormatType.cs
Normal file
25
src/Discord.Net.Core/Entities/Messages/StickerFormatType.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the types of formats for stickers.
|
||||
/// </summary>
|
||||
public enum StickerFormatType
|
||||
{
|
||||
/// <summary>
|
||||
/// Default value for a sticker format type.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
/// <summary>
|
||||
/// The sticker format type is png.
|
||||
/// </summary>
|
||||
Png = 1,
|
||||
/// <summary>
|
||||
/// The sticker format type is apng.
|
||||
/// </summary>
|
||||
Apng = 2,
|
||||
/// <summary>
|
||||
/// The sticker format type is lottie.
|
||||
/// </summary>
|
||||
Lottie = 3
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user