dirigeants / klasa Goto Github PK
View Code? Open in Web Editor NEWA class remix of the Komada Bot Framework
Home Page: https://klasa.js.org
License: MIT License
A class remix of the Komada Bot Framework
Home Page: https://klasa.js.org
License: MIT License
In usage, if I was todo <Command:somerandomthing>
and run the command console would get spammed with unknown argument type and spam till getting a Javascript stack trace (infinite loop) https://github.com/dirigeants/klasa/blob/master/src/lib/structures/CommandMessage.js#L138 basically what happening is this.client.emit('warn', 'Unknown Argument Type encountered'); return this.multiPossibles(++possible, validated);
here it emits warn event then runs the multiPossibles function again causing an infinite loop
The library should not care anything about what the provider is using in the background. This also allows for each sql provider to be more customized to that individual database, rather than trying to find a set of sql syntax/types common to all sql databases. As well as reduction of core code (bloat) and finally massive simplification of SettingGateway.
Potentially add a SQL QueryBuilder Util with overridable defaults, to aid in reduction of duplicate code/making SQL Providers more maintainable.
Branch | Build failing 🚨 |
---|---|
Dependency | eslint |
Current Version | 4.9.0 |
Type | devDependency |
This version is covered by your current version range and after updating it in your project the build failed.
eslint is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.
npm run check-commit
script (#9513) (Teddy Katz).md
to link (for github users) (#9501) (薛定谔的猫)npm run profile
script (fixes #9397) (#9455) (Teddy Katz)The new version differs by 38 commits.
9deb1b1
4.10.0
6d19001
Build: changelog update for 4.10.0
bb6e60a
Fix: Improve the doc for no-restricted-modules rule (fixes #9437) (#9495)
c529de9
Docs: Amend rule document to correct and complete it (refs #6251). (#9498)
f9c6673
Chore: Add tests to cover array and object values and leading commas. (#9502)
9169258
Chore: remove npm run check-commit
script (#9513)
7d390b2
Docs: Revise contributor documentation on issue labels. (#9469)
d80b9d0
Fix: no-var don't fix globals (fixes #9520) (#9525)
b8aa071
Fix: allow linting the empty string from stdin (fixes #9515) (#9517)
350a72c
Chore: regex.test => string.startsWith (#9518)
de0bef4
Chore: remove obsolete eslintbot templates (#9512)
720b6d5
Docs: Update ISSUE_TEMPLATE.md (#9504)
2fa64b7
Fix: should not convert non-consecutive line comments to a single blo… (#9475)
9725146
Fix: multiline-comment-style fix produces invalid code (fixes #9461). (#9463)
b12cff8
Fix: Expected order of jsdoc tags (fixes #9412) (#9451)
There are 38 commits in total.
See the full diff
There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot 🌴
Almost all of the pieces' typings mark certain methods as 'abstract'.
The methods are normally optional, but the 'abstract' marking forces you to implement them.
import { Command } from 'klasa';
import { Client } from '../../structures/Client';
// [ts] Non-abstract class 'default' does not implement inherited abstract member 'disable' from class 'Command'.
export default class extends Command {
constructor(client: Client, dir: string, file: string[]) {
super(client, dir, file, {
aliases: ['details', 'what'],
description: 'Provides some information about this bot.'
});
}
async run(msg) {
return msg.sendMessage(msg.language.get('COMMAND_INFO'));
}
};
No errors; typescripts allows the class.
There are some really good stuff on Klasa that use reactions and paginations and make life a lot more easier and amazing with stuff like RichDisplay and RichMenu.
I was wondering if there was a chance of incorporating something similar for awaitMessages. I use this as an application of sort and was hoping for an awesome way to do this.
it would require parameters like:
an object that shows how many different questions you need to be answered, time for each question, type of response like options which could use reactions etc
Let me know if I am not clear on the suggestion and would like more details I will be happy to elaborate.
By the time HactoberFest begins, RichDisplay and RichMenus should be merged into master. It would be great for someone to write tutorials for using them (like the other docs tutorials you can find in the ./tutorials folder).
The tutorials should include a general overview, basic implementation with explanation of parameters, and creative examples of use. The RichMenu should have it's own tutorial as a child of RichDisplay (RichMenu extends RichDisplay) highlighting the similarities and differences, and it's own examples of use.
Please be sure to create your pull request after the first of October so your pr counts for HactoberFest. More details about HactoberFest
Edit: The RichDisplay Tutorial has been completed, and merged. A RichMenu tutorial is still wanted.
When you have many extendables, for different classes, I bet it gets pretty disorganized. You can prefix their filenames with the class name, e.g., userProfile.js, but then you have to explicitly specify the property/method name in each one.
I'm proposing that subfolders in the ./extendables/
folder be used as the appliesTo arg by default, so that users can then make the filename the name of the property/method, for simplicity and for better organization.
Commands have categories, which are useful for file organization. I propose similar usefulness for extendables.
./extendables/User/profile.js
:
const { Extendable } = require('klasa');
class MyExtendable extends Extendable {
get extend() {
// return whatever
}
}
module.exports = MyExtendable;
A file that uses it:
msg.author.profile // etc.
appliesTo
arg./extendables/User/modLog.js
, with appliesTo: ['Guild']
Currently, we are using constructor to set up the config of a class.
Instead, we could use a method of the class. This will keep the code clean, simpler and more dynamic.
class Parent {
constructor(...args) {
// Do something with it
console.log(args)
}
}
class Children extends Parent {
constructor(...args) {
super(...args, {
command: "ping"
})
}
}
class Children {
constructor(...args) {
let config;
if (typeof this.config === "function") config = this.config();
if (!config) throw Error("You forgot to set the config using the method config");
// Do something with config or just make it available for the methods
this._internalConfig = config;
}
}
class TestChild extends Children {
config() {
return {"command": "ping"}
}
}
To see what happens to your code in Node.js 10, Greenkeeper has created a branch with the following changes:
.travis.yml
package.json
files, so that was left aloneIf you’re interested in upgrading this repo to Node.js 10, you can open a PR with these changes. Please note that this issue is just intended as a friendly reminder and the PR as a possible starting point for getting your code running on Node.js 10.
Greenkeeper has checked the engines
key in any package.json
file, the .nvmrc
file, and the .travis.yml
file, if present.
engines
was only updated if it defined a single version, not a range..nvmrc
was updated to Node.js 10.travis.yml
was only changed if there was a root-level node_js
that didn’t already include Node.js 10, such as node
or lts/*
. In this case, the new version was appended to the list. We didn’t touch job or matrix configurations because these tend to be quite specific and complex, and it’s difficult to infer what the intentions were.For many simpler .travis.yml
configurations, this PR should suffice as-is, but depending on what you’re doing it may require additional work or may not be applicable at all. We’re also aware that you may have good reasons to not update to Node.js 10, which is why this was sent as an issue and not a pull request. Feel free to delete it without comment, I’m a humble robot and won’t feel rejected 🤖
There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot 🌴
If your category has over a certain amount of commands (54 in my case) the default help commands breaks due to not correctly splitting the codeblocks (the .send() catch fires with a wrong message)
show help command correctly
is there a client option that would let the owner set a custom amount of level above 10.
When using commands, they are case insensitive. When using the help command, however, you must use exact case for the command you want help on.
Where the prefix is +
:
+Ping
(Works)
+Help Ping
(It can't find the command...not that it tells you that. It sends you the entire list of commands, but I digress)
I am proposing that the cmd ArgResolver be changed to allow this.
I think this term is very misleading for a property that is only there to prevent an inhibitor to be run for the help command. If we want it configurable for inhibitors to only be run in certain scenarios, this should be more configurable.
I want an easy way to disable individual core commands.
I don't want to have the user-conf
command in my bot. At least not in the near future. There is no nice way to get rid of it, without getting rid of all the other core commands.
Currently I'd need to transfer the command file, then set enabled: false, then maybe move it into a folder called 'Disabled' or something. That is quite annoying, especially if I wanna make the bot open source. I don't want a random folder with some commands that shouldn't be touched.
I want a way to be able to persistently disable individual core commands globally, that'd work with OSS. You could put it into the Client initialization, maybe?
I really hope this is added, as this issue is really annoying me.
Thanks for reading.
With the PR #156 we have implemented Cron, however, we wanted to have a fully functional Cron before pulishing it and implement the rest of features. Currently, we're missing five non-standard wildcards:
Edit: Added Done
column to the wildcard table and a list of commits implementing the new wildcards.
Done | Wildcard | Description |
---|---|---|
- | L |
'L' stands for "last". When used in the day-of-week field, it allows you to specify constructs such as "the last Friday" ("5L") of a given month. In the day-of-month field, it specifies the last day of the month. |
- | W |
The 'W' character is allowed for the day-of-month field. This character is used to specify the weekday (Monday-Friday) nearest the given day. As an example, if you were to specify "15W" as the value for the day-of-month field, the meaning is: "the nearest weekday to the 15th of the month." So, if the 15th is a Saturday, the trigger fires on Friday the 14th. If the 15th is a Sunday, the trigger fires on Monday the 16th. If the 15th is a Tuesday, then it fires on Tuesday the 15th. However, if you specify "1W" as the value for day-of-month, and the 1st is a Saturday, the trigger fires on Monday the 3rd, as it does not 'jump' over the boundary of a month's days. The 'W' character can be specified only when the day-of-month is a single day, not a range or list of days. |
✅ | ? |
In some implementations, used instead of '*' for leaving either day-of-month or day-of-week blank. Other cron implementations substitute "?" with the start-up time of the cron daemon, so that ? ? * * * * would be updated to 25 8 * * * * if cron started-up on 8:25am, and would run at this time every day until restarted again. |
- | # |
'#' is allowed for the day-of-week field, and must be followed by a number between one and five. It allows you to specify constructs such as "the second Friday" of a given month. For example, entering "5#3" in the day-of-week field corresponds to the third Friday of every month. |
✅ | H |
'H' is used in the Jenkins continuous integration system to indicate that a "hashed" value is substituted. Thus instead of '20 * * * *' which means at 20 minutes after the hour every hour, 'H * * * *' indicates that the task is performed every hour at an unspecified but invariant time. This allows spreading out tasks over time. |
From the Wikipedia page.
We also support nonstandard predefined scheduling definitions, however, @yearly
is supported where @annually
isn't. (✅).
4b4a42ad0f
] Fixed the wildcard ?
. (bdistin)692e485d2b
] Implemented the wildcards ?
, H
, and the scheduling definition @annually
. (bdistin)Apparently, on the docs, it shows this for checking the Permission level of a msg.
msg.hasAtleastPermissionLevel(#)
However, when testing this it ends up returning:
0|app | [2017-10-24 19:12:40] TypeError: msg.hasAtleastPermissionLevel is not a function 0|app | [2017-10-24 19:12:40] at module.exports.run (/home/jordan/Sistine/commands/Currency/balance.js:38:31) 0|app | [2017-10-24 19:12:40] at msg.validateArgs.then (/home/jordan/Sistine/monitors/commandHandler.js:66:19) 0|app | [2017-10-24 19:12:40] at <anonymous>
The function ends up working if you capitalize the l in Atleast to AtLeast.
https://dancing.while-at.work/3f4e0f.png
A way to be able to have custom Prefix with regex's aka this.client.config.prefix
could be new RegExp(/!/g)
for example
Currently Provider#getAll wants just the table, and expects to return all the data. That is horrible, because that means you could potentially be fetching thousands of documents for no apparent reason. (not to mention in
klasa/src/lib/settings/Gateway.js
Lines 185 to 198 in 60c8503
This proposal suggests adding an optional array of ids to the getAll functions, where each provider has to handle it manually (most databases have ways of doing this. Mongo has $in, most of sql seems to have select item from table where item.id in (values, here)
, rethink can do filtering, etc.)
async getAll(table, filter = undefined) {
if (util.isArray(filter)) {
// Fetch data based on the filter, where each item in filter is the id
// for instance, assuming we have sql
return this.run(`SELECT * FROM ${table} AS g WHERE g.id IN (${filter.join(",")})`)
}
// Fetch all data like normal
}
This should return all data if no array is provided, or filtered data otherwise. This should NOT have to fetch all data and return the correct one, but should rather integrate with the database's syntax and fetch exactly whats needed at once.
Having a RichDisplay sent in a DM will cause havoc on your logs. The commands work perfectly. The rich display works perfectly. The pages change perfectly. It does everything that it should do but it keeps sending this error to your log for every reaction that clicked. So if a user clicks 2-3 times and you have thousands of users on a popular command it destroys logs.
There should be a way to catch/ignore this error somehow because as I said the command works perfectly. The users have no issues. But the developer logs are insanely spammed.
Uncaught Promise Error:
DiscordAPIError: Cannot execute action on a DM channel
at item.request.gen.end (node_modules/discord.js/src/rest/handlers/RequestHandler.js:79:65)
at then (node_modules/snekfetch/src/index.js:218:21)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:228:7)
1) Create a rich display command to run in a DM
2) Use reactions
3) Check logs
Either a workaround or some sort of method to avoid this log is necessary. The only issue here is with the error log and not the RichDisplay or command. All i really need is a way to ignore this error from my console.
I got multiple recurring tasks that should ran every minute but what happens is that the first task runs then the second ones run in the second minute and in the third minute the third tasks runs, and a loop starts.
Make multiple recurring tasks (mine hapened with the same task) with the cron "* * * * *" (that means that they should run every minute of every hour of every day, etc), after that check how the multiple recurring tasks are executing, for example if you want to do a simple test you could make a task that does console.log("test"), and that should appear n times (n being the amount of recurring tasks you made) in the console but it doesnt.
What should happen is that your console should be filled of "test" but it is not because only one scheduledTask was ran.
☝️ Greenkeeper’s updated Terms of Service will come into effect on April 6th, 2018.
Branch | Build failing 🚨 |
---|---|
Dependency | @types/node |
Current Version | 9.6.0 |
Type | devDependency |
This version is covered by your current version range and after updating it in your project the build failed.
@types/node is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.
There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot 🌴
When Duration#toNow
is used on Date objects or timestamps earlier than Date.now()
, it returns seconds
always.
Date.now()
on the first parameter of Duration#toNow()
Return the actual Duration, returned seconds
instead.
well oops basically https://i.imgur.com/ravkASt.png
when i go to edit a cmd and do the 1st optional argument prompts when it shouldn't
The PR #228 went into stale due to the lack of an objective design and lack of a technical specification for QueryBuilder. This issue will remain opened until the design for QueryBuilder gets fully written, specified and merged into the master branch.
I'm opening this issue as QueryBuilder is part of the v1.0.0 RoadMap and therefore, its design should start taking priority so it can be written, tested and merged before discord.js 12 does, that way we can land the long-awaited Klasa 1.0.0 with discord.js 12 release.
The current (and last written) version of QueryBuilder looked like this:
// Create a QueryBuilder for PostgreSQL
this.qb = new QueryBuilder(this.client, {
// Declare the boolean type, with the datatype name as "BOOL"
// and defaults false and true
BOOLEAN: { name: 'BOOL', default: [false, true] },
// Declare the float type, defaults to 0
FLOAT: { name: 'DOUBLE PRECISION', default: 0 },
// Declare the integer type, defaults to 0
INTEGER: { name: 'INTEGER', default: 0 },
// Declare the text type, defaults to NULL
TEXT: { name: 'TEXT' },
// Declare the varchar type, defaults to NULL, the property of
// size tells QB to use VARCHAR(MAX_LENGTH)
VARCHAR: { name: 'VARCHAR', size: true }
}, {
// When using arrays, PG converts INTEGER to INTEGER[]. So we want
// to append '[]' at the end of the type
arrayWrap: (type) => `${type}[]`
});
However, this design has not been approved by the team. I would also like to open this to everyone who wants to contribute in the design of QueryBuilder (perhaps we can take a look to Sequelize and Knex, and get the best of them for some aspects?).
When you issue the command to disable the message event. It should not let you, but yet it does.
It's simple to fix the problem. All that needs to be done is change Message to message. (See the code below)
// peice.name === 'Message' should actually be piece.name === 'message'
async run(msg, [piece]) {
if ((piece.type === 'event' && piece.name === 'Message') || (piece.type === 'monitor' && piece.name === 'commandHandler')) {
return msg.sendMessage(msg.language.get('COMMAND_DISABLE_WARN'));
}
piece.disable();
return msg.sendCode('diff', msg.language.get('COMMAND_DISABLE', piece.type, piece.name));
}
It is expected to prevent you from disabling the message event handler.
It's actual behavior, disables the message event handler and prevents you from issuing further commands.
An increment method for SG to add/remove numbers from SG Configs.:
// Increment by 1
this.client.configs.increment('commandsUsed', 1);
// Decrement by 1
this.client.configs.increment('commandsUsed', -1);
Current Method of doing this:
// Increment by 1
this.client.configs.update('commandsUsed', this.client.configs.commandsUsed + 1);
// Decrement by 1
this.client.configs.update('commandsUsed', this.client.configs.commandsUsed - 1);
Databases have built-in methods for incrementing which might help in implementing this in providers. MongoDB
RethinkDB
Benefits: Shorter and simpler. Perhaps faster?
Use cases: experience systems, analytics and counters.
I've noticed this bug where if u let a command prompt for 30 seconds it would return [object Map]
https://i.imgur.com/N4urwsW.gif that gif shows you what I mean, I'm guessing the issue is you're awaiting messages with no error handling
With the fix of #147 it led to a new issue where the reaction needs to be tapped twice. I believe it occurs because now there is no way to remove the reaction automatically so you have to a) remove b) add new reaction.
EDIT: Oops sorry I wasn't saying the fix caused it just revealed that it needs 2. Even before the fix this issue occurred because the bot couldn't remove the reactions so they still had to click twice. This fix simply revealed this issue more to me.
1) Create a richdisplay to run in DM
2) run the command and go to page 2
3) try to go to page 3 but it wont
4) click again and it will go to page 3
The RichDisplay when it lacks perms to remove reactions could work when the user removes a reaction to move to next page
Usage with prefix !
!blacklist @stitch#9441
Blacklists me. Instead, it says "guildID must be between 17 and 19 characters.
It isn't a huge breaking bug, but something I thought worth mentioning. Honestly, i am not even sure if this is something that can even be fixed.
Typings automatically begin saying BOTNAME is typing...
however, it does not take into consideration where the bot is sending the message. For example, if someone runs a command in a channel the bot will say the typings BUT that command actually sends a message in another channel. Its confusing as it seems to cause users to think the bot has broke until they realize oh the message came here.
P.S. This is not breaking just something to make it less inconvenient in those rare circumstances.
1) Enable Typings
2) Run a command that sends a message to different channel
Typings should occur on the channel where the bot types.
Having SchemaPiece on a SchemaFolder breaks conf get
when trying to access the folder, conf get SchemaFolder#SchemaPiece
will work just as fine.
type
as TextChannel
conf get <SchemaFolder>
Branch | Build failing 🚨 |
---|---|
Dependency |
markdownlint-cli
|
Current Version | 0.8.1 |
Type | devDependency |
This version is covered by your current version range and after updating it in your project the build failed.
markdownlint-cli is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.
The new version differs by 4 commits.
081d1f2
Bump version 0.8.2
d9f6bf6
Merge pull request #37 from mroderick/patch-1
ce3f44d
Fix #36: Update deep-extend and rc
f847068
Move output of --output tests outside test directory to avoid race condition in tests (fixes #34).
See the full diff
There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot 🌴
At the moment we have absolutely no control about the order the inhibitors are run in. And for some ideas there is the scenario needed to run one inhibitor before another and to stop the the whole process
(to not run the other inhibitors following)
The implementation of Command#cooldown is very effective, and it got enhanced thanks to Command#bucket allowed developers to have a better control of them without annoyingly set ratelimits at first command usage and disturb the user.
However, the underlying system feels incomplete and not very performant.
It uses a timeout for every single cooldown, this is separated in multiple commands, so both RAM and CPU usage seems to be affected by this. In practice, the excessive amount of timeouts seems to make other shift even a bit. This could be fixed with a cooldown sweeper using an interval, similar to Schedule's system.
It's not very effective: if a user spams a command, they should be notified only once, however, Klasa will reply as many times as it can. Some developers (me, included) use ratelimits to protect the bot from, not only heavy processing or limit the usage of commands, but also to protect the bot against breaking Discord ratelimits. That is, due to the lack of silent ratelimits.
Finally, there's an extreme side case that has been affecting my bot today: it's cool to put the ratelimits after a successful command run, however, there are commands (such the ones that send files or generates images) that take a while longer. These commands take more to resolve, therefore, they also take longer to fire the finalizers that put the user in cooldown. For example, I have a command that takes ~1 second to process an image and send it to Discord, the command has a cooldown of 30 seconds with a bucket of 1. A user sends 5 messages within that second.
Expected behavior: Run one, ratelimit the second, ignore the other three (with this proposal).
Actual behavior: As cooldowns aren't applied until the first successful command run, the bot does run all 5 commands.
When KlasaClientOptions.cmdEditing is set to true and command prompt are enabled (formerly known as KlasaClientOptions.cmdPrompt
before the refactor), Klasa identifies message edits as new messages, therefore, prompts will identify command edits as the response (which is unwanted most of the time).
Proposal: To fix this issue, we should check if the message received is the same as the one that triggered the prompt. In that case, return an invalid value (i.e. null). As throwing will be (in most cases) identified as the lack of a response. This will be handled by the developer (a notice should be made in the documentation via the JSDoc).
If the message is edited during Usage's prompt, Klasa should cancel the current command execution and re-parse it. That way, when you do:
s!conf set prefix
You'll be prompted by Usage asking for the value to set. And then you edit it to:
s!conf set prefix m!
That'll identify s!conf set prefix m!
as the accepted value, in this case, making that the new prefix (in practice this will error as there's a maximum number of characters in the schema) and will run the same command but with m!
as the value. This is pretty dangerous in some cases as, related to #180, ratelimits aren't applied during command parsing but after successful command run, so you could call the command multiple times with the prompt and edit them later, causing a fatal issue.
To counter this issue, I propose prompt cancellation when the captured message in Message#prompt()
is the same one as the message that called the prompt.
We can agree that usage strings are very cool, very easy to use, very clean and readable, compared to other systems implemented in other frameworks with are, for example, an array of objects that lately face the issue of union
type, something easy to write thanks to the usage string. However, as easy as it is, the usage string has one weakness that we can't address in the current way, for that, I have multiple proposals.
This is @MrJacz's proposal, an array typeof Array<string | (msg: KlasaMessage) => string
. This is the easiest way to address this issue as it's another property for CommandOptions
: usagePrompt
. It's usage would come to be something similar to:
{
usage: '<battletag:string> [bronze|silver|gold|platinum]',
usageDelim: ' ',
usagePrompt: [
'Give me a battletag formatted as username#0000',
'Give me a rank name, can be bronze, silver, gold or platinum, pick the one that is next to your rank.'
]
}
However, it's lineal and to do so you may need to pass empty values or undefined in the middle of the array, to address that, it's possible to have a class do that:
{
usage: '<battletag:string> [bronze|silver|gold|platinum]',
usageDelim: ' ',
usagePrompt: new UsagePrompt()
.addPrompt(1,
'Give me a rank name, can be bronze, silver, gold or platinum, pick the one that is next to your rank.')
}
Where 0
, being <battletag:string>
, would use the default message (battletag is a required argument
).
However, it may be confusing, may it start with zero? Or maybe with one? To address this issue, we could make CommandOptions.usage
accept more types: not just string
.
{
usage: new ArgumentUsage()
.addParameter('battletag', /(\w{4,12})#(\d{4,5})/, true,
'Give me a valid BattleTag, should be formatted like someuser#0000')
.addParameter('rank', 'bronze|silver|gold|platinum', false,
'Give me a rank name, can be bronze, silver, gold or platinum, pick the one that is next to your rank.'),
usageDelim: ' '
}
Where ArgumentUsage
is a class that compiles directly to ParsedUsage
and has a .toString()
method to compile to usageString
(used in the help command, for example). The reason this would compile to ParseUsage
is so it's able to add the new properties to the possibles: promptMessage
being either a string or callback (msg: KlasaMessage) => string
.
The Argument#addParameter
option is very powerful as it doesn't only add one more feature to Usage, which is prompt, but it also adds two more (nice) features: the possibility to have raw RegExp to use as regexp type (I'll be honest, I haven't figured the RegExp type since it got released, it's very complicated inside usageString, if this gets merged, the usage of the RegExp
type in Klasa will be significantly easier) or even a custom type. Of course, this part of the concept can change, and name would be... perhaps custom
or allow a fifth parameter which is parameter name for usageString. This can be reviewed later.
Furthermore, stringifying a RegExp for usageString is relatively easy, RegExp#toString()
does that.
This method would also support strings as legacy and would allow union type. Of course, this could use the current usageString parser, covering the downsides of the systems that are not based in quotedString.
The design of this method is inspired on PermissionLevels to keep the design of the framework and its core pieces.
EDIT: Stringifying an ArgumentUsage
instance would be as easy as mapping all the entries and write argName:typeName/typeParam
then wrap with <
and >
or [
and ]
depending on whether the value of the second parameter is true or false.
class ArgumentUsage {
public constructor();
private _entries: object[];
public addParameter(
argName: string,
type: string | RegExp | (msg: KlasaMessage, arg: string) => string,
required: boolean,
promptMessage?: string | (msg: KlasaMessage) => string,
typeName?: string): this;
public toJSON(): object;
public toString(): string;
}
EDIT 2: ArgumentUsage
is not meant to replace the former usageString
, but to complement as a more advanced tool that opens the gates for more creativity, implementing better debugging (IntelliSense, separation of the "parts" of each Tag, custom types, better RegExp readability...) and the possibilities to reach where usageString
can't reach while also using the parser for the aforementioned to cover the issues this kind of system has in other frameworks (lack of union type as an example).
This is more than just an enhanced usage, this allows better debugging, better internationalization, custom messages/prompts (feature highly requested over almost half a year) and improves user friendly-ness towards users.
None.
in usage strings, you can currently only have optional or required flags in usage but what I mean is having a string in a usage like <reminder:string> in <Time:time>
so the command format would be prefix remind me to bug ao about this proposal in 1 hour
just like Skyra's reminder command
usage: "<reminder:string> in <time:time>"
The command to throw some string if in
the literal string isn't there this could also be wrapped in <in>
or [in]
making it required or optional
The Message#reply method would be more useful if it supported command editing, like KlasaMessage#send, et. al., do. I am proposing that Klasa replaces that method with its own.
Error when trying to update a SG config of type 'any' with an object.
TypeError: Cannot set property 'test' of null
Get a raw app.js, only changing the token value - or skip to Step 4 if you have an unmodified bot running the latest klasa/d.js master that you can test on.
Install Klasa, Discord Master:
Run the bot.
Add a key to your schema of type any
:
+eval this.client.gateways.users.schema.add("test", { type: "any" })
test
key, with an Object
value.+eval msg.author.configs.update("test", { test: 'test' });
Object
value in the test
key of the users config.+eval msg.author.configs.reset("test");
test
key, with an Object
value.+eval msg.author.configs.update("test", { test: 'test' });
TypeError: Cannot set property 'test' of null
. If the error doesn't appear, try rebooting the bot and trying it again.The test
key in the users' configs should be updated with the Object value.
The docs are still far from perfect, and we would like feedback from our developers to help us improving them before Klasa 1.0.0 release.
Between the issues we could notice:
When quotedStringSupport
is set to true and a command uses a usageDelim that is not a space, commands with the repeator tag do not work correctly. (Tested with user type).
Klasa would get all users and send an array of users.
When I input one user, it works perfectly, but it fails with two or more.
> $test 383383927575937034, 242043489611808769
Error: person must be a mention or valid user id.
> $test "383383927575937034" "242043489611808769"
Error: person must be a mention or valid user id.
> $test "383383927575937034", "242043489611808769"
Error: person must be a mention or valid user id.
const { Command } = require('klasa');
module.exports = class extends Command {
constructor(...args) {
super(...args, { usage: '<person:user> [...]', usageDelim: ', ' });
}
run(msg, [...user]) {
return msg.send(`Mentioned: ${user.map(us => us.tag).join(', ')}`);
}
};
When quotedStringSupport
is set to false, it does parse the ids correctly.
as the title already says the cmdDeletion doesn't work anymore after the cmdEditing rewrite.
const { Client } = require('klasa');
new Client({
prefix: '+',
cmdDeleting: true,
readyMessage: (client) => `Successfully initialized. Ready to serve ${client.guilds.size} guilds.`
}).login('your-bot-token');
Delete the message if invoke message is deleted
For a long time, we have depended of the moment package, however, its i18n support is not used, as well as it is a bit hard to use, check the reference here. We could do two things:
1.- Remove moment as a dependency and make our own one, this would be very similar to what we did with chalk before (thanks to Faith), and we could get rid of many weird issues when using moment-duration-format
. Then, our implementation could be more efficient with the latest V8 changes and easier to use.
2.- Modify our usage of moment so it's multilanguage. (It is used in the stats command to show how long has a bot been running for).
klasa/src/commands/System/stats.js
Line 16 in 12616ee
Since SGv1, in the PR #255 from Komada, we had the first implementation of SchemaPiece
being able to store more than a single value of the same type (instead of being type array, from the former configuration system).
However, this system is extremely old and should be renamed and refactored into something much better, in this proposal, I'll use SchemaPiece#multiValue
as a placeholder for a better name.
What does SchemaPiece#multiValue
do compared to SchemaPiece#array
? The current name limits the options, the values may be contained inside an array or not, but, what if I want to use Set
or Map
? The current system does not allow it, but multiValue will.
There are multiple ways to achieve this, but I'll present two in this proposal:
This is more versatile, it allows custom types and moves some of the heavy work from SG to them, it also allows users to implement their own ValueController
, for example, one being Collection
extending Map
and so on. Compatibility with string
for simplicity in SchemaFolderAddOptions
is accepted with a later resolve.
Said ValueController
would implement basic methods such as create
, clone
, add
, remove
and modify
and they could be stored in GatewayDriver
together with the available key types.
This is less customizable and more hardcoded, plus makes SettingGateway's internals much heavier. These methods would be integrated in a different file (similar to a util) for later usage.
In both options, you'll be able to do
SchemaFolder#add('tags', { type: 'string', multiValue: 'Map' });
And the new values will be stored in the Map. However, some of the multiValue may not be able to be directly configurable, so they'll have the same behavior as type: 'any'
: sets SchemaPiece#configurable
to false.
This proposal is not merging on #179 but in a later one.
Hi,
I've just spotted a little missing parenthesis ')' into the UnderstandingPermissionLevel tutorial.
On the second example (the one showing how to override the defaultPermissionLevels).
Not sure if it's useful but I made a fix here:
#34
Branch | Build failing 🚨 |
---|---|
Dependency | typescript |
Current Version | 2.5.2 |
Type | devDependency |
This version is covered by your current version range and after updating it in your project the build failed.
As typescript is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.
I recommend you give this issue a high priority. I’m sure you can resolve this 💪
This release include a set of bug fixes reported against TypeScript 2.5.2. For the complete list of fixed issues, check out the fixed issues query for TypeScript 2.5.3.
Download:
The new version differs by 51 commits.
94b4f8b
Update LKG
aa40be6
Merge pull request #18673 from RyanCavanaugh/port18603
6281b05
Report external files in initial case
5538770
Look at correct 'package.json' location for a scoped package (#18580) (#18651)
acfd670
Merge pull request #18617 from amcasey/NoModifiers25
9630c46
JavaScript: handle lack of modifiers on extracted method
7b5247f
Merge pull request #18605 from RyanCavanaugh/portExternalFilesFixes
6ed9bad
Port plugin fixes from master
e9a9d2c
Merge pull request #18518 from amcasey/ExtractMethodFixes25
27bede8
Stop requiring that the full range of a declaration fall within the
f0b7843
Merge pull request #18508 from amcasey/ExtractSingleToken
063e8a7
Merge pull request #18427 from amcasey/GH17869
fbb6cd5
Merge pull request #18448 from amcasey/NestedReturn
a667b04
Merge pull request #18423 from amcasey/GH18188
334125e
Merge pull request #18343 from amcasey/InsertionPosition
There are 51 commits in total.
See the full diff
There is a collection of frequently asked questions and of course you may always ask my humans.
Your Greenkeeper Bot 🌴
A client option which would let the user define more than the typical 10 permission levels cap.
Branch | Build failing 🚨 |
---|---|
Dependency | @types/node |
Current Version | 9.3.0 |
Type | devDependency |
This version is covered by your current version range and after updating it in your project the build failed.
@types/node is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.
There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot 🌴
Use the built-in help command on iOS
To fix: Add newline before starting the codeblock
Additional: Remove blank newline at end of codeblocks
Currently, changing the colors for the KlasaConsole is, tedious. With code like this
new Client({
console: {
colors: {
[event]: {
time: {
background: "green",
},
},
},
},
});
looking quite bad.
This proposal is a way to either re-use the already existing Colors class, or another class, to be able to do something more like
new Client({
console: {
colors: {
[event]: {
time: new Colors({ background: "green", text: "white", style: "underline" }),
message: new Colors({ background: "white", text: "black" }),
},
},
},
});
This looks way cleaner, and more concise in my opinion., and doesn't go extremely deep in the client options. (something eslint will appreciate if you have the depth rule configured.)
In the given example, [event]
is an actual event name, like log
or warn
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.