vhoyon / vramework Goto Github PK
View Code? Open in Web Editor NEWFramework that we built on top of DV8FromTheWorld's JDA to ease Java Discord Bot creation
License: MIT License
Framework that we built on top of DV8FromTheWorld's JDA to ease Java Discord Bot creation
License: MIT License
@V-ed commented on Tue Sep 11 2018
https://cloud.google.com/translate/docs/translating-text#translate_translate_text-java
https://github.com/GoogleCloudPlatform/google-cloud-java
I'm not sure about untranslated bot string though, as it would require the use of another method for language which wouldn't make sense as untranslated strings in our program is purely due to lazyness or framework un-abstraction.
@V-ed commented on Fri Aug 24 2018
Vhoyon/Discord-Bot#150 (comment)
This really makes me want to implement a way to know when the logger logs an error, to get the line number & class where the log call was made...
https://stackoverflow.com/a/31128774
@V-ed commented on Mon Sep 17 2018
There would be three different cases :
We could re-use the same logic that was implemented for preventing content from being added, but this time, only checking those who are marked as "need content" and throw an exception when a option marked as such has no content.
Instead of re-using though, we may want to tweak the methods implemented in #119 to create "Policies" : it could be an Enum that tells which behavior should be implemented, thus giving a more meaningful name than simply true
or false
.
The OptionHelp
object would require a little tweaking too, but instead of using those policies, it uses a Boolean
object in which the latter implies the policies :
1
above;false
would mean the option 2
;true
would mean the option 3
.This way, we wouldn't need to check if the option is content-less everytime and handling it manually : it could be generalized in the router and tell the user that "the option -[option]
needs content, try again with content!".
https://axelfontaine.com/blog/optional-dependencies.html
It is optional to use ClassGraph to load the classes from a package - you can always do it manually. Therefore, it would be better to load ClassGraph by default (assume the user wanted to use the package - discovery feature of our framework), but allow him to not load it if undesired. Therefore, if ClassGraph gets excluded but there is an attempt to use the method to load classes via the package, give an error to the user saying that to use this functionnality, ClassGraph needs to not be excluded in the POM.
Some documentation will be required to explain that you will be able to remove ClassGraph if you don't need it.
As Maven is a pERfeCt program, we probably won't be using the <optional>true</optional>
tag, but rather use <exclusions>
.
@V-ed commented on Tue Jun 19 2018
This addition would be located here :
https://github.com/Vhoyon/Discord-Bot/blob/310631a590d9e8268d26c10f8c3a8f38faa2f74c/framework/vendor/interfaces/LinkableCommand.java#L84-L86
and will take the same logic parameters descriptions uses to show itself, here :
https://github.com/Vhoyon/Discord-Bot/blob/310631a590d9e8268d26c10f8c3a8f38faa2f74c/framework/vendor/interfaces/LinkableCommand.java#L56-L82
Here is an example of what I expect when typing !!help setting
:
[[textHeader ("Usage : !!setting")]]
[command description]
[[textWhenParametersAvailable ("Available parameters :")]]
- [param1] : [paramDesc1]
- [param2] : [paramDesc2]
[[textWhenAlternativesAvailable ("Alternative calls :")]]
- [atl1]
- [alt2]
@V-ed commented on Wed Aug 29 2018
This could give our bot an advantage above other bots, but at the same time is not a huge advantage and would require quite alot of engineering to make this work (dynamic checks for parameter linkages...).
I'm not saying it's impossible - I just don't want to put time on it if we will literally never use it.
This new class would allow a bridge between the Buffer and the in-development Database features, allowing a quicker access via the Buffer yet still saving to the Database in the end.
The basic premise would be that the Cache would check the buffer for the wanted data, and if not found, fetch it from the Database and put it in the buffer.
After any retrieval from the Cache, a time would be set to clear the buffer of that data and save it to the database. This timer delay would be statically configurable to allow for a different need (bigger RAM = bigger timeout in the buffer). This timer could also be managed by our TimerManager.
As we advertise that our framework handles setting, we should also provide the ability to easily create a settings command with an abstract interface to deal with settings.
Since dealing with settings may mean more than simply setting a value, we would need to handle callbacks and deal with langs too.
This is the command currently implemented in our own bot, which we would port in here :
https://github.com/Vhoyon/Discord-Bot/blob/69256eb4df14005eb09f06fea60ac7a3e7f0bd2c/src/main/java/io/github/vhoyon/bot/commands/CommandSetting.java
I tested and it appears that hot-reload doesn't work anymore on Command classes because they are loaded into a stream that isn't closed.
It is probably a bug within ClassGraph itself, because we are using a try-with-resources block, which shouldn't keep open streams alive.
Keep in mind that classes are loaded with ClassGraph after the first command (in Discord mind you) that is being caught (that should actually be done once on start, may need a future improvement on that side).
Hot-reload does work when we use Links/Classes directly in the CommandLinksContainer constructor, which thoses does not use ClassGraph.
The routing mechanism is probably one of the most important aspect of this framework, having the ability to route the message to the correct class and execute the required actions, despite multiple conditions (is the command already running? is the message formatted correctly? is there a command that needs confirmation?)... yet we let the end users implement this routing mechanism.
It's not so bad on our own project, since we already implemented it, but a default implementation with possible customizations would be a huge step forward for first timers.
Should we make some sort of interface with many events, and a default implementation that actually implements all of those events?
However this is implemented, it would heavily follow something like https://github.com/Vhoyon/Discord-Bot/blob/3f21717dfbaf6456fd5bc26211ebd2ee1a664446/src/main/java/io/github/vhoyon/bot/app/CommandRouter.java#L53-L182
It's already possible to do so via conditions in the action method of a command, but is relatively bulky to use conditions to tests possible permissions every single time (and then deal with error messages).
A great example would be to allow a command to define one or many role(s) so that only those roles will be available to run that command.
A method such as String[] whitelistedRoles()
would be available to override (defaults to null
, so no restrictions) and when overriden with an array of role(s) name(s), those roles would be used to filter out users that has no permission automatically with a message that defaults to Sorry, you do not have the permission(s) to run the [command name] command!
, which would be customizable somewhere, probably in the CommandRouter class.
All of this should also be done statically too to allow for usage in places where the context may not be directly given, such as in the MessageListener classes.
Vhoyon/Discord-Bot#109 (comment)
Seems like you wanted to call the lang line
SongByStringFail
here, but forgot to wrap your string with alang("SongByStringFail")
.This makes me realize we should probably have a method like
sendMessageFromLang(String langKey)
, this would help in cases like this one where we only need to send the string through a message without formatting... I'll create an issue for that! :D
@V-ed commented on Mon Jul 30 2018
This is after the support from #2 will be added.
copied from Vhoyon/Discord-Bot#30 (comment)
TODO :
Track the message ID of the form in the buffer for the TextChannel and the available options.
A ReactOption
object could be created to track what option is what and what has been selected. This could be part of a ReactMessage
where the id of the message would be stored (the first line of this comment).
I imagine something like this :
public class ReactMessage {
public ReactMessage(String messageId, ReactOption... options){
[...]
}
}
and this for the ReactOption
:
public class ReactOption {
public ReactOption(String emoji, int countBeforeChosen){
[...]
}
}
@V-ed commented on Fri Aug 03 2018
This ReactBuilder could also handle the behavior of what happens to the other reactions when one has been successfully chosen :
- Should the choices from the bot be deleted? [DEFAULT]
- Should all of them be deleted (if the permissions are even good enough for that)?
- Should it do nothing?
@V-ed commented on Sun Jul 29 2018
This would be useful for reactions based forms that no default emoji can provide an easy to understand action for, for example.
Basically this would let devs use images as emojis (as supported by Discord) but provide an easy way for their bot to use it.
@V-ed commented on Fri Aug 31 2018
A simple message in the lines of Hi @[username], I'm [Bot's Nickname]! Enter \help to know more about the available commands, or type \help [command] to get the help of a command in particular!
would be neat.
This would help identify the current prefix in case where the latter was changed in a text-channel - there would be no other way to know the prefix otherwise as it can be anything really.
This would be in the form of a new interface (kind of like the Hidden
interface) which would not have any default set, but rather defines a method used to check if the command needs to be hidden or not.
This would allow a command to be available under only certain conditions, and when this condition isn't met, it was like if the command doesn't exists.
@V-ed commented on Tue May 15 2018
Currently, we parse only the messages that starts with the Resources.PREFIX
string (!!
), but allowing to parse messages that don't belong to this ruleset could help for commands that filters normal messages (a good example would be issue Vhoyon/Discord-Bot#57).
@V-ed commented on Fri Sep 21 2018
https://stackoverflow.com/a/29918826
We could use the library mentioned in this SO answer to run the actions of writing to a file with higher privileges if it can't in normal mode.
Our bot would ask if we want to try to create the file using higher privileges and would remember the decision taken (to prevent having to confirm every time a command in inputted, which could be alot..).
There would be only two options for that confirmation : Yes or No.
@V-ed commented on Thu Jun 21 2018
This could be heavily inspired by Laravel's Localization utility (https://laravel.com/docs/5.6/localization#retrieving-translation-strings) :
AppleCount=[0] There are none|[1,19] There are some|[20,*] There are many
A new method to get those types of lines would be added to the Translatable and Dictionary objects : langAmount()
.
This langAmount
method would take some parameters :
/**
@param key Key of the lang to map from the lang() method.
@param amount Integer telling the amount of objects there is - used to determine which portion of the lang to pick from the list.
@param replacements Variable amount of replacements to replace text in the line found.
*/
String langAmount(String key, int amount, String... replacements)
This way, to further the example above, trying to access AppleCount
would be like so :
String appleText = langAmount("AppleCount", list.size());
Another example would be this string :
VariableCounter=[0] There is no variable here!|[1] There is only 1 variable here...|[2,20] There are {0} variables here!|[21,*] There is too many variables in here, the maximum accepted is 20!
Accessed this way :
String variableCountText = langAmount("VariableCounter", variables.size(), variable.size());
In that example, if the number of variable is between 2 and 20, it will actually show the number of variables in the formatted text, and that in different languages if wanted!
int size;
size = 4;
String variableCountText = langAmount("VariableCounter", size, size);
// variableCountText = "There are 4 variables here!"
size = 1;
String variableCountText = langAmount("VariableCounter", size, size);
// variableCountText = "There is only 1 variable here..."
size = 24;
String variableCountText = langAmount("VariableCounter", size, size);
// variableCountText = "There is too many variables in here, the maximum accepted is 20!"
We could throw a custom NumberOutOfRangeException
(that extends IndexOutOfBoundsException
) if the number is not between the range the line allowed :
int size = -2;
String variableCountText = langAmount("VariableCounter", size, size);
// throws NumberOutOfRangeException
@V-ed commented on Tue Jul 31 2018
I started thinking about how this will be implemented and came up with an object to handle lang lines :
https://gist.github.com/V-ed/ffa57aec6bf646d2749a03a01c21d265
This code is not meant to be used in our Bot yet, but might be used as a template later on. This was just a proof of concept that such string could be handled by an object automatically.
This gist also doesn't include an idea I had while doing the code snippet : a LangAmountManager that would keep track of which range is used, which is available, handle different formats automatically, etc.
I'll say it again just in case : Please do not use this gist as-is, as it is not optimized, not entirely functionnal (works on a perfect scenario but as no error handling, etc) and repeats code.
Here's a quick and dirty implementation example to get you started :
public final class TimerManager {
private static HashMap<String, Thread> timers;
private TimerManager(){}
/**
* @param timerName Name of the timer
* @param delay Delay (in milliseconds) before doing the action
* @param action Action to do after the delay was finished, without being called again, which resets the delay
*/
public static void manage(final String timerName, final int delay, Runnable action){
if(timers == null)
timers = new HashMap<>();
stopTimer(timerName);
Thread timerThread = new Thread(() -> {
try{
Thread.currentThread().sleep(delay);
action.run();
}
catch(InterruptedException e){}
finally{
timers.remove(timerName);
}
});
timers.put(timerName, timerThread);
timerThread.start();
}
public static void stopTimer(String timerName){
if(timers.containsKey(timerName))
timers.get(timerName).interrupt();
}
}
The implementation in our bot is generic enough to be applied by every project by default, while allowing the override if wanted.
Porting this to our framework would let a first timer do less on initial setup.
Also, this would be backward compatible, as we're not changing the core functionnality, simply providing a default implementation - of course projects who already override it won't see a change, but they could always remove it if they don't need a custom implementation anymore!
@V-ed commented on Thu Jul 19 2018
For example, different types of parameters would be separated by a new line on the developer's request.
@V-ed commented on Wed Aug 15 2018
There would be a property that tells AbstractBotCommand
that this [Bot] is typing...
should be shown or not when starting a command.
https://github.com/classgraph/classgraph
<dependency>
<groupId>io.github.lukehutch</groupId>
<artifactId>fast-classpath-scanner</artifactId>
<version>2.19.0</version>
</dependency>
This depency is very old and should be changed to this :
<dependency>
<groupId>io.github.classgraph</groupId>
<artifactId>classgraph</artifactId>
<version>LATEST</version>
</dependency>
(note that LATEST
should be changed to an actual version, such as 4.2.9
, the latest version as I'm writing this issue)
This wiki on porting FastClasspathScanner to ClassGraph might be useful
Currently, the Buffer
class simply uses its own static variable to get the data from memory.
It would be interesting to actually add a way to store data to other places easily (such as a database) via a BufferImplementation
abstract object, for example.
The default would be via a static variable, like the current implementation, but this implementation would be tweakable if desired.
@V-ed commented on Sat Aug 18 2018
My initial though is to make an interface Hideable
and a condition to the getFullHelp
method that tests if the command is Hideable or not.
Edit : Hideable
or Hidden
?
public class CommandTest extends BotCommand implements Hideable {
public class CommandTest extends BotCommand implements Hidden {
As the owner of the Request object, I'll create a repo under my account and add it to the v-ed.github.io
maven repository.
My plan is to make an utility that very closely resembles Apache's Common Cli but allow the usage of a full String too with command handling (and not just Options handling).
One of the plan of this transition is also to change everything "Parameter" in the Request class to be "Option", a shorter, more expressive term that Apache also uses.
@V-ed commented on Sun Apr 15 2018
This could make for some interesting behaviors such as visual confirmation (see example below) or voting!
Just some explanations for that example : The bot could send a message with default reactions (choices) of which the user would add a reaction (by clicking on the reaction he wants) to input his choice.
In other words, this would enable a new interaction method with the bot, which is always useful.
@V-ed commented on Mon Jul 30 2018
EDIT : This behavior of creating ReactForms easily is tracked in #124.
TODO :
Track the message ID of the form in the buffer for the TextChannel and the available options.
A ReactOption
object could be created to track what option is what and what has been selected. This could be part of a ReactMessage
where the id of the message would be stored (the first line of this comment).
I imagine something like this :
public class ReactMessage {
public ReactMessage(String messageId, ReactOption... options){
[...]
}
}
and this for the ReactOption
:
public class ReactOption {
public ReactOption(String emoji, int countBeforeChosen){
[...]
}
}
@V-ed commented on Thu Aug 09 2018
My initial take on this would be this :
true
;Module
s placed in /app.modules.auto.*
using ClassGraph.Racer
), it would load it in the default directory (/app.modules.*
);
test.Racer
would search for /app.modules.test.Racer.java
./
(ex. : /app.animations.Racer
), it would load the module from the full path provided.All of this loading will need to have a class extending Module
or its children. We wouldn't load classes just like that, we need to build modules.
We would of course need to also update everything that handles options so that it won't break our own framework.
This change would be backward incompatible, as it would change the core functionnality of Options in our Framework. But, in the end, it will be better as it will bring some coherence between our own methods (getAliases()
switched to returning a List
a while ago...)
@V-ed commented on Sun Apr 01 2018
Embedded messages are messages shown in a framed windows, such as the youtube video thumbnail preview / player.
Embedded messages could be useful, for example, for the Music command when showing who added this or that music to the playlist, show a seeking bar, etc.
@V-ed commented on Thu Aug 30 2018
Vhoyon/Discord-Bot#162 (comment)
Now, the hardest part will be what happens to confirmation messages and successfull action messages...
After discussing with @StephanoMehawej, we thought about the concept of parameters "weight" which, when added up, would give an unique identifier (so that we could easily know when parameter A was used with parameter B, for exemple).
This "weight" would be attributed with the 2โฟ notation such that any entry would yield unique additionnal value.
Now, it's just a matter of how to know which parameter is weighted more :
- Via the order of their parameter help definitions?
- Via a parameter in the parameter help constructor?
- ... both?
- like, if there's no constructor, do it automatically, and if one of the parameterhelp provides an "weight index", then set its weight and organize other around this value...
@V-ed commented on Mon Sep 10 2018
Idea : The default weight when creating the Request's Parameters would be 0
(aka not handled) and there would be a method that sets the weight based on the parameter's name. Example : setParameterImportance(String parameterName, int importance)
and setParametersImportances(HashMap<String, int> importances)
(for this one, the String is the name of the parameter, and the int is the importance).
The importance would be determined by a simple 1, 2, 3, 4, etc count, and there would be magic under the hood that sets the weights appropriately.
@V-ed commented on Fri Aug 24 2018
For example, we have no option bound to adgjahgd
in our CommandHello
command, yet we currently let it silently pass through because we never use such option.
It would be great to have the option to add in an environment variable the ability to prevent actions if bad parameters are in the query for a command, so such interactions would happen :
V-ed > \hello --dhawkjdh
Bot > X The option `dhawkjdh` is not recognized. Use `\help hello` to see the list of available options!
I imagine 3 options available :
One possible issue with this is that it assumes that there is a "help" command available. Should we make an Generic help
command available to anyone using this framework?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.