nandertga / msgroom-orm Goto Github PK
View Code? Open in Web Editor NEWA MsgRoom client.
Home Page: https://nandertga.github.io/msgroom-orm/
License: MIT License
A MsgRoom client.
Home Page: https://nandertga.github.io/msgroom-orm/
License: MIT License
// let's say we want to define pong, an alias for ping
client.commands.pong = {
alias: true,
original: client.commands.ping,
originalName: "ping",
}
// let's say we want to define pong, an alias for otherCommand.ping
client.commands.pong = {
alias: true,
original: client.commands.otherCommand.ping,
originalName: "otherCommand.ping",
}
Like this we can hide aliases from the help command.
With a say
command, there's always the issue of someone doing !say !say !say !say !say !say !say !say !say
and rate limiting the bot. This would be solved if the bot automatically didn't respond to itself.
A problem: It would need to somehow know if it is itself, or just its creator with the same ID.
That name would be shorter and is more applicable since I changed it to be a map of Command
s instead of just CommandHandler
s
When trying to help someone on msgroom called \u202e yesterday (actually he uses that unicode character as his name, but everyone refers to him by that name because it's an invisible character), I found out it's a pain to get a nightly build from the repository.
I configured the project in package.json to only include the dist/ folder (the readme, license and package.json are included too by npm).
This causes npm to only fetch those things from the repository when telling it to do so.
Because of this npm won't download the src/ folder, nor the dist/ folder (it doesn't exist on the repo) and you have to manually clone the repository, rename the cloned folder from msgroom-orm
to msgroom
and run npm install
and npm run build
.
This is very annoying and I don't want to remove the above setting, because I want to save space.
I'm working on a new github actions workflow to automatically test and run npm pack on every commit, and to also publish the result at a new package called msgroom-nightly
.
The version naming scheme will go as follows:
-(full git sha here)
(the dash makes it a prerelease)This will result in something like this: 2.0.0-ffac537e6cbbf934b08745a378932722df287a53
This won't really work with semantic versioning (even though it's parseable by it), but I don't think it's that much of a problem since it's just a nightly build and use is at your own risk, and you'd have to check manually every time when updating anyway, because every commit could have a breaking change in it.
In case it gets too long
Syntax: !help <page>
const client = new Client("name", "", {
unescapeMessages: false,
});
I have noticed several people adding suffixes to their bots' help commands.
Syntax: new option in constructor and new property named helpSuffix
.
Currently there is no way for users to know subcommands exist.
Making the help command show this should resolve that.
msgroom (the chat room, not this library) can have some problematic usernames that make putting usernames in chat messages tricky. As far as I can tell, there are two main problems:
\u202e
**nolanwhy**
A username()
utility function that you could just wrap usernames that would be output in would help with this. It would:
\u202d
at the end of the username to negate any text reversal going onI should remove this.
We need some way to be able to tell users more about a command.
My current idea is to put an object where you'd put a function (command handler) now.
This object can contain aliases for a command, the handler and a description.
The way to detect this is simple: from the moment a property called handler
is defined, it's considered a command.
I think we should also provide a class the user can instantiate for better code readability.
So turns out people have been experimenting with TestBot's repeat command, and used it to trigger other bots.
This is not good, as people could for example abuse one bot to trigger another, while the bot that was triggered wouldn't know.
Solution? New option in the constructor: blockBots
.
This new option will block anyone who has a prefix or "bot" in their name.
I'll also notify a user when they change their name or join with such a name that they will be ignored due to their name.
Recently, Yabluzo and other bots on recent versions have started crashing now and then.
I have been aware of this issue for some time now and have been able to log some of the events that caused one of these undefined errors.
These logs indicate that a message
event is sometimes handled before the user-join
event assigns a new user to client.users
.
However, this is impossible because these event handlers are all synchronous and socket.io guarantees that all events are received (and thus have their event handlers run) in the same order they were sent.
My conclusion is that client.users[user]
must be undefined for some other reason.
I think this may be related to a recent change that introduced blocking bots using Sheesh's bot API.
I have also noticed that the crashes seem to happen for bots or people who have the same ID as a bot.
I will investigate further.
Ever since I decided to allow to leave out the description and aliases properties, I have been having to deal with them in the already messy help command.
I'm working on putting this in a separate transform.
If you have subcommands like !a b
, !a c
, !a d
, just trying to call !a
crashes msgroom-nightly. Here's the error from toB:
<toBPath>\node_modules\msgroom-nightly\dist\index.js:281
if (key.toLowerCase() == command.toLowerCase()) {
^
TypeError: Cannot read properties of undefined (reading 'toLowerCase')
at Client.getCommand (<toBPath>\node_modules\msgroom-nightly\dist\index.js:281:54)
at Client.processCommands (<toBPath>\node_modules\msgroom-nightly\dist\index.js:317:42)
at Socket.<anonymous> (<toBPath>\node_modules\msgroom-nightly\dist\index.js:136:27)
at Emitter.emit (<toBPath>\node_modules\@socket.io\component-emitter\index.js:143:20)
at Socket.emitEvent (<toBPath>\node_modules\socket.io-client\build\cjs\socket.js:519:20)
at Socket.onevent (<toBPath>\node_modules\socket.io-client\build\cjs\socket.js:506:18)
at Socket.onpacket (<toBPath>\node_modules\socket.io-client\build\cjs\socket.js:474:22)
at Emitter.emit (<toBPath>\node_modules\@socket.io\component-emitter\index.js:143:20)
at <toBPath>\node_modules\socket.io-client\build\cjs\manager.js:237:18
at process.processTicksAndRejections (node:internal/process/task_queues:81:21)
Node.js v18.16.0
The API docs stopped generating ever since the migration to docusaurus v3.
I should really fix this.
The maximum length of a message is 2048 characters.
Since the server doesn't bother telling us when a message is too long, we should.
I have no idea yet if it should throw an error or something.
Maybe tell them using werror
? Maybe split the message?
I need some input for this.
Currently it's an array you have to search through and that's annoying when we know the session ID is guaranteed to be unique.
A hashmap is easier and more efficient here.
The fact that I was lazy and used an array in the first place caused the mess of #4.
right now they know nothing at all
Currently, every option is a field on the Client
class.
The new approach will have all the options in a separate field.
For example: client.helpCommandLimit
New approach: client.options.helpCommandLimit
I'm changing it like this for more clarity.
I also want to add a feature where you can override certain options for a specific command.
I'll add a new field to Command
and one to CommandContext
to change and view the options respectively.
And while we're at it, why not let an option be a function that takes the context and any more arguments that provide more information (or maybe put them on the context too?)
is this a server for msgroom? I was going to make one at
https://gitlab.com/its-pablo/msgroom-server
@NanderTGA are you still working on this an stuff
I'm currently attempting to make commands case-insensitive (#36), but if this is going to work, there will be a for loop inside a while loop.
This is not really good for performance.
If we make aliases work too (#35), that will need to use walkCommandMapEntry(), which is a recursive function.
I need to rewrite this entire function.
When one changes Client#name
, you'd expect it to update, but it doesn't.
Solution:
Update it when receiving the nick-change
event with a matching session ID.
Msgroom v2 is coming along nicely, but there's one big problem: documentation.
The plan is to write some proper documentation on the repository wiki.
Until I fix the other 2 issues and write some proper documentaton, v2 cannot release.
Affected tsconfig.json compilerOptions:
You should add bot API keys. Example: import Client from "msgroom";
const client = new Client("TestBot", "APIKey", [ "!" ]);
await client.connect();
This will allow you to hide commands from the help command.
The plan is to add an extra field to Command
called hidden
.
This will be a simple boolean (false by default).
Pretty annoying, we should fix that
We can use a library for this like he
When a user sends just the prefix, tell them to run the help command.
Command gets a new property: arguments
Example:
client.commands.dice = {
arguments: [
{ // turns into <sides>
name: "sides",
required: true,
}, {
// turns into [...stuff]
name: "stuff",
required: false,
rest: true,
}
]
}
I also have this idea to do some validation perhaps. (Sending a user things like missing command error...).
The current toB code does this:
import Client from "msgroom-nightly";
import Command from "msgroom-nightly/dist/utils/Command.js";
This isn't ideal. Perhaps this could be changed to work like this:
import { Client, Command } from "msgroom-nightly";
Say you wanted to implement a counter command. It'd look like this:
let counter = 0;
client.commands.counter = {
description: "A counter.",
handler: () => `The counter is ${++counter}!`,
}
This works, but it uses a global variable, so it pollutes the global scope.
A much nicer way to do this would be:
client.commands.counter = class {
private counter = 0;
public description = "A counter.";
public handler() {
return `The counter is ${++this.counter}`;
}
};
I think this would improve the UX of this library by a lot. I'm currently facing this problem with my toB's command:
const hangmanSymbols = [
// ...
];
let hangman: string | null = null;
let hangmanIncorrectGuesses = 0;
let hangmanGuessed: string[] = [];
const hangmanGuessesAmount = 9;
const hangmanReset = () => {
// ...
};
const hangmanView = () => {
// ...
};
const hangmanSolved = () => {
// ...
};
client.commands.hangman = {
// ...
};
I've seen quite some bots implementing some admin system of their own, often having people with the same ID being an admin by default, who then can give other people admin access.
Then they have to deal with loading and saving that stuff.
Since this kind of functionality is common, and people don't get promoted or demoted a lot, and there usually only are a few admins, a simple JSON file will do just fine.
I'll do it like this:
Executing this: !thing "first argument" "second one"
Will turn into thing.handler(context, "first argument", "second one")
being called.
The same way it works in cmd, powershell, bash...
A Set makes more sense here. No duplicates + easier to remove specific prefixes.
I managed to implement putting commands in other files in yabluzo, but it's far from ideal and other people are on their own.
It's annoying to have to use .then
and all that stuff.
The way this would work is by making client.processCommands
async and not awaiting the Promise
it returns on handling commands.
I want to transform some properties of objects you receive from the server like session_id
to have a different name instead (sessionID
in this case).
This is something for v2.
Say you want to use $
as a prefix.
You set the prefix to $
, but stuff breaks.
Turns out you need to escape it, so you change it to "\\$"
(confusing, I know).
It works, until you want to tell people your prefix, but you only have the escaped one.
Then you need to remove the backslash and yada yada, basically one giant mess.
At the time of writing the command parser, I thought it would be a good idea to use regex to check for matching prefixes in a message, to avoid a (simpler) for loop.
As a result of this, people could use regex themselves to check for prefixes. Awesome, right?
It seemed to work fine, until someone wanted to use $
as a prefix.
The dollar sign has a special meaning in regex, so when you embed that into a regex expression, you get broken behavior.
Loop over the prefixes instead.
If the current prefix is a string, check if the message starts with it and remove it from the message.
If it's a regexp, test if the regex matches and remove the matching parts
Unable to disable the welcomeMessage with a blank string.
Please fix.
This is a follow-up issue to #34.
In 3 months time the msgroom server has seemingly changed a bit. For example, I recall seeing a werror in the console sent by the server saying You are doing this too much - please wait
a while ago.
I also recall seeing another bot written in python which seemingly got the session ID from an event.
I need to investigate this further because the hack to get the sessionID is pretty janky and barely works.
Turns out I didn't account for people getting the session ID when blockSelf is off.
Thanks to Kelbaz for reporting the issue.
ReDoS vulnerabilities are a serious problem and people using regex prefixes could fall victim to this.
I want to protect people against this by checking for ReDoS vulnerabilities in the background using recheck.
It does add an extra dependency though.
Do or don't?
Right now a commandMap
cannot have a description of its own.
Solution?
client.commands.thing = {
undefined: { handler: ... },
subcommand: { handler: ... },
}
Will turn into
client.commands.thing = {
description: ...,
aliases: [...],
handler: () => "some thing",
subcommands: {
undefined: { handler: ... },
subcommand: { handler: ... },
}
}
I don't know for sure if this is a proper solution though.
Any feedback is greatly appreciated!
If a command ask
gets registered, then %ask something
and %ASK something
and %aSK something
should also lead to that command. There have been some cases of people using %ASK A CAPITALIZED QUESTION
, so I think it makes sense.
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.