trilemabot [ii]: prefixed commands
Following up on the previous part of this series, the patch below teaches trilemabot to respond to prefixed commands, as per the spec. More specifically, the bot takes a pre-defined1 prefix
, a command
and optional arguments
, in the form:
<prefix><command> <arguments>
parses them, and passes them to a pre-defined2 handling method.
The V patch and my seal:
For more details on installation and usage see the first part.
The remainder of this entry a. shows a fully functional trilemabot example, dictbot; and b. discusses rationale and potential complexity arising from the design choices that I made for this prefixed command handler.
First, dictbot. This is a didactic example more than anything, although it can be improved and turned into something useful.
As pointed out in the logs, the function of dictbot is to look up definitions in text dictionaries:
the bot goes through each line in http://www.loper-os.org/pub/ro_eng_expr.txt and if it finds one for which the query is a substr of the entry, it displays the definition. not very effective, it's intended as a very simple (<100 lines of code) demo for next trilemabot patch. but imho there's room for improving it even without adding google translate support.
Examples can also be found in the logs.
In the end, some discussion points.
[i] trilemabot command handling is centered around the trilemabot-handle-cmd
generic function. To define a new command, e.g. help
, the programmer must define a new trilemabot-handle-cmd
method that is specialized a. on a command mnemonic, e.g. in our case :help
(using eql specializers), and b. on the bot's class. I believe this approach to be more elegant than using something such as a hash-table of callbacks, because it uses the full power of CLOS and because it then enables one to use the trilemabot-define-cmd
wrapper. Command handling has, however, been implemented before, so I am curious to hear whether there's a better choice for this.
[ii] The command parser makes no assumptions whatsoever about the arguments, since I'm fairly convinced that none can be made. Some bots might want to split the arguments to their commands bash-style, others (such as dictbot) might process them as they are, while others may use whatever crazy parser I haven't even thought about. So argument specification and implementation is left entirely up to the bot owner.
[iii] Saying that the trilemabot-prefixed-cmd patch implements "command handling" is somewhat improper. In more complex situations, much of the handling is going to occur somewhere other than the handler itself.
Let's take the following example: one may for whatever reason want to limit access to some commands to L1 members3. In this case, the bot will have to talk to deedbot before issuing the actual command. Thus a. the bot will ask deedbot for trust information, then b. after receiving a response, it will determine whether the issuer is allowed to call the command, and only then c. the bot will handle the command.
In the current implementation, (a) will be executed on a trilemabot-handle-cmd
method, (b) will be executed on a privmsg
handler, and (c) will be executed immediately after (b) finishes. This implies the necessity of keeping some state information between (a) and (b), and where this state will be maintained is not immediately clear. This is where the inbox slot may turn out to be useful. Or not? I must admit, I'm not entirely sure what's the right control-flow yet.
After this discussion reaches some conclusion, the next step will be to figure out what to prioritize: regrinding ircbot into a unified tree with a manifest, or marching on towards the completion of rssbot. I think it's a good time to choose the former, given that the number of patches is still small.
I.e., defined when the bot instance is created by the user.↩
I.e., defined when a bot with more specific functionality is implemented by the programmer.↩
For example the new RSS bot, the main reason for my bot-crafting journey, has commands that are to be in general L2-only, while some commands will be L1-only.↩