Update from Discord .Net Labs 3.4.8 (#1958)

* 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

* 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 Console.WriteLine

* Rename Available to IsAvailable in stickers

* Rename Default and Required to IsDefault and IsRequired in IApplicationCommandOption. Rename DefaultPermission to IsDefaultPermission in IApplicationCommand

* Fix different rest channels not deserializing properly

* 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

* 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

* 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)

* 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 property names and summaries

* Add Audit Log Data classes for Threads (#301)

* Add ThreadDeleteAuditLogData

* Add ThreadCreateAuditLogData

* Fix ThreadCreateAuditLogData using old instead of new value

* Create ThreadInfo Class

* Fix Thread not being a property

* Add ThreadUpdateAuditLogData

* Cleanup usings

* Add RateLimit to ThreadAuditLogData classese

Co-authored-by: Playwo <eliaswolf2001@t-online.de>

* Fix #300

* Interaction Command Service (#52)

* init

* attribute rename

* added docs

* Revert "added docs"

This reverts commit 30aa0c4ef7e190a726ec2cb3a183da5e2f9b07d9.

* added basic docs

* Switched to nested modules  for method grouping, changed command traversal method

* interface now declares the helper methods

* added new method with predicate parameter

* added config option for deleting the "thinking" state of unhandled commands

* Slash Module Base now exposes helper methods for interacting with the underlying Interaction

* Revert "interface now declares the helper methods"

This reverts commit 541b0be93530e880c482962d41cd6e0cefa4e771.

* IDiscordInteraction now declares the helper methods

* new cancelable wait interaction method

* added support for user created command types

* added option type 'number', added write method to typereaders

* added enum and timespan typereaders

* revert

* added interface method declarations

* inline docs

* revert interface changes

* current user id assignment in sharded client

* added wildcards to interactions, tweaks

* tweaks on interaction wild card pattern

* Pre-app menu

* fixed CurrentUserId and added application command events

* made event listener persistent

* Sharded Client Application Command Events and CurrentUserId Issue (#105)

* added interface method declarations

* inline docs

* current user id assignment in sharded client

* fixed CurrentUserId and added application command events

* made event listener persistent

* removed option type converter, task offloaded to typereaders

* added "deleteOGResponse" method to module base

* Upstream fetch for Discord-Net-Labs/release/3.x

* solved merge conflicts

* removed merge artifacts

* added new Context Command attributes

* added Conxtext Command info classes and changed the naming scheme for the existing classes

* added IgnoreGroupNames prop to command attributes

* added ContextCommand builder

* moved command builders to internal

* added ContextCommand methods to the command service

* command service now uses InteractionHelper to register commands

* bug fixes and refactorings

* docs update

* added inline docs to public members

* added inline docs

* added method name property to command infos

* added inline docs

* changed the execution callback to a declared delegate

* createInstance delegate is now created only once per module

* declared the ExecuteCallback delegate

* introduced a way to modify the command permissions

* changed method names

* added optional compiled lambda module builder

* added the missing sync execution option

* moved run mode selection to the base class

* info class refactorings

* switched to compiled lambda based method invoke

* command refactorings

* added docs

* removed untended class

* bug fixes

* minor refactorings

* reflection changes

* bug fix for interaction parameters

* commands and modules now groups the preconditons on building

* added default permission to context commands

* added DontAutoRegister attribute

* renamed TypeReader to TypeConverter

* added docs to TypeConverterResult, made ISlashModuleBase public

* namespace and project change

* added inline docs file

* renamed ExecuteComponentCommand method

* added scoped service support to the dependency injection model

* fixed premature disposal of scoped services

* extended the scope to cover the precondition checking methods

* removed slash command related preconditions from core lib

* added sample application

* precondition checks are now executed according to the command RunMode

* reverting the conflicting changes

* reverted SocketInteraction

* reverting more conflicts

* added indentations to inline docs

* implemented change requests

* updated the sample app

* moved builders to public

* added indentations to typeconverter docs

* renamed old componentCommandExecuted event

* bug fix for generic typeconverters

* Revert "bug fix for generic typeconverters"

This reverts commit fcc61957deb5dfc17c41367f1c7c72d27024b0ee.

* bug fix for context commands

* code cleanup

* removed public module build method

* modev OnModuleBuilding execution inside the module build method

* added try-catch blocks encapsulating arg generation

* fixed parameter preconditions not raising commandExecuted event

* removed OnModuleBuilding execution from ModuleClassBuilder

* removed setters from Precondition ErrorMessages

* added methods to interaction service for creating user defined modules

* added IParameterInfo parameter to TypeConverter.Write

* changed the target frameworks

* DefaultValueConverter bug fix

* GenerateArgs refactorings

* WaitForMessageComponent now relies message id

* added ChannelTypes support

* added ChannelTypes support

* fix build error for new lib version

* added ToString method to CommandInfo

* added ToString method to CommandInfo

* Fix index out of bounds error for new non-null slash command option collection

* enum converter rework

* added user extendable types to command context and module base

* added regex anchors to ensure pattern matches the whole string

* incomplete guides

* add missing ignoreGroupNames assignment for ComponentInteraction

* typeconverters now seperate pascal casing parameter names

* fix missing IServiceScopefactory ?

* Revert "typeconverters now seperate pascal casing parameter names"

This reverts commit 141300f3d2c244fc6795999d910462939d16a2e1.

* moved the option name pascal casing seperator to RestUtils

* fix component command arg generation

* removed , from default command delimiters

* updated the regex to match every non whitespace value

* added Autocomplete interaction support and updated the regex to match every non whitespace value

* replaced the posix class with range exps in pascal casing seperator

* added inline docs to autocompleter related classes

* added regex metacharacter escape to wildcard patterns

* added null check to Regex EscapeExcluding

* added .net5.0 support and updated the project package

* added .net5.0 support and updated the project package

* add dependency injection to autocompleters

* add net6.0

* bump versions

* bug fix: pascal casing parameters are not assigned

* rework autocomplete commands to accept command and parameter names seperatly

* rename *InteractionCommandContext to *InteractionContext

* add max-min value support to number type slash command options

* add hide attribute to deafult enum converter

* add inline docs

* guides update: min/max value and autocomplete interactions

* remove net6.0 support

* add inline doc to Config.EnableAutocompleters

* add autocompleters guide

* added attribute usage to min/max value

* implement rest based interactions

* add handling logic for rest based interactions

* update default TypeConverters to accommodate rest based interactions

* added interaction specific interfaces

* fix build error

* implement change requests

* bump metapackage version

* replace concrete interface types with interfaces in command execution logic

* fix min/max value attribute target

* add rest specific interaction module for creating interaction responses for rest based interactions within the module

* update rest callback to accept an interaction context parameter

* clean up RestResponseCallback implementation artifacts

* fix command registration bug when using the sharded socket client

* update docs

* fix build errors

* fix slash command depth check

* implement requested changes

* fix build error

* the grand finale

* the grand finale

Co-authored-by: quin lynch <lynchquin@gmail.com>

* Remove XML doc

* Add Interactions service to azure build

* Add DocFX refs to interaction framework docs

* meta: bump docfx version

* meta: bump versions

* Remove versioning metadata in csproj

* Fix user command mismatch in docs

* Fix parameter in message commands

* Fix SocketVoiceChannel options are created as generic mentionables in Interaction service (#308)

* added interaction specific interfaces

* fix build error

* implement change requests

* add autocomplete respond method to IAutocompleteInteraction

* fix sharded client current user

* fix generic typeconverter picking priority

* Revert "fix sharded client current user"

This reverts commit a9c15ffd6ab02651e83e72c275889502b60cfddc.

* Revert "add autocomplete respond method to IAutocompleteInteraction"

This reverts commit f2fc50f1f19a0b41144b6dc93080d2f3a01282fc.

* meta: bump version

* Improve the `GuildFeatures` converter (#311)

* Fix Message/User commands are not being executed when their name have spaces on it  (#310)

* added interaction specific interfaces

* fix build error

* implement change requests

* add autocomplete respond method to IAutocompleteInteraction

* fix sharded client current user

* fix generic typeconverter picking priority

* Revert "fix sharded client current user"

This reverts commit a9c15ffd6ab02651e83e72c275889502b60cfddc.

* Revert "add autocomplete respond method to IAutocompleteInteraction"

This reverts commit f2fc50f1f19a0b41144b6dc93080d2f3a01282fc.

* fix command parsing for names with spaces

* meta: bump version

* fix minor spelling mistake

* add missing $ on docs

Co-Authored-By: Liege72 <65319395+Liege72@users.noreply.github.com>

* Squashed commit of the following:

commit ff0bbbd4d3c4141a6e7eedbe2da0a2cbf5a8a208
Merge: 41b4686b 19a66bf8
Author: quin lynch <lynchquin@gmail.com>
Date:   Sat Nov 27 08:39:35 2021 -0400

    Merge branch 'dev' of https://github.com/discord-net/Discord.Net into dev

commit 19a66bf878
Author: Daniel Baynton <49287178+230Daniel@users.noreply.github.com>
Date:   Fri Nov 26 15:41:55 2021 +0000

    feature: Add method to clear guild user cache (#1767)

    * Add method to clear a SocketGuild's user cache

    * Add optional predicate

    * Compress overload to be consistant

    * Fix global user not clearing (may cause other issues)

    * Remove debug code and add param documentation

    * Standardise doc string

    * Remove old hack-fix

    * Rename new method for consistency

    * Add missing line to reset downloaderPromise

    * Undo accidental whitespace changes

    * Rider better actually keep the tab this time

    Co-authored-by: Quin Lynch <49576606+quinchs@users.noreply.github.com>

commit b9274d115d
Author: Monica S <FiniteReality@users.noreply.github.com>
Date:   Fri Nov 26 15:41:08 2021 +0000

    Add characters commonly use in links to Sanitize (#1152)

    Co-authored-by: Quin Lynch <49576606+quinchs@users.noreply.github.com>

commit 51e06e9ce1
Author: Quin Lynch <49576606+quinchs@users.noreply.github.com>
Date:   Fri Nov 26 11:30:19 2021 -0400

    feature: warn on invalid gateway intents (#1948)

commit 82276e351a
Author: Quin Lynch <49576606+quinchs@users.noreply.github.com>
Date:   Fri Nov 26 11:29:53 2021 -0400

    feature: default application games (#1949)

    * Initial implementation

    * Add missing summary

commit 4f1fe2b084
Merge: 9d6dc627 3cd9f399
Author: quin lynch <lynchquin@gmail.com>
Date:   Fri Nov 26 11:23:32 2021 -0400

    Merge branch 'siscodeorg-commands/validate-get-best-match' into dev

commit 3cd9f39918
Merge: 9d6dc627 adf3a9c4
Author: quin lynch <lynchquin@gmail.com>
Date:   Fri Nov 26 11:23:05 2021 -0400

    Merge branch 'commands/validate-get-best-match' of https://github.com/siscodeorg/Discord.Net into siscodeorg-commands/validate-get-best-match

commit adf3a9c459
Author: roridev <t3ctotalmenterandom1@outlook.com>
Date:   Fri Nov 26 09:26:53 2021 -0300

    Fix incorrect casing on `HandleCommandPipeline`

commit a92ec56d88
Author: roridev <t3ctotalmenterandom1@outlook.com>
Date:   Thu Nov 25 16:42:18 2021 -0300

    Add requested changes

    Changes:
    - Use IResult instead of Optional CommandMatch

    - Rework branching workflow

commit d1b31c8f52
Author: roridev <t3ctotalmenterandom1@outlook.com>
Date:   Thu Nov 25 15:31:48 2021 -0300

    Add `MatchResult`

commit 9d6dc6279d
Author: Quin Lynch <49576606+quinchs@users.noreply.github.com>
Date:   Thu Nov 25 11:25:19 2021 -0400

    Update socket presence and add new presence event (#1945)

commit 10afd96e6e
Author: Quin Lynch <49576606+quinchs@users.noreply.github.com>
Date:   Thu Nov 25 11:24:44 2021 -0400

    feature: Handle bidirectional usernames (#1943)

    * Initial implementation

    * Update summary

commit 143ca6db43
Author: Quin Lynch <49576606+quinchs@users.noreply.github.com>
Date:   Thu Nov 25 11:23:33 2021 -0400

    fix NRE when adding parameters thru builders (#1946)

commit d5f5ae132c
Author: Cenk Ergen <57065323+Cenngo@users.noreply.github.com>
Date:   Thu Nov 25 18:22:50 2021 +0300

    fix sharded client current user (#1947)

commit b5c150dc16
Author: Quin Lynch <49576606+quinchs@users.noreply.github.com>
Date:   Wed Nov 24 12:53:39 2021 -0400

    Add Voice binaries (#1944)

    * Add binaries and read me

    * Update sending voice docs

    * Undo markdown formatting

commit bc440abd44
Author: Quin Lynch <49576606+quinchs@users.noreply.github.com>
Date:   Wed Nov 24 12:52:55 2021 -0400

    Implement multi-file upload to webhooks (#1942)

commit f7a07aec02
Author: Paulo <pnmanjos@hotmail.com>
Date:   Wed Nov 24 09:57:06 2021 -0300

    Add default nullable enum typereader (#1518)

commit 6abdfcbf87
Author: Slate <kristian.f@hotmail.co.uk>
Date:   Wed Nov 24 12:55:07 2021 +0000

    Added negative TimeSpan handling (#1666)

    - Added unit tests for the TimeSpanTypeReader
    - Fixes https://github.com/discord-net/Discord.Net/issues/1657

commit e0dbe7c695
Author: Paulo <pnmanjos@hotmail.com>
Date:   Wed Nov 24 09:43:57 2021 -0300

    Add MaxBitrate to the interface (#1861)

    Co-authored-by: Quin Lynch <49576606+quinchs@users.noreply.github.com>

commit 3cb662ff7a
Author: d4n <dan3436@hotmail.com>
Date:   Tue Nov 23 10:49:31 2021 -0500

    Add null check to AllowedMentions.ToModel() (#1865)

commit 900c1f4385
Author: Quin Lynch <49576606+quinchs@users.noreply.github.com>
Date:   Tue Nov 23 11:46:18 2021 -0400

    Fix emoto try parse (#1941)

commit 933ea42eaa
Author: Quin Lynch <49576606+quinchs@users.noreply.github.com>
Date:   Tue Nov 23 09:58:05 2021 -0400

    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>

commit 3395700720
Author: Nikon <47792796+INikonI@users.noreply.github.com>
Date:   Mon Aug 23 02:00:18 2021 +0500

    feature: IVoiceChannel implements IMentionable (#1896)

commit 41b4686b5e77cd9986006866b9ac7ac418bc05f2
Author: Quin Lynch <49576606+quinchs@users.noreply.github.com>
Date:   Tue Aug 3 20:43:10 2021 -0300

    Update README.md

commit 5fc31451a1fafdc471acfe3a08269d371b20b70b
Author: Quin Lynch <49576606+quinchs@users.noreply.github.com>
Date:   Tue Aug 3 20:28:15 2021 -0300

    Update README.md

commit 56d16397f7
Author: roridev <t3ctotalmenterandom1@outlook.com>
Date:   Fri Nov 27 18:42:23 2020 -0300

    Fixes Azure linux build failing due to a CS8652.

commit c455b50331
Author: roridev <t3ctotalmenterandom1@outlook.com>
Date:   Fri Nov 27 14:10:39 2020 -0300

    Make use of new ValidateAndGetBestMatch api on ExecuteAsync

commit 7955a09090
Author: roridev <t3ctotalmenterandom1@outlook.com>
Date:   Fri Nov 27 13:52:53 2020 -0300

    Creates ValidateAndGetBestMatch function

    This function will validate all commands from a SearchResult and return the result of said validation, along with the command matched, if a valid match was found.

commit 574b503e9e
Author: roridev <t3ctotalmenterandom1@outlook.com>
Date:   Fri Nov 27 13:38:00 2020 -0300

    Moves CalculateScore function to outer scope.

* Update from Discord.Net dev - fix merge conflicts

* meta: .net6 support

* meta: pipelines use .net 6

* meta: bump tests framework versions

* Invoke SlashCommandExecuted event on failed type conversion (#314)

* added interaction specific interfaces

* fix build error

* implement change requests

* add autocomplete respond method to IAutocompleteInteraction

* fix sharded client current user

* fix generic typeconverter picking priority

* Revert "fix sharded client current user"

This reverts commit a9c15ffd6ab02651e83e72c275889502b60cfddc.

* Revert "add autocomplete respond method to IAutocompleteInteraction"

This reverts commit f2fc50f1f19a0b41144b6dc93080d2f3a01282fc.

* fix command parsing for names with spaces

* add SlashCommandExecuted event invoke to failed type conversion

* update interactions sample app

* Revert "update interactions sample app"

This reverts commit 6ac8cd0da60b440874cf29abc7202cdc49fd0538.

* meta: bump to exclusive net.5 and net6 versions

Co-Authored-By: JT <Hawxy@users.noreply.github.com>

* meta: bump versions

* meta: add net461 support back

* Add System.Collections.Immutable back to core

* Fix presence NRE

* meta: bump versions

* Fix presence NRE again...

* meta: bump version

* Fix current user presence

* meta: bump version

* Fix NRE on service providerless command execution (#322)


* fix not set to an instance of an object exception for service providerless command execution

* add methods for manually registering global comands (#325)

* fix dependency injection link in docs (#326)

* Add back netstandard2.0 / 2.1. Closes #324

* meta: bump version

* Add not supported exception on news channels when creating threads, #296

* Revert thread block for news channel. Add check for news channel

Co-Authored-By: Nova Fox <novamaday@gmail.com>

* Make autocomplete log virtual (#328)

* Fix #300 again

* Update GUILD_SCHEDULED_EVENT_CREATE (#330)

Changed _guildScheduledEventCancelled to _guildScheduledEventCreated in GUILD_SCHEDULED_EVENT_CREATE

* correct the number of allowed autocomplete choices (#333)

* correct the number of allowed autocomplete choices (#334)

* Add FollowupWithFileAsync to IDiscordInteraction (#336)

* Add uppercase character check to SlashCommandBuilder and ApplicationCommandOptionProperties (#339)

* Make IModuleBase and IInteractionModuleBase public (#341)

* fix command validation (#335)

* fix autocomplete command traversal and use IList<string> in command map instead of stirng[] (#342)

* Refactor Interactions (#340)

* Refactor Interactions

* Remove ApplicationCommandException

* Fix Module Preconditions (#343)

* fix module preconditions

* fix module preconditions

* meta: bump version

* Update autocomplete docs

* Initial preps

* Fix #347

This comit makes `Content` optional for webhook execution. This comit also adds null checks to content when creating the api args to properly specify the optional struct to the model. This is done so the message entity doesn't try to parse a null string.

* Fix merge errors

* meta: net5 and 6 support

* Update README.md

Co-authored-by: Simon Hjorthøj <sh2@live.dk>
Co-authored-by: MrCakeSlayer <13650699+MrCakeSlayer@users.noreply.github.com>
Co-authored-by: drobbins329 <drobbins329@gmail.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>
Co-authored-by: PoolPirate <94938310+PoolPirate@users.noreply.github.com>
Co-authored-by: Playwo <eliaswolf2001@t-online.de>
Co-authored-by: JT <Hawxy@users.noreply.github.com>
Co-authored-by: Nova Fox <novamaday@gmail.com>
Co-authored-by: Daan van den Hoek <28300783+daanvandenhoek@users.noreply.github.com>
Co-authored-by: nev-r <gh@f-m.fm>
This commit is contained in:
Quin Lynch
2021-12-06 16:02:07 -04:00
committed by GitHub
parent ba656e99b8
commit aa6bb5e293
157 changed files with 9224 additions and 514 deletions

View File

@@ -0,0 +1,76 @@
using System;
namespace Discord.Interactions.Builders
{
/// <summary>
/// Represents a builder for creating <see cref="AutocompleteCommandInfo"/>.
/// </summary>
public sealed class AutocompleteCommandBuilder : CommandBuilder<AutocompleteCommandInfo, AutocompleteCommandBuilder, CommandParameterBuilder>
{
/// <summary>
/// Gets the name of the target parameter.
/// </summary>
public string ParameterName { get; set; }
/// <summary>
/// Gets the name of the target command.
/// </summary>
public string CommandName { get; set; }
protected override AutocompleteCommandBuilder Instance => this;
internal AutocompleteCommandBuilder(ModuleBuilder module) : base(module) { }
/// <summary>
/// Initializes a new <see cref="AutocompleteCommandBuilder"/>.
/// </summary>
/// <param name="module">Parent module of this command.</param>
/// <param name="name">Name of this command.</param>
/// <param name="callback">Execution callback of this command.</param>
public AutocompleteCommandBuilder(ModuleBuilder module, string name, ExecuteCallback callback) : base(module, name, callback) { }
/// <summary>
/// Sets <see cref="ParameterName"/>.
/// </summary>
/// <param name="name">New value of the <see cref="ParameterName"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public AutocompleteCommandBuilder WithParameterName(string name)
{
ParameterName = name;
return this;
}
/// <summary>
/// Sets <see cref="CommandName"/>.
/// </summary>
/// <param name="name">New value of the <see cref="CommandName"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public AutocompleteCommandBuilder WithCommandName(string name)
{
CommandName = name;
return this;
}
/// <summary>
/// Adds a command parameter to the parameters collection.
/// </summary>
/// <param name="configure"><see cref="CommandParameterBuilder"/> factory.</param>
/// <returns>
/// The builder instance.
/// </returns>
public override AutocompleteCommandBuilder AddParameter(Action<CommandParameterBuilder> configure)
{
var parameter = new CommandParameterBuilder(this);
configure(parameter);
AddParameters(parameter);
return this;
}
internal override AutocompleteCommandInfo Build(ModuleInfo module, InteractionService commandService) =>
new AutocompleteCommandInfo(this, module, commandService);
}
}

View File

@@ -0,0 +1,174 @@
using System;
using System.Collections.Generic;
namespace Discord.Interactions.Builders
{
/// <summary>
/// Represents the base builder class for creating <see cref="CommandInfo{TParameter}"/>.
/// </summary>
/// <typeparam name="TInfo">The <see cref="CommandInfo{TParameter}"/> this builder yields when built.</typeparam>
/// <typeparam name="TBuilder">Inherited <see cref="CommandBuilder{TInfo, TBuilder, TParamBuilder}"/> type.</typeparam>
/// <typeparam name="TParamBuilder">Builder type for this commands parameters.</typeparam>
public abstract class CommandBuilder<TInfo, TBuilder, TParamBuilder> : ICommandBuilder
where TInfo : class, ICommandInfo
where TBuilder : CommandBuilder<TInfo, TBuilder, TParamBuilder>
where TParamBuilder : class, IParameterBuilder
{
private readonly List<Attribute> _attributes;
private readonly List<PreconditionAttribute> _preconditions;
private readonly List<TParamBuilder> _parameters;
protected abstract TBuilder Instance { get; }
/// <inheritdoc/>
public ModuleBuilder Module { get; }
//// <inheritdoc/>
public ExecuteCallback Callback { get; internal set; }
/// <inheritdoc/>
public string Name { get; internal set; }
/// <inheritdoc/>
public string MethodName { get; set; }
/// <inheritdoc/>
public bool IgnoreGroupNames { get; set; }
/// <inheritdoc/>
public RunMode RunMode { get; set; }
/// <inheritdoc/>
public IReadOnlyList<Attribute> Attributes => _attributes;
/// <inheritdoc/>
public IReadOnlyList<TParamBuilder> Parameters => _parameters;
/// <inheritdoc/>
public IReadOnlyList<PreconditionAttribute> Preconditions => _preconditions;
/// <inheritdoc/>
IReadOnlyList<IParameterBuilder> ICommandBuilder.Parameters => Parameters;
internal CommandBuilder (ModuleBuilder module)
{
_attributes = new List<Attribute>();
_preconditions = new List<PreconditionAttribute>();
_parameters = new List<TParamBuilder>();
Module = module;
}
protected CommandBuilder (ModuleBuilder module, string name, ExecuteCallback callback) : this(module)
{
Name = name;
Callback = callback;
}
/// <summary>
/// Sets <see cref="Name"/>.
/// </summary>
/// <param name="name">New value of the <see cref="Name"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public TBuilder WithName (string name)
{
Name = name;
return Instance;
}
/// <summary>
/// Sets <see cref="MethodName"/>.
/// </summary>
/// <param name="name">New value of the <see cref="MethodName"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public TBuilder WithMethodName (string name)
{
MethodName = name;
return Instance;
}
/// <summary>
/// Adds attributes to <see cref="Attributes"/>.
/// </summary>
/// <param name="attributes">New attributes to be added to <see cref="Attributes"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public TBuilder WithAttributes (params Attribute[] attributes)
{
_attributes.AddRange(attributes);
return Instance;
}
/// <summary>
/// Sets <see cref="RunMode"/>.
/// </summary>
/// <param name="runMode">New value of the <see cref="RunMode"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public TBuilder SetRunMode (RunMode runMode)
{
RunMode = runMode;
return Instance;
}
/// <summary>
/// Adds parameter builders to <see cref="Parameters"/>.
/// </summary>
/// <param name="parameters">New parameter builders to be added to <see cref="Parameters"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public TBuilder AddParameters (params TParamBuilder[] parameters)
{
_parameters.AddRange(parameters);
return Instance;
}
/// <summary>
/// Adds preconditions to <see cref="Preconditions"/>.
/// </summary>
/// <param name="preconditions">New preconditions to be added to <see cref="Preconditions"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public TBuilder WithPreconditions (params PreconditionAttribute[] preconditions)
{
_preconditions.AddRange(preconditions);
return Instance;
}
/// <inheritdoc/>
public abstract TBuilder AddParameter (Action<TParamBuilder> configure);
internal abstract TInfo Build (ModuleInfo module, InteractionService commandService);
//ICommandBuilder
/// <inheritdoc/>
ICommandBuilder ICommandBuilder.WithName (string name) =>
WithName(name);
/// <inheritdoc/>
ICommandBuilder ICommandBuilder.WithMethodName (string name) =>
WithMethodName(name);
ICommandBuilder ICommandBuilder.WithAttributes (params Attribute[] attributes) =>
WithAttributes(attributes);
/// <inheritdoc/>
ICommandBuilder ICommandBuilder.SetRunMode (RunMode runMode) =>
SetRunMode(runMode);
/// <inheritdoc/>
ICommandBuilder ICommandBuilder.AddParameters (params IParameterBuilder[] parameters) =>
AddParameters(parameters as TParamBuilder);
/// <inheritdoc/>
ICommandBuilder ICommandBuilder.WithPreconditions (params PreconditionAttribute[] preconditions) =>
WithPreconditions(preconditions);
}
}

View File

@@ -0,0 +1,40 @@
using System;
namespace Discord.Interactions.Builders
{
/// <summary>
/// Represents a builder for creating <see cref="ComponentCommandInfo"/>.
/// </summary>
public sealed class ComponentCommandBuilder : CommandBuilder<ComponentCommandInfo, ComponentCommandBuilder, CommandParameterBuilder>
{
protected override ComponentCommandBuilder Instance => this;
internal ComponentCommandBuilder (ModuleBuilder module) : base(module) { }
/// <summary>
/// Initializes a new <see cref="ComponentBuilder"/>.
/// </summary>
/// <param name="module">Parent module of this command.</param>
/// <param name="name">Name of this command.</param>
/// <param name="callback">Execution callback of this command.</param>
public ComponentCommandBuilder (ModuleBuilder module, string name, ExecuteCallback callback) : base(module, name, callback) { }
/// <summary>
/// Adds a command parameter to the parameters collection.
/// </summary>
/// <param name="configure"><see cref="CommandParameterBuilder"/> factory.</param>
/// <returns>
/// The builder instance.
/// </returns>
public override ComponentCommandBuilder AddParameter (Action<CommandParameterBuilder> configure)
{
var parameter = new CommandParameterBuilder(this);
configure(parameter);
AddParameters(parameter);
return this;
}
internal override ComponentCommandInfo Build (ModuleInfo module, InteractionService commandService) =>
new ComponentCommandInfo(this, module, commandService);
}
}

View File

@@ -0,0 +1,76 @@
using System;
namespace Discord.Interactions.Builders
{
/// <summary>
/// Represents a builder for creating <see cref="ContextCommandInfo"/>.
/// </summary>
public sealed class ContextCommandBuilder : CommandBuilder<ContextCommandInfo, ContextCommandBuilder, CommandParameterBuilder>
{
protected override ContextCommandBuilder Instance => this;
/// <summary>
/// Gets the type of this command.
/// </summary>
public ApplicationCommandType CommandType { get; set; }
/// <summary>
/// Gets the default permission of this command.
/// </summary>
public bool DefaultPermission { get; set; } = true;
internal ContextCommandBuilder (ModuleBuilder module) : base(module) { }
/// <summary>
/// Initializes a new <see cref="ContextCommandBuilder"/>.
/// </summary>
/// <param name="module">Parent module of this command.</param>
/// <param name="name">Name of this command.</param>
/// <param name="callback">Execution callback of this command.</param>
public ContextCommandBuilder (ModuleBuilder module, string name, ExecuteCallback callback) : base(module, name, callback) { }
/// <summary>
/// Sets <see cref="CommandType"/>.
/// </summary>
/// <param name="commandType">New value of the <see cref="CommandType"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public ContextCommandBuilder SetType (ApplicationCommandType commandType)
{
CommandType = commandType;
return this;
}
/// <summary>
/// Sets <see cref="DefaultPermission"/>.
/// </summary>
/// <param name="defaultPermision">New value of the <see cref="DefaultPermission"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public ContextCommandBuilder SetDefaultPermission (bool defaultPermision)
{
DefaultPermission = defaultPermision;
return this;
}
/// <summary>
/// Adds a command parameter to the parameters collection.
/// </summary>
/// <param name="configure"><see cref="CommandParameterBuilder"/> factory.</param>
/// <returns>
/// The builder instance.
/// </returns>
public override ContextCommandBuilder AddParameter (Action<CommandParameterBuilder> configure)
{
var parameter = new CommandParameterBuilder(this);
configure(parameter);
AddParameters(parameter);
return this;
}
internal override ContextCommandInfo Build (ModuleInfo module, InteractionService commandService) =>
ContextCommandInfo.Create(this, module, commandService);
}
}

View File

@@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
namespace Discord.Interactions.Builders
{
/// <summary>
/// Represent a command builder for creating <see cref="ICommandInfo"/>.
/// </summary>
public interface ICommandBuilder
{
/// <summary>
/// Gets the execution delegate of this command.
/// </summary>
ExecuteCallback Callback { get; }
/// <summary>
/// Gets the parent module of this command.
/// </summary>
ModuleBuilder Module { get; }
/// <summary>
/// Gets the name of this command.
/// </summary>
string Name { get; }
/// <summary>
/// Gets or sets the method name of this command.
/// </summary>
string MethodName { get; set; }
/// <summary>
/// Gets or sets <see langword="true"/> if this command will be registered and executed as a standalone command, unaffected by the <see cref="GroupAttribute"/>s of
/// of the commands parents.
/// </summary>
bool IgnoreGroupNames { get; set; }
/// <summary>
/// Gets or sets the run mode this command gets executed with.
/// </summary>
RunMode RunMode { get; set; }
/// <summary>
/// Gets a collection of the attributes of this command.
/// </summary>
IReadOnlyList<Attribute> Attributes { get; }
/// <summary>
/// Gets a collection of the parameters of this command.
/// </summary>
IReadOnlyList<IParameterBuilder> Parameters { get; }
/// <summary>
/// Gets a collection of the preconditions of this command.
/// </summary>
IReadOnlyList<PreconditionAttribute> Preconditions { get; }
/// <summary>
/// Sets <see cref="Name"/>.
/// </summary>
/// <param name="name">New value of the <see cref="Name"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
ICommandBuilder WithName (string name);
/// <summary>
/// Sets <see cref="MethodName"/>.
/// </summary>
/// <param name="name">New value of the <see cref="MethodName"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
ICommandBuilder WithMethodName (string name);
/// <summary>
/// Adds attributes to <see cref="Attributes"/>.
/// </summary>
/// <param name="attributes">New attributes to be added to <see cref="Attributes"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
ICommandBuilder WithAttributes (params Attribute[] attributes);
/// <summary>
/// Sets <see cref="RunMode"/>.
/// </summary>
/// <param name="runMode">New value of the <see cref="RunMode"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
ICommandBuilder SetRunMode (RunMode runMode);
/// <summary>
/// Adds parameter builders to <see cref="Parameters"/>.
/// </summary>
/// <param name="parameters">New parameter builders to be added to <see cref="Parameters"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
ICommandBuilder AddParameters (params IParameterBuilder[] parameters);
/// <summary>
/// Adds preconditions to <see cref="Preconditions"/>.
/// </summary>
/// <param name="preconditions">New preconditions to be added to <see cref="Preconditions"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
ICommandBuilder WithPreconditions (params PreconditionAttribute[] preconditions);
}
}

View File

@@ -0,0 +1,76 @@
using System;
namespace Discord.Interactions.Builders
{
/// <summary>
/// Represents a builder for creating <see cref="SlashCommandInfo"/>.
/// </summary>
public sealed class SlashCommandBuilder : CommandBuilder<SlashCommandInfo, SlashCommandBuilder, SlashCommandParameterBuilder>
{
protected override SlashCommandBuilder Instance => this;
/// <summary>
/// Gets and sets the description of this command.
/// </summary>
public string Description { get; set; }
/// <summary>
/// Gets and sets the default permission of this command.
/// </summary>
public bool DefaultPermission { get; set; } = true;
internal SlashCommandBuilder (ModuleBuilder module) : base(module) { }
/// <summary>
/// Initializes a new <see cref="SlashCommandBuilder"/>.
/// </summary>
/// <param name="module">Parent module of this command.</param>
/// <param name="name">Name of this command.</param>
/// <param name="callback">Execution callback of this command.</param>
public SlashCommandBuilder (ModuleBuilder module, string name, ExecuteCallback callback) : base(module, name, callback) { }
/// <summary>
/// Sets <see cref="Description"/>.
/// </summary>
/// <param name="description">New value of the <see cref="Description"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public SlashCommandBuilder WithDescription (string description)
{
Description = description;
return this;
}
/// <summary>
/// Sets <see cref="DefaultPermission"/>.
/// </summary>
/// <param name="defaultPermision">New value of the <see cref="DefaultPermission"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public SlashCommandBuilder WithDefaultPermission (bool permission)
{
DefaultPermission = permission;
return Instance;
}
/// <summary>
/// Adds a command parameter to the parameters collection.
/// </summary>
/// <param name="configure"><see cref="SlashCommandParameterBuilder"/> factory.</param>
/// <returns>
/// The builder instance.
/// </returns>
public override SlashCommandBuilder AddParameter (Action<SlashCommandParameterBuilder> configure)
{
var parameter = new SlashCommandParameterBuilder(this);
configure(parameter);
AddParameters(parameter);
return this;
}
internal override SlashCommandInfo Build (ModuleInfo module, InteractionService commandService) =>
new SlashCommandInfo(this, module, commandService);
}
}

View File

@@ -0,0 +1,279 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Discord.Interactions.Builders
{
/// <summary>
/// Represents a builder for creating <see cref="ModuleInfo"/>.
/// </summary>
public class ModuleBuilder
{
private readonly List<Attribute> _attributes;
private readonly List<PreconditionAttribute> _preconditions;
private readonly List<ModuleBuilder> _subModules;
private readonly List<SlashCommandBuilder> _slashCommands;
private readonly List<ContextCommandBuilder> _contextCommands;
private readonly List<ComponentCommandBuilder> _componentCommands;
private readonly List<AutocompleteCommandBuilder> _autocompleteCommands;
/// <summary>
/// Gets the underlying Interaction Service.
/// </summary>
public InteractionService InteractionService { get; }
/// <summary>
/// Gets the parent module if this module is a sub-module.
/// </summary>
public ModuleBuilder Parent { get; }
/// <summary>
/// Gets the name of this module.
/// </summary>
public string Name { get; internal set; }
/// <summary>
/// Gets and sets the group name of this module.
/// </summary>
public string SlashGroupName { get; set; }
/// <summary>
/// Gets whether this has a <see cref="GroupAttribute"/>.
/// </summary>
public bool IsSlashGroup => !string.IsNullOrEmpty(SlashGroupName);
/// <summary>
/// Gets and sets the description of this module.
/// </summary>
public string Description { get; set; }
/// <summary>
/// Gets and sets the default permission of this module.
/// </summary>
public bool DefaultPermission { get; set; } = true;
/// <summary>
/// Gets and sets whether this has a <see cref="DontAutoRegisterAttribute"/>.
/// </summary>
public bool DontAutoRegister { get; set; } = false;
/// <summary>
/// Gets a collection of the attributes of this module.
/// </summary>
public IReadOnlyList<Attribute> Attributes => _attributes;
/// <summary>
/// Gets a collection of the preconditions of this module.
/// </summary>
public IReadOnlyCollection<PreconditionAttribute> Preconditions => _preconditions;
/// <summary>
/// Gets a collection of the sub-modules of this module.
/// </summary>
public IReadOnlyList<ModuleBuilder> SubModules => _subModules;
/// <summary>
/// Gets a collection of the Slash Commands of this module.
/// </summary>
public IReadOnlyList<SlashCommandBuilder> SlashCommands => _slashCommands;
/// <summary>
/// Gets a collection of the Context Commands of this module.
/// </summary>
public IReadOnlyList<ContextCommandBuilder> ContextCommands => _contextCommands;
/// <summary>
/// Gets a collection of the Component Commands of this module.
/// </summary>
public IReadOnlyList<ComponentCommandBuilder> ComponentCommands => _componentCommands;
/// <summary>
/// Gets a collection of the Autocomplete Commands of this module.
/// </summary>
public IReadOnlyList<AutocompleteCommandBuilder> AutocompleteCommands => _autocompleteCommands;
internal TypeInfo TypeInfo { get; set; }
internal ModuleBuilder (InteractionService interactionService, ModuleBuilder parent = null)
{
InteractionService = interactionService;
Parent = parent;
_attributes = new List<Attribute>();
_subModules = new List<ModuleBuilder>();
_slashCommands = new List<SlashCommandBuilder>();
_contextCommands = new List<ContextCommandBuilder>();
_componentCommands = new List<ComponentCommandBuilder>();
_autocompleteCommands = new List<AutocompleteCommandBuilder>();
_preconditions = new List<PreconditionAttribute>();
}
/// <summary>
/// Initializes a new <see cref="ModuleBuilder"/>.
/// </summary>
/// <param name="interactionService">The underlying Interaction Service.</param>
/// <param name="name">Name of this module.</param>
/// <param name="parent">Parent module of this sub-module.</param>
public ModuleBuilder (InteractionService interactionService, string name, ModuleBuilder parent = null) : this(interactionService, parent)
{
Name = name;
}
/// <summary>
/// Sets <see cref="SlashGroupName"/>.
/// </summary>
/// <param name="name">New value of the <see cref="SlashGroupName"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public ModuleBuilder WithGroupName (string name)
{
SlashGroupName = name;
return this;
}
/// <summary>
/// Sets <see cref="Description"/>.
/// </summary>
/// <param name="description">New value of the <see cref="Description"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public ModuleBuilder WithDescription (string description)
{
Description = description;
return this;
}
/// <summary>
/// Sets <see cref="DefaultPermission"/>.
/// </summary>
/// <param name="permission">New value of the <see cref="DefaultPermission"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public ModuleBuilder WithDefaultPermision (bool permission)
{
DefaultPermission = permission;
return this;
}
/// <summary>
/// Adds attributes to <see cref="Attributes"/>
/// </summary>
/// <param name="attributes">New attributes to be added to <see cref="Attributes"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public ModuleBuilder AddAttributes (params Attribute[] attributes)
{
_attributes.AddRange(attributes);
return this;
}
/// <summary>
/// Adds preconditions to <see cref="Preconditions"/>
/// </summary>
/// <param name="preconditions">New preconditions to be added to <see cref="Preconditions"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public ModuleBuilder AddPreconditions (params PreconditionAttribute[] preconditions)
{
_preconditions.AddRange(preconditions);
return this;
}
/// <summary>
/// Adds slash command builder to <see cref="SlashCommands"/>
/// </summary>
/// <param name="configure"><see cref="SlashCommandBuilder"/> factory.</param>
/// <returns>
/// The builder instance.
/// </returns>
public ModuleBuilder AddSlashCommand (Action<SlashCommandBuilder> configure)
{
var command = new SlashCommandBuilder(this);
configure(command);
_slashCommands.Add(command);
return this;
}
/// <summary>
/// Adds context command builder to <see cref="ContextCommands"/>
/// </summary>
/// <param name="configure"><see cref="ContextCommandBuilder"/> factory.</param>
/// <returns>
/// The builder instance.
/// </returns>
public ModuleBuilder AddContextCommand (Action<ContextCommandBuilder> configure)
{
var command = new ContextCommandBuilder(this);
configure(command);
_contextCommands.Add(command);
return this;
}
/// <summary>
/// Adds component command builder to <see cref="ComponentCommands"/>
/// </summary>
/// <param name="configure"><see cref="ComponentCommandBuilder"/> factory.</param>
/// <returns>
/// The builder instance.
/// </returns>
public ModuleBuilder AddComponentCommand (Action<ComponentCommandBuilder> configure)
{
var command = new ComponentCommandBuilder(this);
configure(command);
_componentCommands.Add(command);
return this;
}
/// <summary>
/// Adds autocomplete command builder to <see cref="AutocompleteCommands"/>
/// </summary>
/// <param name="configure"><see cref="AutocompleteCommands"/> factory.</param>
/// <returns>
/// The builder instance.
/// </returns>
public ModuleBuilder AddAutocompleteCommand(Action<AutocompleteCommandBuilder> configure)
{
var command = new AutocompleteCommandBuilder(this);
configure(command);
_autocompleteCommands.Add(command);
return this;
}
/// <summary>
/// Adds sub-module builder to <see cref="SubModules"/>
/// </summary>
/// <param name="configure"><see cref="ModuleBuilder"/> factory.</param>
/// <returns>
/// The builder instance.
/// </returns>
public ModuleBuilder AddModule (Action<ModuleBuilder> configure)
{
var subModule = new ModuleBuilder(InteractionService, this);
configure(subModule);
_subModules.Add(subModule);
return this;
}
internal ModuleInfo Build (InteractionService interactionService, IServiceProvider services, ModuleInfo parent = null)
{
var moduleInfo = new ModuleInfo(this, interactionService, services, parent);
IInteractionModuleBase instance = ReflectionUtils<IInteractionModuleBase>.CreateObject(TypeInfo, interactionService, services);
try
{
instance.OnModuleBuilding(interactionService, moduleInfo);
}
finally
{
( instance as IDisposable )?.Dispose();
}
return moduleInfo;
}
}
}

View File

@@ -0,0 +1,469 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Discord.Interactions.Builders
{
internal static class ModuleClassBuilder
{
private static readonly TypeInfo ModuleTypeInfo = typeof(IInteractionModuleBase).GetTypeInfo();
public const int MaxCommandDepth = 3;
public static async Task<IEnumerable<TypeInfo>> SearchAsync (Assembly assembly, InteractionService commandService)
{
static bool IsLoadableModule (TypeInfo info)
{
return info.DeclaredMethods.Any(x => x.GetCustomAttribute<SlashCommandAttribute>() != null);
}
var result = new List<TypeInfo>();
foreach (var type in assembly.DefinedTypes)
{
if (( type.IsPublic || type.IsNestedPublic ) && IsValidModuleDefinition(type))
{
result.Add(type);
}
else if (IsLoadableModule(type))
{
await commandService._cmdLogger.WarningAsync($"Class {type.FullName} is not public and cannot be loaded.").ConfigureAwait(false);
}
}
return result;
}
public static async Task<Dictionary<Type, ModuleInfo>> BuildAsync (IEnumerable<TypeInfo> validTypes, InteractionService commandService,
IServiceProvider services)
{
var topLevelGroups = validTypes.Where(x => x.DeclaringType == null || !IsValidModuleDefinition(x.DeclaringType.GetTypeInfo()));
var built = new List<TypeInfo>();
var result = new Dictionary<Type, ModuleInfo>();
foreach (var type in topLevelGroups)
{
var builder = new ModuleBuilder(commandService);
BuildModule(builder, type, commandService, services);
BuildSubModules(builder, type.DeclaredNestedTypes, built, commandService, services);
built.Add(type);
var moduleInfo = builder.Build(commandService, services);
result.Add(type.AsType(), moduleInfo);
}
await commandService._cmdLogger.DebugAsync($"Successfully built {built.Count} Slash Command modules.").ConfigureAwait(false);
return result;
}
private static void BuildModule (ModuleBuilder builder, TypeInfo typeInfo, InteractionService commandService,
IServiceProvider services)
{
var attributes = typeInfo.GetCustomAttributes();
builder.Name = typeInfo.Name;
builder.TypeInfo = typeInfo;
foreach (var attribute in attributes)
{
switch (attribute)
{
case GroupAttribute group:
{
builder.SlashGroupName = group.Name;
builder.Description = group.Description;
}
break;
case DefaultPermissionAttribute defPermission:
{
builder.DefaultPermission = defPermission.IsDefaultPermission;
}
break;
case PreconditionAttribute precondition:
builder.AddPreconditions(precondition);
break;
case DontAutoRegisterAttribute dontAutoRegister:
builder.DontAutoRegister = true;
break;
default:
builder.AddAttributes(attribute);
break;
}
}
var methods = typeInfo.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
var validSlashCommands = methods.Where(IsValidSlashCommandDefinition);
var validContextCommands = methods.Where(IsValidContextCommandDefinition);
var validInteractions = methods.Where(IsValidComponentCommandDefinition);
var validAutocompleteCommands = methods.Where(IsValidAutocompleteCommandDefinition);
Func<IServiceProvider, IInteractionModuleBase> createInstance = commandService._useCompiledLambda ?
ReflectionUtils<IInteractionModuleBase>.CreateLambdaBuilder(typeInfo, commandService) : ReflectionUtils<IInteractionModuleBase>.CreateBuilder(typeInfo, commandService);
foreach (var method in validSlashCommands)
builder.AddSlashCommand(x => BuildSlashCommand(x, createInstance, method, commandService, services));
foreach (var method in validContextCommands)
builder.AddContextCommand(x => BuildContextCommand(x, createInstance, method, commandService, services));
foreach (var method in validInteractions)
builder.AddComponentCommand(x => BuildComponentCommand(x, createInstance, method, commandService, services));
foreach(var method in validAutocompleteCommands)
builder.AddAutocompleteCommand(x => BuildAutocompleteCommand(x, createInstance, method, commandService, services));
}
private static void BuildSubModules (ModuleBuilder parent, IEnumerable<TypeInfo> subModules, IList<TypeInfo> builtTypes, InteractionService commandService,
IServiceProvider services, int slashGroupDepth = 0)
{
foreach (var submodule in subModules.Where(IsValidModuleDefinition))
{
if (builtTypes.Contains(submodule))
continue;
parent.AddModule((builder) =>
{
BuildModule(builder, submodule, commandService, services);
if (slashGroupDepth >= MaxCommandDepth - 1)
throw new InvalidOperationException($"Slash Commands only support {MaxCommandDepth - 1} command prefixes for sub-commands");
BuildSubModules(builder, submodule.DeclaredNestedTypes, builtTypes, commandService, services, builder.IsSlashGroup ? slashGroupDepth + 1 : slashGroupDepth);
});
builtTypes.Add(submodule);
}
}
private static void BuildSlashCommand (SlashCommandBuilder builder, Func<IServiceProvider, IInteractionModuleBase> createInstance, MethodInfo methodInfo,
InteractionService commandService, IServiceProvider services)
{
var attributes = methodInfo.GetCustomAttributes();
builder.MethodName = methodInfo.Name;
foreach (var attribute in attributes)
{
switch (attribute)
{
case SlashCommandAttribute command:
{
builder.Name = command.Name;
builder.Description = command.Description;
builder.IgnoreGroupNames = command.IgnoreGroupNames;
builder.RunMode = command.RunMode;
}
break;
case DefaultPermissionAttribute defaultPermission:
{
builder.DefaultPermission = defaultPermission.IsDefaultPermission;
}
break;
case PreconditionAttribute precondition:
builder.WithPreconditions(precondition);
break;
default:
builder.WithAttributes(attribute);
break;
}
}
var parameters = methodInfo.GetParameters();
foreach (var parameter in parameters)
builder.AddParameter(x => BuildSlashParameter(x, parameter, services));
builder.Callback = CreateCallback(createInstance, methodInfo, commandService);
}
private static void BuildContextCommand (ContextCommandBuilder builder, Func<IServiceProvider, IInteractionModuleBase> createInstance, MethodInfo methodInfo,
InteractionService commandService, IServiceProvider services)
{
var attributes = methodInfo.GetCustomAttributes();
builder.MethodName = methodInfo.Name;
foreach (var attribute in attributes)
{
switch (attribute)
{
case ContextCommandAttribute command:
{
builder.Name = command.Name;
builder.CommandType = command.CommandType;
builder.RunMode = command.RunMode;
command.CheckMethodDefinition(methodInfo);
}
break;
case DefaultPermissionAttribute defaultPermission:
{
builder.DefaultPermission = defaultPermission.IsDefaultPermission;
}
break;
case PreconditionAttribute precondition:
builder.WithPreconditions(precondition);
break;
default:
builder.WithAttributes(attribute);
break;
}
}
var parameters = methodInfo.GetParameters();
foreach (var parameter in parameters)
builder.AddParameter(x => BuildParameter(x, parameter));
builder.Callback = CreateCallback(createInstance, methodInfo, commandService);
}
private static void BuildComponentCommand (ComponentCommandBuilder builder, Func<IServiceProvider, IInteractionModuleBase> createInstance, MethodInfo methodInfo,
InteractionService commandService, IServiceProvider services)
{
if (!methodInfo.GetParameters().All(x => x.ParameterType == typeof(string) || x.ParameterType == typeof(string[])))
throw new InvalidOperationException($"Interaction method parameters all must be types of {typeof(string).Name} or {typeof(string[]).Name}");
var attributes = methodInfo.GetCustomAttributes();
builder.MethodName = methodInfo.Name;
foreach (var attribute in attributes)
{
switch (attribute)
{
case ComponentInteractionAttribute interaction:
{
builder.Name = interaction.CustomId;
builder.RunMode = interaction.RunMode;
builder.IgnoreGroupNames = interaction.IgnoreGroupNames;
}
break;
case PreconditionAttribute precondition:
builder.WithPreconditions(precondition);
break;
default:
builder.WithAttributes(attribute);
break;
}
}
var parameters = methodInfo.GetParameters();
foreach (var parameter in parameters)
builder.AddParameter(x => BuildParameter(x, parameter));
builder.Callback = CreateCallback(createInstance, methodInfo, commandService);
}
private static void BuildAutocompleteCommand(AutocompleteCommandBuilder builder, Func<IServiceProvider, IInteractionModuleBase> createInstance, MethodInfo methodInfo,
InteractionService commandService, IServiceProvider services)
{
var attributes = methodInfo.GetCustomAttributes();
builder.MethodName = methodInfo.Name;
foreach(var attribute in attributes)
{
switch (attribute)
{
case AutocompleteCommandAttribute autocomplete:
{
builder.ParameterName = autocomplete.ParameterName;
builder.CommandName = autocomplete.CommandName;
builder.Name = autocomplete.CommandName + " " + autocomplete.ParameterName;
builder.RunMode = autocomplete.RunMode;
}
break;
case PreconditionAttribute precondition:
builder.WithPreconditions(precondition);
break;
default:
builder.WithAttributes(attribute);
break;
}
}
var parameters = methodInfo.GetParameters();
foreach (var parameter in parameters)
builder.AddParameter(x => BuildParameter(x, parameter));
builder.Callback = CreateCallback(createInstance, methodInfo, commandService);
}
private static ExecuteCallback CreateCallback (Func<IServiceProvider, IInteractionModuleBase> createInstance,
MethodInfo methodInfo, InteractionService commandService)
{
Func<IInteractionModuleBase, object[], Task> commandInvoker = commandService._useCompiledLambda ?
ReflectionUtils<IInteractionModuleBase>.CreateMethodInvoker(methodInfo) : (module, args) => methodInfo.Invoke(module, args) as Task;
async Task<IResult> ExecuteCallback (IInteractionContext context, object[] args, IServiceProvider serviceProvider, ICommandInfo commandInfo)
{
var instance = createInstance(serviceProvider);
instance.SetContext(context);
try
{
instance.BeforeExecute(commandInfo);
var task = commandInvoker(instance, args) ?? Task.Delay(0);
if (task is Task<RuntimeResult> runtimeTask)
{
return await runtimeTask.ConfigureAwait(false);
}
else
{
await task.ConfigureAwait(false);
return ExecuteResult.FromSuccess();
}
}
catch (Exception ex)
{
await commandService._cmdLogger.ErrorAsync(ex).ConfigureAwait(false);
return ExecuteResult.FromError(ex);
}
finally
{
instance.AfterExecute(commandInfo);
( instance as IDisposable )?.Dispose();
}
}
return ExecuteCallback;
}
#region Parameters
private static void BuildSlashParameter (SlashCommandParameterBuilder builder, ParameterInfo paramInfo, IServiceProvider services)
{
var attributes = paramInfo.GetCustomAttributes();
var paramType = paramInfo.ParameterType;
builder.Name = paramInfo.Name;
builder.Description = paramInfo.Name;
builder.IsRequired = !paramInfo.IsOptional;
builder.DefaultValue = paramInfo.DefaultValue;
builder.SetParameterType(paramType, services);
foreach (var attribute in attributes)
{
switch (attribute)
{
case SummaryAttribute description:
{
if (!string.IsNullOrEmpty(description.Name))
builder.Name = description.Name;
if (!string.IsNullOrEmpty(description.Description))
builder.Description = description.Description;
}
break;
case ChoiceAttribute choice:
builder.WithChoices(new ParameterChoice(choice.Name, choice.Value));
break;
case ParamArrayAttribute _:
builder.IsParameterArray = true;
break;
case ParameterPreconditionAttribute precondition:
builder.AddPreconditions(precondition);
break;
case ChannelTypesAttribute channelTypes:
builder.WithChannelTypes(channelTypes.ChannelTypes);
break;
case AutocompleteAttribute autocomplete:
builder.Autocomplete = true;
if(autocomplete.AutocompleteHandlerType is not null)
builder.WithAutocompleteHandler(autocomplete.AutocompleteHandlerType, services);
break;
case MaxValueAttribute maxValue:
builder.MaxValue = maxValue.Value;
break;
case MinValueAttribute minValue:
builder.MinValue = minValue.Value;
break;
default:
builder.AddAttributes(attribute);
break;
}
}
// Replace pascal casings with '-'
builder.Name = Regex.Replace(builder.Name, "(?<=[a-z])(?=[A-Z])", "-").ToLower();
}
private static void BuildParameter (CommandParameterBuilder builder, ParameterInfo paramInfo)
{
var attributes = paramInfo.GetCustomAttributes();
var paramType = paramInfo.ParameterType;
builder.Name = paramInfo.Name;
builder.IsRequired = !paramInfo.IsOptional;
builder.DefaultValue = paramInfo.DefaultValue;
builder.SetParameterType(paramType);
foreach (var attribute in attributes)
{
switch (attribute)
{
case ParameterPreconditionAttribute precondition:
builder.AddPreconditions(precondition);
break;
case ParamArrayAttribute _:
builder.IsParameterArray = true;
break;
default:
builder.AddAttributes(attribute);
break;
}
}
}
#endregion
internal static bool IsValidModuleDefinition (TypeInfo typeInfo)
{
return ModuleTypeInfo.IsAssignableFrom(typeInfo) &&
!typeInfo.IsAbstract &&
!typeInfo.ContainsGenericParameters;
}
private static bool IsValidSlashCommandDefinition (MethodInfo methodInfo)
{
return methodInfo.IsDefined(typeof(SlashCommandAttribute)) &&
( methodInfo.ReturnType == typeof(Task) || methodInfo.ReturnType == typeof(Task<RuntimeResult>) ) &&
!methodInfo.IsStatic &&
!methodInfo.IsGenericMethod;
}
private static bool IsValidContextCommandDefinition (MethodInfo methodInfo)
{
return methodInfo.IsDefined(typeof(ContextCommandAttribute)) &&
( methodInfo.ReturnType == typeof(Task) || methodInfo.ReturnType == typeof(Task<RuntimeResult>) ) &&
!methodInfo.IsStatic &&
!methodInfo.IsGenericMethod;
}
private static bool IsValidComponentCommandDefinition (MethodInfo methodInfo)
{
return methodInfo.IsDefined(typeof(ComponentInteractionAttribute)) &&
(methodInfo.ReturnType == typeof(Task) || methodInfo.ReturnType == typeof(Task<RuntimeResult>)) &&
!methodInfo.IsStatic &&
!methodInfo.IsGenericMethod;
}
private static bool IsValidAutocompleteCommandDefinition (MethodInfo methodInfo)
{
return methodInfo.IsDefined(typeof(AutocompleteCommandAttribute)) &&
(methodInfo.ReturnType == typeof(Task) || methodInfo.ReturnType == typeof(Task<RuntimeResult>)) &&
!methodInfo.IsStatic &&
!methodInfo.IsGenericMethod &&
methodInfo.GetParameters().Length == 0;
}
}
}

View File

@@ -0,0 +1,25 @@
using System;
namespace Discord.Interactions.Builders
{
/// <summary>
/// Represents a builder for creating <see cref="CommandParameterInfo"/>.
/// </summary>
public sealed class CommandParameterBuilder : ParameterBuilder<CommandParameterInfo, CommandParameterBuilder>
{
protected override CommandParameterBuilder Instance => this;
internal CommandParameterBuilder (ICommandBuilder command) : base(command) { }
/// <summary>
/// Initializes a new <see cref="CommandParameterInfo"/>.
/// </summary>
/// <param name="command">Parent command of this parameter.</param>
/// <param name="name">Name of this command.</param>
/// <param name="type">Type of this parameter.</param>
public CommandParameterBuilder (ICommandBuilder command, string name, Type type) : base(command, name, type) { }
internal override CommandParameterInfo Build (ICommandInfo command) =>
new CommandParameterInfo(this, command);
}
}

View File

@@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
namespace Discord.Interactions.Builders
{
/// <summary>
/// Represent a command builder for creating <see cref="IParameterInfo"/>.
/// </summary>
public interface IParameterBuilder
{
/// <summary>
/// Gets the parent command of this parameter.
/// </summary>
ICommandBuilder Command { get; }
/// <summary>
/// Gets the name of this parameter.
/// </summary>
string Name { get; }
/// <summary>
/// Gets the type of this parameter.
/// </summary>
Type ParameterType { get; }
/// <summary>
/// Gets whether this parameter is required.
/// </summary>
bool IsRequired { get; }
/// <summary>
/// Gets whether this parameter is <see langword="params"/>.
/// </summary>
bool IsParameterArray { get; }
/// <summary>
/// Gets the deafult value of this parameter.
/// </summary>
object DefaultValue { get; }
/// <summary>
/// Gets a collection of the attributes of this command.
/// </summary>
IReadOnlyCollection<Attribute> Attributes { get; }
/// <summary>
/// Gets a collection of the preconditions of this command.
/// </summary>
IReadOnlyCollection<ParameterPreconditionAttribute> Preconditions { get; }
/// <summary>
/// Sets <see cref="Name"/>.
/// </summary>
/// <param name="name">New value of the <see cref="Name"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
IParameterBuilder WithName (string name);
/// <summary>
/// Sets <see cref="ParameterType"/>.
/// </summary>
/// <param name="type">New value of the <see cref="ParameterType"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
IParameterBuilder SetParameterType (Type type);
/// <summary>
/// Sets <see cref="IsRequired"/>.
/// </summary>
/// <param name="isRequired">New value of the <see cref="IsRequired"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
IParameterBuilder SetRequired (bool isRequired);
/// <summary>
/// Sets <see cref="DefaultValue"/>.
/// </summary>
/// <param name="defaultValue">New value of the <see cref="DefaultValue"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
IParameterBuilder SetDefaultValue (object defaultValue);
/// <summary>
/// Adds attributes to <see cref="Attributes"/>.
/// </summary>
/// <param name="attributes">New attributes to be added to <see cref="Attributes"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
IParameterBuilder AddAttributes (params Attribute[] attributes);
/// <summary>
/// Adds preconditions to <see cref="Preconditions"/>.
/// </summary>
/// <param name="preconditions">New attributes to be added to <see cref="Preconditions"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
IParameterBuilder AddPreconditions (params ParameterPreconditionAttribute[] preconditions);
}
}

View File

@@ -0,0 +1,162 @@
using System;
using System.Collections.Generic;
namespace Discord.Interactions.Builders
{
/// <summary>
/// Represents the base builder class for creating <see cref="IParameterInfo"/>.
/// </summary>
/// <typeparam name="TInfo">The <see cref="IParameterInfo"/> this builder yields when built.</typeparam>
/// <typeparam name="TBuilder">Inherited <see cref="ParameterBuilder{TInfo, TBuilder}"/> type.</typeparam>
public abstract class ParameterBuilder<TInfo, TBuilder> : IParameterBuilder
where TInfo : class, IParameterInfo
where TBuilder : ParameterBuilder<TInfo, TBuilder>
{
private readonly List<ParameterPreconditionAttribute> _preconditions;
private readonly List<Attribute> _attributes;
/// <inheritdoc/>
public ICommandBuilder Command { get; }
/// <inheritdoc/>
public string Name { get; internal set; }
/// <inheritdoc/>
public Type ParameterType { get; private set; }
/// <inheritdoc/>
public bool IsRequired { get; set; } = true;
/// <inheritdoc/>
public bool IsParameterArray { get; set; } = false;
/// <inheritdoc/>
public object DefaultValue { get; set; }
/// <inheritdoc/>
public IReadOnlyCollection<Attribute> Attributes => _attributes;
/// <inheritdoc/>
public IReadOnlyCollection<ParameterPreconditionAttribute> Preconditions => _preconditions;
protected abstract TBuilder Instance { get; }
internal ParameterBuilder (ICommandBuilder command)
{
_attributes = new List<Attribute>();
_preconditions = new List<ParameterPreconditionAttribute>();
Command = command;
}
protected ParameterBuilder (ICommandBuilder command, string name, Type type) : this(command)
{
Name = name;
SetParameterType(type);
}
/// <summary>
/// Sets <see cref="Name"/>.
/// </summary>
/// <param name="name">New value of the <see cref="Name"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public virtual TBuilder WithName (string name)
{
Name = name;
return Instance;
}
/// <summary>
/// Sets <see cref="ParameterType"/>.
/// </summary>
/// <param name="type">New value of the <see cref="ParameterType"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public virtual TBuilder SetParameterType (Type type)
{
ParameterType = type;
return Instance;
}
/// <summary>
/// Sets <see cref="IsRequired"/>.
/// </summary>
/// <param name="isRequired">New value of the <see cref="IsRequired"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public virtual TBuilder SetRequired (bool isRequired)
{
IsRequired = isRequired;
return Instance;
}
/// <summary>
/// Sets <see cref="DefaultValue"/>.
/// </summary>
/// <param name="defaultValue">New value of the <see cref="DefaultValue"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public virtual TBuilder SetDefaultValue (object defaultValue)
{
DefaultValue = defaultValue;
return Instance;
}
/// <summary>
/// Adds attributes to <see cref="Attributes"/>
/// </summary>
/// <param name="attributes">New attributes to be added to <see cref="Attributes"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public virtual TBuilder AddAttributes (params Attribute[] attributes)
{
_attributes.AddRange(attributes);
return Instance;
}
/// <summary>
/// Adds preconditions to <see cref="Preconditions"/>
/// </summary>
/// <param name="preconditions">New attributes to be added to <see cref="Preconditions"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public virtual TBuilder AddPreconditions (params ParameterPreconditionAttribute[] attributes)
{
_preconditions.AddRange(attributes);
return Instance;
}
internal abstract TInfo Build (ICommandInfo command);
//IParameterBuilder
/// <inheritdoc/>
IParameterBuilder IParameterBuilder.WithName (string name) =>
WithName(name);
/// <inheritdoc/>
IParameterBuilder IParameterBuilder.SetParameterType (Type type) =>
SetParameterType(type);
/// <inheritdoc/>
IParameterBuilder IParameterBuilder.SetRequired (bool isRequired) =>
SetRequired(isRequired);
/// <inheritdoc/>
IParameterBuilder IParameterBuilder.SetDefaultValue (object defaultValue) =>
SetDefaultValue(defaultValue);
/// <inheritdoc/>
IParameterBuilder IParameterBuilder.AddAttributes (params Attribute[] attributes) =>
AddAttributes(attributes);
/// <inheritdoc/>
IParameterBuilder IParameterBuilder.AddPreconditions (params ParameterPreconditionAttribute[] preconditions) =>
AddPreconditions(preconditions);
}
}

View File

@@ -0,0 +1,178 @@
using System;
using System.Collections.Generic;
namespace Discord.Interactions.Builders
{
/// <summary>
/// Represents a builder for creating <see cref="SlashCommandParameterInfo"/>.
/// </summary>
public sealed class SlashCommandParameterBuilder : ParameterBuilder<SlashCommandParameterInfo, SlashCommandParameterBuilder>
{
private readonly List<ParameterChoice> _choices = new();
private readonly List<ChannelType> _channelTypes = new();
/// <summary>
/// Gets or sets the description of this parameter.
/// </summary>
public string Description { get; set; }
/// <summary>
/// Gets or sets the max value of this parameter.
/// </summary>
public double? MaxValue { get; set; }
/// <summary>
/// Gets or sets the min value of this parameter.
/// </summary>
public double? MinValue { get; set; }
/// <summary>
/// Gets a collection of the choices of this command.
/// </summary>
public IReadOnlyCollection<ParameterChoice> Choices => _choices;
/// <summary>
/// Gets a collection of the channel types of this command.
/// </summary>
public IReadOnlyCollection<ChannelType> ChannelTypes => _channelTypes;
/// <summary>
/// Gets or sets whether this parameter should be configured for Autocomplete Interactions.
/// </summary>
public bool Autocomplete { get; set; }
/// <summary>
/// Gets or sets the <see cref="TypeConverter"/> of this parameter.
/// </summary>
public TypeConverter TypeConverter { get; private set; }
/// <summary>
/// Gets or sets the <see cref="IAutocompleteHandler"/> of this parameter.
/// </summary>
public IAutocompleteHandler AutocompleteHandler { get; set; }
protected override SlashCommandParameterBuilder Instance => this;
internal SlashCommandParameterBuilder(ICommandBuilder command) : base(command) { }
/// <summary>
/// Initializes a new <see cref="SlashCommandParameterBuilder"/>.
/// </summary>
/// <param name="command">Parent command of this parameter.</param>
/// <param name="name">Name of this command.</param>
/// <param name="type">Type of this parameter.</param>
public SlashCommandParameterBuilder(ICommandBuilder command, string name, Type type) : base(command, name, type) { }
/// <summary>
/// Sets <see cref="Description"/>.
/// </summary>
/// <param name="description">New value of the <see cref="Description"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public SlashCommandParameterBuilder WithDescription(string description)
{
Description = description;
return this;
}
/// <summary>
/// Sets <see cref="MinValue"/>.
/// </summary>
/// <param name="value">New value of the <see cref="MinValue"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public SlashCommandParameterBuilder WithMinValue(double value)
{
MinValue = value;
return this;
}
/// <summary>
/// Sets <see cref="MaxValue"/>.
/// </summary>
/// <param name="value">New value of the <see cref="MaxValue"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public SlashCommandParameterBuilder WithMaxValue(double value)
{
MaxValue = value;
return this;
}
/// <summary>
/// Adds parameter choices to <see cref="Choices"/>.
/// </summary>
/// <param name="options">New choices to be added to <see cref="Choices"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public SlashCommandParameterBuilder WithChoices(params ParameterChoice[] options)
{
_choices.AddRange(options);
return this;
}
/// <summary>
/// Adds channel types to <see cref="ChannelTypes"/>.
/// </summary>
/// <param name="channelTypes">New channel types to be added to <see cref="ChannelTypes"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public SlashCommandParameterBuilder WithChannelTypes(params ChannelType[] channelTypes)
{
_channelTypes.AddRange(channelTypes);
return this;
}
/// <summary>
/// Adds channel types to <see cref="ChannelTypes"/>.
/// </summary>
/// <param name="channelTypes">New channel types to be added to <see cref="ChannelTypes"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public SlashCommandParameterBuilder WithChannelTypes(IEnumerable<ChannelType> channelTypes)
{
_channelTypes.AddRange(channelTypes);
return this;
}
/// <summary>
/// Sets <see cref="AutocompleteHandler"/>.
/// </summary>
/// <param name="autocompleteHandlerType">Type of the <see cref="IAutocompleteHandler"/>.</param>
/// <param name="services">Service container to be used to resolve the dependencies of this parameters <see cref="TypeConverter"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public SlashCommandParameterBuilder WithAutocompleteHandler(Type autocompleteHandlerType, IServiceProvider services = null)
{
AutocompleteHandler = Command.Module.InteractionService.GetAutocompleteHandler(autocompleteHandlerType, services);
return this;
}
/// <inheritdoc/>
public override SlashCommandParameterBuilder SetParameterType(Type type) => SetParameterType(type, null);
/// <summary>
/// Sets <see cref="ParameterBuilder{TInfo, TBuilder}.ParameterType"/>.
/// </summary>
/// <param name="type">New value of the <see cref="ParameterBuilder{TInfo, TBuilder}.ParameterType"/>.</param>
/// <param name="services">Service container to be used to resolve the dependencies of this parameters <see cref="TypeConverter"/>.</param>
/// <returns>
/// The builder instance.
/// </returns>
public SlashCommandParameterBuilder SetParameterType(Type type, IServiceProvider services = null)
{
base.SetParameterType(type);
TypeConverter = Command.Module.InteractionService.GetTypeConverter(ParameterType, services);
return this;
}
internal override SlashCommandParameterInfo Build(ICommandInfo command) =>
new SlashCommandParameterInfo(this, command as SlashCommandInfo);
}
}