Releases: freya022/BotCommands
v3.0.0-alpha.11 | Modal improvements, default timeouts and interfaced declarations
Overview
Simplified code-declared commands, autocomplete and rate limit declarations; Separated annotated command properties and QoL additions.
Mandatory JDAService
(#154)
Creating a service extending JDAService
is now required.
This has many advantages:
- Checking gateway intents, cache flags, and member cache requirements for event listeners and event waiters
- Conditionally enabling services based on gateway intents (see
@RequiredIntents
),
cache flags, and member cache - Starting JDA when every other service is ready
However, this means that you can only initialize JDA in one place,
as a reminder, you can get a JDA instance by either:
- Listening to
InjectedJDAEvent
- Retrieving it using lazy services
- Getting it manually, after it has been injected (not recommended)
Code-declared commands using interfaced services (#153)
To reduce confusion, simplify documentation, improve feature discoverability and performance,
@TextDeclaration
and @AppDeclaration
were replaced with interfaces: TextCommandProvider
and GlobalApplicationCommandProvider
/GuildApplicationCommandProvider
.
Declaring command is now as simple as implementing one of these interfaces.
The only downside is that you can no longer use dependency injection, but you can still move those dependencies to the declaring class.
Before
@Command
class MyCommand {
@AppDeclaration
fun declare(manager: GlobalApplicationCommandManager) {
// declare commands
}
}
After
@Command
class MyCommand : GlobalApplicationCommandProvider {
override fun declareGlobalApplicationCommands(manager: GlobalApplicationCommandManager) {
// declare commands
}
}
Code-declared autocomplete using interfaced services (#153)
In-command autocomplete declarations had a few issues, the main issue being that they could be declared multiple times (due to loops, being callable per-guild, or having to be updated),
which could override previous handlers, and caused these previous handlers to not be invalidated.
Autocomplete handlers can now be declared similarly to commands, by implementing AutocompleteHandlerProvider
,
and be referenced by name, using autocompleteByName
, or by callable reference, such as autocompleteByFunction(SlashPlay::onTitleAutocomplete)
.
Before
@Command
class SlashBasicAutocomplete : GlobalApplicationCommandProvider {
suspend fun onSlashBasicAutocomplete(event: GuildSlashEvent, fruit: String) {
// Reply
}
fun onFruitAutocomplete(event: CommandAutoCompleteInteractionEvent, fruit: String): Collection<String> {
return emptyList() // Return choices
}
override fun declareGlobalApplicationCommands(manager: GlobalApplicationCommandManager) {
manager.slashCommand("basic_autocomplete", function = ::onSlashBasicAutocomplete) {
option("fruit") {
// This seems easier but you would run into issues if that line was executed more than once,
// which includes when your commands are getting updated a second time
autocomplete("SlashBasicAutocomplete: fruit", ::onFruitAutocomplete)
}
}
}
}
After
@Command
class SlashBasicAutocomplete : GlobalApplicationCommandProvider, AutocompleteHandlerProvider {
suspend fun onSlashBasicAutocomplete(event: GuildSlashEvent, fruit: String) {
// Reply
}
fun onFruitAutocomplete(event: CommandAutoCompleteInteractionEvent, fruit: String): Collection<String> {
return emptyList() // Return choices
}
override fun declareGlobalApplicationCommands(manager: GlobalApplicationCommandManager) {
manager.slashCommand("basic_autocomplete", function = ::onSlashBasicAutocomplete) {
option("fruit") {
// Reference an existing autocomplete value supplier for this option
autocompleteByFunction(::onFruitAutocomplete)
}
}
}
override fun declareAutocomplete(manager: AutocompleteManager) {
// Register this function as an autocomplete values supplier
// You can customize, but there's nothing to do here
manager.autocomplete(::onFruitAutocomplete)
}
}
Code-declared rate limits using interfaced services (#156)
Similar to autocomplete handlers, rate limits could be declared multiple times, which led to exceptions.
This change makes it so annotated and in-command rate limits are declared anonymously, as they don't have a name and cannot be referenced.
Also, to keep a similar API with commands and autocomplete handlers, rate limits are now declared by implementing RateLimitProvider
.
Note: In-command rate limits can still be used.
Before
@Command
class MyCommand {
@RateLimitDeclaration
fun declare(rateLimitContainer: RateLimitContainer) {
// declare commands
}
}
After
@Command
class MyCommand : RateLimitProvider {
override fun declareRateLimit(manager: RateLimitManager) {
// declare rate limits
}
}
Prefixed component and modal IDs (#150)
To help verify ownership of components and modals, a prefix has been added to their IDs,
as such, any previously created component / modal will no longer be recognized.
In the future, this should allow to disable errors related to unknown components and modals,
if you have an use case for such thing, make sure to make a feature request for it.
Note: Custom modal IDs can no longer be set, they were used to cache values of a cancelled modal,
but are tricky to use, and rather need proper support from Discord.
Distinct annotations for path-specific command properties (#146)
Annotated commands suffer from several issues due to all the data being written in one annotation:
- For multiple commands with the same top-level name, you must specify the same data everytime (like the
scope
,defaultLocked
ornsfw
), which causes hard to diagnose issues if the values are not the same everywhere, without even mentioning the maintainability problem - The
description
of subcommand groups had a chance to not be applied on the right group- This is due to the annotation applying the description to the top-level command, the subcommand group, as well as the subcommand, as all of them share the same description
- This is also what causes unnecessary application command updates, as the description of subcommand groups would sometimes alternate (partially due an unstable order of reflectively-obtained methods), this did not cause an issue as subcommand groups are not visible on Discord (yet)
- Text commands had a
generalDescription
property, but this only applies to the text command itself, i.e., not on the text command variation- It was unclear where that description was applied on
Solution
Properties which are attribuable to only a part of a command (such as the scope
which only can be set on the top-level command) will be in a different annotation:
- Slash commands will have 3 annotations:
- [Required on subcommands] Top-level (
scope
,defaultLocked
,nsfw
,description
) - [Optional] Subcommand group (
description
) - [Required] Slash command (
name
,group
,subcommand
,description
)
- [Required on subcommands] Top-level (
- Text commands will have 2 annotations:
- [Optional] Text command (
path
,aliases
,description
) (path
is the path this annotation applies to, if empty, apply on the variation's path) - [Required] Variation (
path
,order
,description
,usage
,example
)
- [Optional] Text command (
Annotations which applies to text commands may appear on a single variation, but they affect the command as a whole, and are not allowed more than once per path.
The description for a top-level text command can be only be set on either annotations.
Slash commands - Before
@Command
class MyMentionsString {
@JDASlashCommand(name = "mentions_string", subcommand = "member")
suspend fun onSlashMentionsStringMember(
event: GuildSlashEvent,
@SlashOption @MentionsString mentions: List<Member>
) {
// Reply
}
@JDASlashCommand(name = "mentions_string", subcommand = "input_user")
suspend fun onSlashMentionsStringInputUser(
event: GuildSlashEvent,
@SlashOption @MentionsString mentions: List<InputUser>
) {
// Reply
}
}
Slash commands - After
@Command
class MyMentionsString {
@TopLevelSlashCommandData // This is required once, when you have subcommands
@JDASlashCommand(name = "mentions_string", subcommand = "member")
suspend fun onSlashMentionsStringMember(
event: GuildSlashEvent,
@SlashOption @MentionsString mentions: List<Member>
) {
event.reply("Mentions:\n${mentions.joinAsList(linePrefix = "-")}").await()
}
@JDASlashCommand(name = "mentions_string", subcommand = "input_user")
suspend fun onSlashMentionsStringInputUser(
event: GuildSlashEvent,
@SlashOption @MentionsString mentions: List<InputUser>
) {
event.reply("Mentions:\n${mentions.joinAsList(linePrefix = "-")}").await()
}
}
Text commands - Before
@Command
class TextTest {
// Quite a bit messy to put the command description and the variation's description i...
v3.0.0-alpha.10 | Text command suggestions, exception context and primary service providers
Overview
Added text command suggestions, extra exception context and primary service providers.
Don't hesitate to check out the changelogs and the wiki as they contain more details.
Fixes
- Added back support for regional indicator emojis (Commit)
- Prepared statements returns a nullable
ResultSet
- Skip adding the "Usages" header in help content if there are no variations
- Services missing an injected dependency (such as
JDA
) can always be retrieved
Changes
- Updated JDA-KTX to the maven-central version:
club.minnced:jda-ktx:0.11.0-beta.19
- You no longer need the Jitpack repository
- Deprecated
BBuilder
entry point, replaced byBotCommands
- Make entry point return
BContext
- Application command cache is now stored in:
%appdata%/BotCommands
on Windows/var/tmp/BotCommands
on Unix
BContext#getPrefix
is nullablenull
if no prefix has been added and ping-as-prefix is not configured, in which case it is logged
Additions
- Added null variants in
EmojiUtils
- Added "primary" service providers
- A primary service provider is prioritized over a normal service provider
- If multiple service providers exist, only one must be usable, or, only one must be marked primary (using
@Primary
).
- Exposed
#setParameters
on prepared statements- This allows setting parameters when using batch statements
- Reimplemented text command suggestions (#143)
- Enabled by default
- Hidden text commands behave the same as if the command didn't exist at all
- Added
TextSuggestionSupplier
and a default implementation, allows command filtering and sorting
- Add extra context to uncaught exceptions in commands/component handlers (#144)
- Improved message format
- Improved exception cleaning
- Any context info can be added in
BContext#dispatchException
- Added
DBResult#stream
(Mainly for Java users)
Full Changelog: v3.0.0-alpha.9...v3.0.0-alpha.10
v3.0.0-alpha.9 | H2 DB, blocking database, improved query logging and service injection
Overview
Added H2 database support, blocking database and buildable components for Java users, reworked query logging and improved service injection with lazy and list of interfaced services.
Note: The wiki has now moved to https://freya022.github.io/BotCommands/3.X
Don't hesitate to check out the changelogs as they contain more details.
Fixes
- Fixed inexistant application commands map when
BApplicationConfig#slashGuildIds
was used (Commit) - Fixed
Event#getRawData
not returning anything - Fixed component timeouts not being retrievable when no handler was added
- Fixed component timeout handlers not having user data passed through (#137)
- Fixed Java type matching for parameter resolver factories (Commit)
- Reply with "Application commands not available" message if a command is not found, and global applications are not registered. (Commit)
- This happens if a global command tries to be executed, when global commands failed to update on startup
- Fixed name of requested services not being taken into account (Commit)
- Fix unknown component filters by preventing usage of anonymous component filters (Commit)
Changes
- Moved
Logging
tocore
package - Replaced
emoji-java
withJEmojis
(#132)- This removes the
org.json
dependency and updatesjackson-databind
to 2.16.0 - Fixes issues with emoji indexes and incorrect fitzpatrick formats
- This removes the
- Require
@DevConfig
opt-in onBApplicationConfig#forceGuildCommands
- Allow calling
DBResult
'sIterator#hasNext
more than once - Reworked query logging (#133)
- Allows adding RDBMS-specific parametrized queries, as to provide the most accurate executable queries
- Connections made with
(Blocking)Database
transparently return traced connections and prepared statements - Prepared statements are logged by using the class which created it, this means that your logger level for the class itself must be on
TRACE
- Prepared statements can have their loggers changed manually, this is only useful if the logger's name cannot be retrieved using the execution stack, see
Database
for more details on tracing
BConfig#logQueries
is now disabled by default- This is done as to avoid accidental logging, now that the logger is the caller class
- Java users can now use use a builder pattern when creating components, similar to V2
- Allow
null
in persistent handlers / timeouts user data (#137) - Separated database configs in a
database
block (Commit)
Additions
- Added a message when applications commands are not registered yet
- Added
BlockingDatabase
for Java users (#133) - Added the ability to read generated keys (Commit)
- Added support for primitive arrays when setting statement parameters (Commit)
- Added missing
lazy
overloads on ServiceContainer (Commit) - Added support for
Lazy
andList
when injecting services- Lazily injected services can have their element type nullable (#141)
- Added support for H2 database (#139)
- Requires PostgreSQL compabitility mode, see
ConnectionSupplier
for more details - This allows you to run an in-memory database, or have it saved to a file, see H2 Database connection modes for details
- Flyway users: Due to required migration script changes, the
bc
schema needs to be deleted, other solutions include changing the checksum or using Flyway#repair, with their own caveats
- Requires PostgreSQL compabitility mode, see
- Allow unresolvable services on optional parameters (Commit)
- Added
ServiceContainer#canCreateService
overload for named services
Removals
- Removed deprecated interaction filtering methods
Full Changelog: v3.0.0-alpha.8...v3.0.0-alpha.9
v3.0.0-alpha.8 | Mentions string, command filters and dynamic channel resolvers
Overview
Added getting mentions from slash command strings, command-specific filters and improvements in documentation.
Don't hesitate to check out the changelogs as they contain more details.
Fixes
- Fixed slash command groups not using default descriptions
- Fixed reading arrays with
DBResult
- Fix parameter resolver cache
Changes
- Renamed
commands.prefixed
package tocommands.text
- Renamed
RegexParameterResolver
toTextParameterResolver
- Moved resolver interfaces from
parameters
toparameters.resolvers
- Updated to Kotlin 1.9.20
- Replaced
Class
withKClass
in DSLs - Filters no longer handles replying, a "rejection handler" must be created for it, check the changelogs for more details
- Abort component interactions if an option is unresolvable and has been acknowledged
- Previously, this would have thrown
Additions
- Allow
logger
live template in Kotlin object declarations - Added command specific filters (PR)
- Added cache flags to
JDAService
- Use service priority when loading non-interfaced services
- Added
@MentionsString
to get a list of mentionables in aSTRING
option - Added a dynamic channel resolver
- All
GuildChannel
types are supported (including future channel types), except trait interfaces (such asIPositionableChannel
) ThreadChannel
is only supported for slash commands
- All
Full Changelog: v3.0.0-alpha.7...v3.0.0-alpha.8
v3.0.0-alpha.7 | Package change, enhanced resolver factories
Overview
Changed the base package, added predicate-based resolver factories, more extensions and fixes.
Don't hesitate to check out the changelogs as they contain more details.
Fixes
- Fixed some potential unknown events (commit)
- Fixed timeout caused by
Database#fetchConnection
not suspending before a connection is available (commit) - Fixed custom conditions on service factories
- Fixed default descriptions not being retrieved for DSL-declared commands (commit)
RequiredIntents
properly throws ifJDAService
is not present
Changes
- Updated
kotlin-logging
to 5.X - Changed base package from
com.freya02
toio.github.freya022
- A simple Find & Replace is enough to fix this
- Bot templates now exist as GitHub repository templates, both in Java and Kotlin
- Changed packages of
GlobalExceptionHandlerAdapter
,InstanceSupplier
,DefaultMessages
,RateLimitScope
andBContext
- (Java users) Renamed some primary annotations values to
value
, avoiding named parameters - Revamped the built-in command-specific help embed
- Replaced
name
/group
/subcommand
in@JDATextCommand
with apath
array- Still limited to 3 path components
Additions
- Added
CommandBuilder#cooldown
extension - Added
BConfig#queryLogThreshold
, logs a query onWARN
if it takes longer than the configured duration - Added per-variant usage and examples on text commands
- Added predicate-based parameter resolver factories
- Allows you to return parameter resolvers based on custom conditions, see the changelog and docs for more details
- Added
RestAction#timeout
using Kotlin'sDuration
- Added
deleteDelayed
extensions for webhook replies/edits - Added
IThreadContainer#retrieveThreadChannelByIdOrNull
(commit) - Added
BContext
to framework events
Removals
- Removed
BContext
from resolvers,GlobalExceptionHandler(Adapter)
,DynamicSupplier
- Retrieve the context using dependency injection instead
Full Changelog: v3.0.0-alpha.6...v3.0.0-alpha.7
v3.0.0-alpha.6 | Rate limiting, localization extensions and DB debug
Overview
Added token bucket-based rate limiting, a convenient way to get both a user and a member, more extensions, transaction debugging and a Java bot template.
Don't hesitate to check out the changelogs as they contain more details.
Fixes
- Fixed text subcommand aliases
- Fixed commands parsing when only the bot mention was present
- Fixed
ClassGraphProcessor#postProcess
running more than once
Changes
- Having a root localization bundle for a given bundle name is now eagerly enforced
BApplicationConfigBuilder#onlineAppCommandCheckEnabled
is now opt-in- Tweaked setter names in config builders for Java users
- Persistent handler name is passed to
ComponentInteractionFilter
if available
Additions
- Added
orNull
variants ofLocalizationContext
(and sub-interfaces) functions - Added localized reply/edit extensions, such as
event#replyLocalized
,hook#editLocalized
- Added
LocalizationContext#switchBundles
which changes the target bundle and clears the prefix, while keeping the locale - Added token bucket-based rate limiting
- Added JDA extensions using Kotlin's
Duration
- Added
ErrorResponse
ignoring functions - Added optional coroutine / thread dump on long transactions
- Added input users, helping in having both the user and member if available
Removals
- Removed deprecated
DBResult
functions
Full Changelog: v3.0.0-alpha.5...v3.0.0-alpha.6
v2.10.3 | Command suggestions switch, a few fixes
Overview
Adds the ability to disable text command suggestions and fixes a few issues
Fixes
- Fixed paginators not able to delete themselves
Changes
- Data passed to
Modals#create
now accepts null values
Additions
- Added
TextCommandsBuilder#disableSuggestions
, disables suggestions when a user tries to use an unknown command
Full Changelog: v2.10.2...v2.10.3
v3.0.0-alpha.5 | Custom conditions, resolver service factories, and JDAService
Overview
Added custom conditions, parameter resolvers can be created from service factories, and added a JDA service abstraction.
Fixes
- Paginator can delete itself in a channel it does not have access to
- Interfaced services with the same "simple name" no longer exclude each others
Changes
- Service annotations can be used on property getters
- Deprecated
DBResult#readOnce
withread
/readOrNull
- Null values are now allowed in modal data
Additions
- Added more JDA extensions
- Added
BTextConfig#showSuggestions
to enable command suggestions on unknown command - Added custom condition annotations
- Added support for parameter resolver using service factories
- Added
bindTo
extensions for persistent components- This allows you to avoid using a constant to declare the handler, and while having the handler reference, as well as the arguments, checked at compile time
- Added
JDAService
, see here- This allows you to not worry about initialization order, as the function creating JDA is called at the right time
- This also allows the framework to know in advance what intents JDA is using
- Added
@RequiredIntents
, allowing you to enable/disable a service based offJDAService#intents
- Added intent checks on event listeners
BEventListener#ignoreIntents
can be used to ignore those checksBConfig#ignoredIntents
can be used to not warn about the supplied intentsBConfig#ignoredEventIntents
can be used to not warn about the intents of a specified event, in theEventWaiter
Removals
- Non-suspending functions of
KPreparedStatement
, inherited fromPreparedStatement
, are now hidden
Full Changelog: v3.0.0-alpha.4...v3.0.0-alpha.5
v3.0.0-alpha.4 | Localization extensions, service priorities
Overview
Improved the extensibility of the Localization API, service types of interfaced services are added automatically, and added service priority.
Fixes
- Suspending service factories are now prohibited correctly
- Fixed single-implementation interfaces services not being constrained correctly
- Fixed
BStatusChangeEvent
not having the correct old status
Changes
- Renamed
FirstReadyEvent
toFirstGuildReadyEvent
- Improved extension of the Localization API, more details here
- Service types of interfaced services are now added automatically
- If you still have a
@ServiceType
used for it, you will be warned
- If you still have a
- Application commands will not be updated if there is an error on the initial update (i.e., on startup)
- Improved exception when an option annotation was possibly forgotten
- Bundles with a
-default
postfix (between the base name and the locale tag) are read by default- The "default" bundle is overridden by existing bundles
- Reworked interaction filters
- Uses interfaced services and coroutines
- All filters are now ran before their targets gets executed
Additions
- Added extensions to MessageCreateData and MessageEditData
- Added
suppressContentWarning
to temporarily suppress message content intent warnings- This is useful if you read the content of message context commands, but without having the
MESSAGE_CONTENT
intent
- This is useful if you read the content of message context commands, but without having the
- Added
namedDefaultScope
to easily create aCoroutineScope
with incrementally named threads - Added
readResource
,withResource
andreadResourceAsString
to read resources relative to the caller class - Added
getValue
operator onServiceContainer
(enables you to use theby
operator to get a service) - Added service priority
- Either on
@BService
or with@ServicePriority
- Either on
- Added
Class
overloads for functions which acceptedKClass
- Added logs of annotated commands being excluded by
@Test
/@CommandId
- Check autocomplete parameters missing from slash commands
- Added an error when invalid component IDs are used
Removals
- Removed Gson
Full Changelog: v3.0.0-alpha.3...v3.0.0-alpha.4
v3.0.0-alpha.3 | Docs, dynamic help examples and EventWaiter
Overview
Added back EventWaiter
, fixed inconsistent handling of default locked/test commands
Fixes
- Fixed inconsistent handling of default locked/test commands
Changes
- Separated
AppOption
intoSlashOption
andContextOption
Additions
- Added back
EventWaiter
, with coroutines support - Added dynamic help examples, which lets you generate an help example based on the execution context (by using the event)
- Exposed
CooldownService
to the API - Added
InjectedJDAEvent
, which gets fired when a JDA instance is received and injected as a service - Reworked most docs related to commands/components/modals
Full Changelog: v3.0.0-alpha.2...v3.0.0-alpha.3