8573 / irc-bot.rs

A library for writing Internet Relay Chat (IRC) bots in the Rust programming language (@rust-lang).
Other
29 stars 13 forks source link

Command syntax, esp. optional arguments #51

Open 8573 opened 5 years ago

8573 commented 5 years ago

In https://github.com/8573/irc-bot.rs/issues/50#issuecomment-514828190, @ctm wrote—

I've only been playing with irc-bot for about a day. I've found it easy to use, although I haven't yet figured out how to make a command that takes an optional argument. In specific, I'd like to be able to support bet, bet N (where N is a positive number), bet pot and bet half, but, at least when using the source from the dev branch of this repository, I get:

Error: While handling YAML: Expected <argument> to be of type Scalar, but it is of type Mapping.

for just bet, although bet "" works fine. I'm using "<amount>" as the argument to the syntax parameter of ModuleBuilder::command. I tried "...", but that fails to compile. With "<amount>", the zero-length string as input is converted to an empty Hash which is why yaml::check_type dies. I'm early enough into development that this doesn't really matter to me, and I realize there may be some other argument to syntax that might work.

Sorry about this! The API for defining commands, especially around taking arguments, is one of the older and messier ones, if not the messiest, and is so poorly documented that I can't even find any generated list of items for it in the documentation. (I suppose its "documentation" consists of the examples provided by the bot modules in src/modules.) Now that I have users other than myself, I realize that it well may be overly restrictive that the "commands" must take YAML objects as arguments, if they take any argument.

The way to have an optional argument like this with a command per se would be to make the argument a YAML mapping (what yaml-rust calls a Hash) and have the optional arguments be optional fields of that mapping, leading to an interface such as—

pokerbot: bet
pokerbot: bet amt: <N>
pokerbot: bet type: pot
pokerbot: bet type: half

However, it currently should be possible to get the interface you intended by using not commands per se but rather the similar feature currently named "triggers", which allow matching incoming messages against an arbitrary regex and running a given function for matching messages, with the regex's captures passed to the function. For your case, I imagine the regex would be ^bet(?: ([0-9]+|pot|half))?$.

These APIs deserve to be overhauled, and I imagine I might unify them into a single, more flexible API. Whether or not I do, I intend to rename triggers to something else, because, if eventually I write documentation for them, I otherwise would be talking about triggers being triggered and what triggers triggers, which could get confusing.

ctm commented 5 years ago

Thank you very much for the quick response!

I did see that I could do a YAML mapping, but I didn't want my users to have to supply the key. We're old farts with muscle memory going back to the goodle days and we're happy to have any memory at all.

I did briefly see how triggers worked, but because of the name, I didn't think of them, especially since commands were so close to what I wanted to do that I fixated on them.