Releases: ShindouMihou/Velen
v3.1.1
⭐ Maven Central & Javacord 3.4.0
Velen is now back on Maven Central after Javacord has finally released their v3.4.0 to the general public. What does this mean for us people who've used the Jitpack version?
- You are encouraged to update to the Maven Central version for a more stable, supported version of Velen.
- Jitpack repository is no longer required, but you may continue to use Jitpack if you wish to utilize a certain version with only a specific commit.
🌡️ What have changed in this tiny patch?
This version of Velen provides a little compatibility update to allow support to the newer, stable release of Javacord. The following changes were done to prevent a breaking, deprecated change:
- Anything in the custom responders for Velen that contains
addFile
as the start has been changed internally to utilize the non-deprecated methodaddAttachment
counterparts. This will continue to be used until further notice. - The version number has been changed from
v3.4.0-SNAPSHOT
to 3.4.0for Javacord on
pom.xml`. - The field
numeric
in the custom command builder for Velen is now usingSlashCommandoptionType.LONG
instead ofINTEGER
which was removed for specific reasons
❤️ Installation
You can install Velen from Maven Central, otherwise known as Sonatype, which also hosts Javacord and many
other libraries.
📦 Maven
<dependency>
<groupId>pw.mihou</groupId>
<artifactId>Velen</artifactId>
<version>3.1.1</version>
</dependency>
📦 Gradle
implementation 'pw.mihou:Velen:3.1.1'
v3.1.0
A new version for Velen which includes one behavioral-breaking change for message commands that uses choices, as for the release notes, here are what we added for this week:
- Added support for slash command indexing, allowing server-specific commands to no longer conflict with slash commands and also increasing performance for slash commands. You can read more @ https://github.com/ShindouMihou/Velen/wiki/Building-Commands!#-indexing-slash-commands
- Fixed an issue with
VelenInviteBuilder
that usedscopes
instead ofscope
for the URL paramater. - 🔴 Key-values are now enforced for message commands, allowing hybrid commands to be closer to their slash command counterparts. What this means is instead of the previous
[choiceOne, choiceTwo, choiceThree]
choices for Velen, it now uses a key-value pair akin to slash commands:[choiceName, choiceValue]
. - 🔴 Removed deprecated
getCommandIgnoreCasing
method. - Add additional support for observeServer(Velen, Server) and
observeAllServer(Velen, DiscordApi... shards)
in VelenObserver.
v3.0.6
A short update that includes some interesting new things:
- Added support for
VelenObserver#observeServer
, it should now automatically update, create server-specific commands as long as you want it. - Changed return type of
VelenObserver#observe
fromvoid
toCompletableFuture<Void>
to allow for blocking, this applies to the above. - Added our own custom CLI called
Velen CLI
which is written in Rust, read more @ https://github.com/ShindouMihou/Velen/tree/master/cli-core
v3.0.5 STABLE
🌃 Trails over the night skies
🟡 To fix some issues with Jitpack, this version has been renamed to
v3.0.5-STABLE
(since the DEV versions were being shown higher than this version). Future Maven Central versions will not follow this versioning system.
A new version of Velen is now out with plentiful of changes, to summarize all the changes:
- Middlewares are now implemented (#17): https://github.com/ShindouMihou/Velen/wiki/Categories,-Middlewares-and-Afterwares
- Afterwares are now implemented (#17): https://github.com/ShindouMihou/Velen/wiki/Categories,-Middlewares-and-Afterwares
- Categories are now implemented (#17): https://github.com/ShindouMihou/Velen/wiki/Categories,-Middlewares-and-Afterwares
- Exposed
default_permission
field for slash commands. - Rewrote
VelenMirror
for a more readable look to potential contributors. - Added support for
.vecomp
files, otherwise known asVelen Category Component
files. (#17) - Added parser for
.vecomp
files, you can set up categories as files now, please viewexamples/categories
for more information or the wiki: https://github.com/ShindouMihou/Velen/wiki/Categories,-Middlewares-and-Afterwares. (#17) - Added more depth information to categories (
description
) (#17). - Removed
SlashCommandChecker
in favor ofVelenObserver
, read more here: https://github.com/ShindouMihou/Velen/wiki/Building-Commands!#%EF%B8%8F-automating-slash-command-updating-and-creation (🔥 BREAKING 🔥) - Fixed compatibility issues with the latest Javacord versions.
- Added
VelenBotInviteBuilder
which is a more advanced version of Javacord'sBotInviteBuilder
with scopes, etc.
v3.0.5-DEV003
This is a version that consists of several fixes and improvements (but is not the complete v3.0.5 version):
- Exposed
default_permission
field for slash commands. - Make
VelenMirror
more readable for potential contributors. - Add support for
.vecomp
files, otherwise known asVelen Category Component
files. - Add parser for
.vecomp
files, you can setup categories as files, please check theexamples/categories
folder for more details.
v3.0.5-DEV002
This is a version that consists of several fixes and improvements (but is not the complete v3.0.5 version):
- Added
middlewares
from #17 - Added more depth into categories from #17
- Fixed multiple issues regarding middleware and so forth.
- Fixed issues with
VelenObserver
which is the replacement forSlashCommandChecker
. - Fixed compatibility issues from latest Javacord versions.
- Removed
SlashCommandChecker
in favor ofVelenObserver
.
v3.0.0
🐉 The Largest Update of Velen
Velen has gone through a lot of changes since its last official version to the master
branch, after a long wait for Javacord 3.4.0, I decided to let this version be out for official use to all the users. Here are all the BREAKING and AMAZING changes that the framework has gone through over the past three weeks.
Feel free to read from the Pull Request
🌟 Velen Mirror
Velen Mirror is the new command constructor system of Velen that aims to separate the nature of your code and
the command constructors which tends to be a mess especially for bots with tons of commands. Mirror is far cleaner
and verbose to read than ordinary Java builders, written under the .velen
syntax.
To fully understand the outline of Mirror, let us take a glance at a simple ping-pong command that can be found written
similarly on both Message and Slash folders but adapted to their own use-case. Our example here will showcase how they can
be written in Hybrid Command.
🎂 Ping-Pong with Velen Mirror
Now that we know of all the currently possible options of Velen Mirror, let us start to minimize
the file to view the actual parts of the command, shall we?
To see a full explanation of everything, please scroll even more below.
😲 ping.min.velen
&[ping]: hybrid {
desc: Do you want to ping-pong with me?
usage: ping [pong|ping]
usage: ping [ping|pong]
shortcut: pong
&[response]: option {
desc: What kind of move will you make?
choice: [PING, PONG]
choice: [PONG, PING]
required: true
type: string
}
cooldown: 5000
handler: hybrid.ping
}
Doesn't that look quite clean and readable, compare that to the original Java builder method?
Press here to read more about Velen Mirror
🥳 True Hybrid Command Support
Velen now supports TRUE hybrid command support which means you can now use a single handler for both slash commands and message commands. It supports both subcommand, subcommand groups, options and practically most of slash commands to message commands.
💘 Automated Slash Command Updater/Registerer
Velen now offers a new integrated module which allows you to automatically update slash commands in a more automated way, this module checks for any differences between slash commands (global ones) to the tiniest bit like options, names or descriptions then updates them accordingly.
There are two different modes to this: NORMAL
and SOFT
- Normal Mode
- This mode will register any
VelenCommand
that isn't registered on Discord's side already while also updating the ones that have differing values (likeSoft
).
- This mode will register any
- Soft Mode
- This mode will not register any
VelenCommadn
that isn't registered on Discord's side but will update any that have differing values (like for example, if aVelenCommand
finds an equivalent command on Discord's side but with a different description, or a different option. It will send an update to update that command).
- This mode will not register any
📦 How to use?
To use this module, all you have to do is create a new SlashCommandChecker
instance which takes in a DiscordApi
and Velen
instance (the DiscordApi
can be any shard, if you are wondering since it shouldn't matter for Discord):
Velen velen = ...
DiscordApi api = ...
new SlashCommandChecker(api, SlashCommandCheckerMode.NORMAL).run(velen);
The method run(Velen)
returns back a CompletableFuture<Integer>
with the integer showing many commands were updated (and registered).
💭 Is this blocking?
Despite being a CompletableFuture
, the initial collection of all slash commands from Discord will be a blocking statement and shouldn't take long (usually 1-2 seconds depending on your latency towards Discord's REST). In the first place, this method IS SUPPOSED TO BE USED AT STARTUP to keep everything up-to-date each restart.
Other than that, after the initial GET
request towards Discord, everything will start to run asynchronously through a different threadpool (VelenThreadPool
) to prevent any blockage with Javacord's side.
📝 Interaction Support for Paginate
This version of Velen now supports interactions for Pagination Helper, please note that this change has introduced a major breaking change for any code that uses PaginateEvent
, here is an example of the previous PaginateEvent
:
new PaginateSimpleEvent<String> {
...
}
And here is how it looks in this new version:
new PaginateSimpleEvent<MessageBuilder, MessageCreateEvent, String> {
...
}
new PaginateSimpleEvent<InteractionOriginalResponseUpdater, InteractionCreateEvent, String> {
...
}
Your IDE should assist you into fixing this breaking change, don't worry.
💭 Why the sudden breaking change?
The sudden breaking change was to introduce this new interaction support while also reducing code duplication as much as possible, otherwise, you would be expecting at least a very fat package for this framework. You can find all the changes here.
😭 Another Breaking Change
There is another breaking change to Velen which involves the slash event but don't worry, you can quickly fix this through CTRL + F
and CTRL + R
, the change added SlashCommandCreateEvent
to the onEvent
for VelenSlashEvent
which is needed to support Pagination with Interactions.
Old:
void onEvent(SlashCommandInteraction event, User user, VelenArguments args,
List<SlashCommandInteractionOption> options, InteractionImmediateResponseBuilder firstResponder);
New:
void onEvent(SlashCommandCreateEvent originalEvent, SlashCommandInteraction event, User user, VelenArguments args,
List<SlashCommandInteractionOption> options, InteractionImmediateResponseBuilder firstResponder);
🌃 Named Options is now supported!
Velen now supports named options, or otherwise named as routed options, which as the name implies works similar to a web framework's router which allows message commands and hybrid commands to be named and be conditioned from the get-go. This is by far one of the better changes of Velen but it is also breaking for message commands which can be fixed easily.
📦 Syntax and Formats
To first understand how this all works, we have to look in depth of the syntax for the formats:
:[optionName]
is how a placeholder for an option looks.:[optionName::(choose,only,among,us)]
is how a placeholder with limited options (ignore casing) looks, the user has to only pick among the options inside the::(...)
. PLEASE NOTE THAT VELEN DOES NOT SUPPORT PLACING SPACES BETWEEN OPTIONS:[optionName:(choose,only,among,us)]
is similar to the one above this but with strict casing.:[optionName:{^[0-9]}]
is a regex pattern option, this first checks if the option in that index matches the regex.
You can only place one regex pattern checker and option limiter inside a option (you can have both though), with a full example of a format utilizing all looking like this:
quiz :[name] :[difficulty::(hard,medium,easy)] :[topic::(anime,politics)] :[amount:{^[0-9]}]
The format above tells Velen that the command should have 4 arguments, the first argument will be named as name
and the second argument will be difficulty
and should match either hard, medium or easy
(case insensitive) with the third argument being named topic
and should match either anime, politics
(case insensitive) and lastly, the last argument should be named amount
and should match the regex pattern: ^[0-9]
which means it should be a digit.
The beauty of this entire thing is, you can have multiple formats and Velen will still accurately grab the correct option name but ensure that the name of the options are unique in each format otherwise Velen will pick up only the first case. An instance with multiple formats is:
quiz :[name] :[difficulty::(hard,medium,easy)] :[topic::(anime,politics)] :[amount:{^[0-9]}]
quiz :[name] :[difficulty::(hard,medium,easy)] :[amount:{^[0-9]}]
quiz :[name] :[topic::(anime,politics)] :[amount:{^[0-9]}]
quiz :[name] :[amount:{^[0-9]}]
quiz :[name]
quiz :[name] :[topic::(anime,politics)] :[difficulty::(hard,medium,easy)] :[amount:{^[0-9]}]
quiz :[name] :[amount:{^[0-9]}] :[topic::(anime,politics)] :[difficulty::(hard,medium,easy)]
If your command has all those formats, Velen will still be able to fetch the correct option name, so don't worry. 😄
💯 Adding formats to your commands and syntax
This is the required method to have this entire thing working, you have to add a format to your command during building using the VelenCommandBuilder#addFormats(...)
method, for instance:
VelenCommand.of("test", "A test command.", velen, (event, message, user, args1, options) -> {
String name = options.withName("name").orElse("Unknown Person");
if (options.withName("condition").isPresent()) {
message.reply("Good"+options.withName("condition").get()+", " + name);
} else {
message.reply("Hello " + name);
}
}).addFormats("test :[name]")
.addFormats("test :[name] :[condition::(morning,night)]")
.attach();
The example above will reply with Hello <name>
if there is a name present, otherwise replies with Hello Unknown Person
and if condition
is present and also is either morning or night
then it will reply with Goodmorning <name>
or Goodnight <name>
.
Hybrid commands also work the same but with extra steps on getting the value of the op...
v2.1.1
🎉 What's New?
⭐ Internal Changes
- The internal dispatcher for Message commands have been rewritten again, it should be running
O(1)
for full message command names (e.g:v.help
instead of a shortcut likev.hel
) which should, in theory, make it faster as it fetches the command at static time but this has its drawbacks:
a. You cannot have two or more VelenCommands with the same name anymore. - Fixed issue with commands not running asynchronous after the last release (v2.1.0) which changed the code for Event Dispatcher.
🌟 Additional Changes
- Added support for more slash command support (a.k.a convenience) methods, allowing you to update specific slash commands with Velen and also fetching all slash commands as
Map<Long, String>
orMap<ID, Command Name>
: (View) - Added support for registering specific commands only instead of just registering all commands: (View)
- Added support for getting all the categories that are registered within Velen: (View)
😱 Deprecated Changes
- As we are now moving to
O(1)
for commands, the method:getCommandIgnoreCasing(...)
has been deprecated in favor ofgetCommand(...)
which has the same effect. For now, the deprecated method will proxy itself togetCommand(...)
but we recommend making the change before we remove it on some version.
v2.1.0: Better Command Checking & Argument Extracting (#11)
🔢 What's New?
Another breaking change, all credits goes to Joshix-1 (PR #11)
✨ Changes
- Added improved extraction for arguments (
named arguments
,arguments enclosed in quotes
, etc), examples and demonstrations below:
Example Code
VelenCommand.of("greet", "Want to be greeted?", velen, (event, message, user, a) -> {
Map<String, String> arguments = VelenUtils.parseArgumentArgsArray(a).getLeft();
if(arguments.containsKey("name")) {
message.reply("Hello " + arguments.get("name"));
} else {
message.reply("Hello!");
}
}).attach();
Arguments in enclosed in quotes
Example Code
VelenCommand.of("say", "Tell the bot to say something?", velen, (event, message, user, a) -> {
if(a.length > 0) {
message.reply("Hello " + a[0]);
}
}).attach();
You can view more methods through the VelenUtils
class, for example, startsWithMention
which checks whether the user or bot with the ID is mentioned at the start of the string.
🔥 Breaking Changes
getShortcuts()
onVelenCommand
no longer returnsList<String>
but instead returnsString[]
.
🎉 Credits
Full credits goes to Joshix-1 for this change, thanks! 🎉
Velen 2.0
💙 Velen 2.0
The first major change of Velen, including several major breaking changes that will be discussed.
❤️ What's New?
✨ Minor Changes
- Added interceptors to rate-limiter which means, you can now add your own functions to the rate-limiter that will be added whenever someone gets rate-limited, is released from the rate-limiter or when the user successfully passes the rate-limiter and the command is executed. More details on wiki.
- Added support for modifying prefixes on the database and also on Velen's internal prefix manager through
VelenPrefixManager#setPrefix(serverId, Prefix)
. More details on wiki.
🔥 Minor Breaking Changes
- Methods such as
getOrderedRoleMentions
andgetOrderedChannelMentions
will now returnCollection<Role>
andCollection<Channel>
respectively instead of the originalCollection<Optional<?>>
.
🔥 MAJOR BREAKING CHANGES 🔥
The breaking change that many has been looking for, support for Embed and Normal customizable messages for Rate-limited
, No Permission
, No Role
, Conditions Not Met
events!
All of these customizable messages now follow a certain format with two methods that you can use to customize the message.
Example of Embed Message
Velen velen = Velen.builder()
.setRatelimitedMessage(VelenRatelimitMessage.ofEmbed((remainingSeconds, user, channel, command)
-> new EmbedBuilder()
.setTitle("You are rate-limited!")
.setDescription("You are currently rate-limited for " + remainingSeconds + " seconds!")))
.build();
Example of Ordinary Message
Velen velen = Velen.builder()
.setRatelimitedMessage(VelenRatelimitMessage.ofNormal((remainingSeconds, user, channel, command)
-> "Please wait " + remainingSeconds + " seconds to use this command!"))
Please read the Wiki for a more detailed guide over how to use this.
🗨️ Q&A
Q: What is Ordinary Message
a.k.a Legacy Message
?
A: An Ordinary Message
or Legacy Message
is the original version of the Customizable Messages of Velen, it sends the user an ordinary text message for the events, contrary to Embed Message
which sends an Embed message.