KRISTEN'S BOARD

Welcome, Guest. Please login or register.

Login with username, password and session length
 
Pages: [1]   Go Down
  Print  
Author Topic: A Guide to Writing Commands for RavishBot  (Read 49 times)
0 Members and 1 Guest are viewing this topic.
Army of One
Total freak
*****

Fame 52
Offline Offline

Gender: Male
Posts: 615



« on: November 03, 2018, 03:00:21 AM »

This guide is also available on Ravishment University.

So, recently, I've been asked in the chat by some people if I'll be adding more commands for the bot. I told them that I could take requests, and posited this choice to them (the same choice I'm putting to everyone who reads this post):
  • Write down what you want the command to do, and, depending on if I think it's a good idea, I would write and implement it into the bot; or
  • You write the command and send it to me, and I'll implement it if I like it.1
If you choose the first option, then this is the point where you can finish reading. Just send me a DM with what you would like the command to do, and I will write it up and implement it. Howeveer if you want to try the second option, then rad on, because this thread is for you.

Commands in RavishBot are written as Javascript functions. If you're not too familiar with Javascript, W3Schools has a nice tutorial for you here. (For the purposes of the bot, however, you only really need to concentate on the main part of the tutorial (excluding Events and JSON), plus the JS Objects and JS Functions sections.)

The Javascript interpreter in RavishBot (i.e. the part of the bot that runs the commands) has its own set of objects which it can use to interact with the bot. The main one of these is called bot2, and it is this one which you'll use the most. I'll give an outline of all the functions in this object in a separate post below.

So, let's write a simple command, called eatme. (This is an actual command on RavishBot.)
Code:
function eatme() {
bot.sendPrivateMessage(bot.currentTarget, "\x01ACTION eats out %1.\x01", bot.currentSender);
}
Even though this is a simple command, there is a lot to unpack here:
  • The first thing you'll notice is that the function name doesn't start with !. The bot actually removes the ! before it executes the command. (The prefix is actually set in the main part of the bot, not in Javascipt code.)
  • The first line calls the method bot.sendPrivateMessage, which sends a message to a target (either a user or a channel) on IRC. It has two required arguments, the target for the message (almost always either the place from which the command was sent, or the current channel), and the message itself. It can also have up to nine optional arguments, which are values you want to put into the message string.
  • The first argument of bot.sendPrivateMessage is bot.currentTarget. This is a property of bot, and contains where the command will return to; this is either the channel (which is #ravishu), or the person who sent it if it was sent in a private message.
  • The second argument is the message itself. In this case, it has \x01 at either end, and the word ACTION. This is actually what gets sent behind the scenes in the chat when you use /me (or /act).
Take note as well of the %1 in the message; I'll go into its next.
  • The third argument, bot.currentSender is who sent the last command. Here, its value will be put into the message string in the place of the %1.
Phew! That's a lot! I'll provided a much more detailed explanation for each of these, and all the other properties and methods of bot, below in a separate post.

Could I have used return instead of that command? A good question if anyone asked it, and I would say yes. return sends whatever expression is following it to whatever is in bot.currentTarget, then stops there. However, this is not always what you would want to do, so please get into the habit of using bot.sendPrivateMessage instead of return.

Command Parameters
Okay, let's talk about parameters. There are two kinds of parameters with commands: required and optional. Required parameters need arguments assigned to them; as such, they are put first in the parameter list (in the brackets). Optional parameters can be left out, and will either default to a set value, or just not be used at all. Optional parameters come after required parameters in the parameter list.

I'll give an example using the drinks command:
Code:
function drinks(drink, nick) {
if (bot.currentTarget.toLowerCase() == bot.ircChannel.toLowerCase()) {
if ((drink === undefined) || (drink.length == 0)) {
bot.sendPrivateMessage(bot.currentTarget, "I don't know what I'm getting everyone.");
} else {
if ((nick === undefined) || (nick.length == 0)) {
bot.sendPrivateMessage(bot.currentTarget, "\x01ACTION serves everyone a %1.\x01", drink);
} else {
bot.sendPrivateMessage(bot.currentTarget, nickIsHere(nick) ? "\x01ACTION serves %1 a %2.\x01" : "Ummm, %1 is not here to get their %2.", nick, drink);
}
}
} else {
if ((drink === undefined) || (drink.length == 0)) {
bot.sendPrivateMessage(bot.currentTarget, "I don't know what I'm getting you.");
} else {
if ((nick === undefined) || (nick.length == 0) || (nick == bot.currentCaller)) {
bot.sendPrivateMessage(bot.currentTarget, "\x01ACTION serves %1 a %2.\x01", bot.currentCaller, drink);
} else {
bot.sendPrivateMessage(bot.currentTarget, "Ummm, %1 is not here to get their %2.", nick, drink);
}
}
}
}
There are two parts to this command, each showing a different side to optional parameters. I'll do each part separately.
Code:
if ((drink === undefined) || (drink.length == 0)) {
bot.sendPrivateMessage(bot.currentTarget, "I don't know what I'm getting everyone.");
} else {
if ((nick === undefined) || (nick.length == 0)) {
bot.sendPrivateMessage(bot.currentTarget, "\x01ACTION serves everyone a %1.\x01", drink);
} else {
bot.sendPrivateMessage(bot.currentTarget, nickIsHere(nick) ? "\x01ACTION serves %1 a %2.\x01" : "Ummm, %1 is not here to get their %2.", nick, drink);
}
}
In this first part (which occurs when the command has been called from the main chat room), if drinks isn't supplied (i.e. if it is undefined), then it sends out an error message3, but if nick is undefined, then it just gives everyone a drink. (If nick is given, then it just serves that person a drink, provided they're present4.)
Code:
if ((drink === undefined) || (drink.length == 0)) {
bot.sendPrivateMessage(bot.currentTarget, "I don't know what I'm getting you.");
} else {
if ((nick === undefined) || (nick.length == 0) || (nick == bot.currentCaller)) {
bot.sendPrivateMessage(bot.currentTarget, "\x01ACTION serves %1 a %2.\x01", bot.currentCaller, drink);
} else {
bot.sendPrivateMessage(bot.currentTarget, "Ummm, %1 is not here to get their %2.", nick, drink);
}
}
}
This second part, which executes when drinks is called within a one-on-one with the bot, all but disallows you from supplying the nick parameter (meaning it must be undefined, unless you give your own nick).

You can also use arguments instead of supplying them directly if you wish; that said, I only suggest using that if there is no upper limit to the number of arguments you may have. gangbang is an example of a command that uses the arguments property.

Providing Help
bot.createHelpDetails is used to provide the help command with details on your command. It also exposes your command to the bot, and thus everyone in chat. (Without that exposure, any attempt to call the command wwill be met with, "Command Not Found.")5 The function takes three things: the name of the command, a short description on what the command does, and a list of the parameters, if it has any. It should always be put either before or after the command itself in the file.

I'll use drinks's help details as an example:
Code:
bot.createHelpDetails("drinks", "Serves drinks.", "<drink> : The drink to serve. This needs to be in quotes.", "<nick> : (optional) : The person to serve it to. In a channel, if this is given, it serves a drink to that specific person, otherwise it is served to everyone. In one-on-one chat, this should not be included at all.");
The first argument is the name of the command, drinks. The second argument is a brief description, in this case "Serves drinks". The remaining arguments are the parameters, and the structure for each parameter description is as follows: "<parameter name> : (required) / (optional) : <description of parameter>". Order is important here, as the order in the help detail must reflect the order of the parameters in the definition. In addition, if a parameter is required, you don't need to indicate it's required, as this will be assumed unless you state otherwise (although it's still good practice to do so when you have a list that contains required and optional parameters; I'm obviously not showing very good practice here).

When you type in !help drinks, this is what you'll get:
RavishBot:  drinks command.
RavishBot:  Serves drinks.
RavishBot:  Calling format - !drinks <drink> [<nick>]
RavishBot:  Parameters -
RavishBot:  <drink> - The drink to serve. This needs to be in quotes.
RavishBot:  <nick> - The person to serve it to. In a channel, if this is given, it serves a drink to that specific person, otherwise it is served to everyone. In one-on-one chat, this should not be included at all.


And That's the End of the Lesson!
And that's the basics. You now know enough to write your own bot command. As I said, I'll put below a listing of all the bot-specific objects and methods available as a reference. That said, if you have any questions, don't be afraid to ask.

Good luck, and happy writing.

1 I'm fully aware of the fairly arbitrary selection criterion I've given. I can tell you, though, that I won't allow any command that'll insult or kick and/or ban someone, or expose a function that shouldn't be exposed as a command.
2 At the time of writing, bot was the only object implemented in the command side of the bot. I'll add others as I include them.
3 An error message is preferred over returning an Error object, as Errors are silently dealt with by the bot.
4 nickIsHere can be used to determine if someone is in chat. It's not part of the bot object, but part of a library of common functions written for use in commands (but not available as one).
5 There is another way to expose commands to the system, using bot.expose. This, however, doesn't create help details, and I generally recommend against using it.


Logged
Army of One
Total freak
*****

Fame 52
Offline Offline

Gender: Male
Posts: 615



« Reply #1 on: November 03, 2018, 03:09:06 AM »

The Common Function Library

This is a small set of functions and variables written in Javascript that can be used in any command. They aren't exposed, and I will veto any attempt to expose them in your command code. (If you create a function for use as a common, however, that's just fine. As long as you use it. And I'll add it here.)

Variables

onConnect
Contains a list of instructions that need to be executed every time the bot connects to the chat room. This is actually created and used by the bot.

To add an instruction to the list, use push to add it to the list, like this:
Code:
onConnect.push("bot.sendPrivateMessage(bot.ircChannel, \"Hello, room.\")");

You should never need to use this; its current sole purpose is to identify the bot to Rizon.

Functions

nickIsHere(nick)

nickIsHere tests to see if a nickname is here. All nicknames are treated as unhatted (i.e. no mod prefix) and are case-sensitive.
Logged
Army of One
Total freak
*****

Fame 52
Offline Offline

Gender: Male
Posts: 615



« Reply #2 on: November 03, 2018, 03:09:41 AM »

The bot Object

This is the main object that you'll be using for your commands, and contains all the core methods and properties you'll need to write your own commands.

Properties
All of these properties are read-only.

bot.currentCaller
Contains the nick of the person who called the command being executed.

bot.currentNick
Holds the bot's nick. This, of course, should be "RavishBot".

bot.currentTarget
Contains where output will be sent by default (i.e. where it would turn up if it was put through return). This would be equal to bot.ircChannel if the command was called in the main chat room, or bot.currentCaller if it was sent through a private chat with the bot.

bot.currentUserNames
This contains a list of all the users currently in chat. Do note that these names will be unhatted, i.e. they will not have any operator prefixes (@, &, ~, etc).

bot.ircChannel
Holds the name of the channel. This should be "#RavishU". (Since channel names aren't case-sensitive, if you are testing this against bot.currentTarget, make sure you use this code: bot.currentTarget.toLowerCase() == bot.ircChannel.toLowerCase().)

Methods
bot.createHelpDetails(name, description)
bot.createHelpDetails(name, description, parm1)
bot.createHelpDetails(name, description, parm1, parm2)
bot.createHelpDetails(name, description, parm1, parm2, parm3)
bot.createHelpDetails(name, description, parm1, parm2, parm3, parm4)
bot.createHelpDetails(name, description, parm1, parm2, parm3, parm4, parm5)
bot.createHelpDetails(name, description, parm1, parm2, parm3, parm4, parm5, parm6)
bot.createHelpDetails(name, description, parm1, parm2, parm3, parm4, parm5, parm6, parm7)
bot.createHelpDetails(name, description, parm1, parm2, parm3, parm4, parm5, parm6, parm7, parm8)
bot.createHelpDetails(name, description, parm1, parm2, parm3, parm4, parm5, parm6, parm7, parm8, parm9)

bot.createHelpDetails create a help entry for your command; this has the added benefit of exposing it to the bot. Because of how it works, this must be used outside of your command's logic, either before it or after.

parm1 through to parm9 contain the documentation for each of the parameters of the command, in the order they are supposed to be given. This documentation is given in the following format: "<parameter name> : (required/optional) : short parameter description", where
  • <parameter name> gives the name of the parameter. It doesn't need to be in angular brackets like I have there, but I will put them in there like that just to keep it consistent.
  • (required/optional) indicates whether the parameter is required or optional. It must be in brackets, i.e. you must put either (required) or (optional).
  • The parameter description simply describes what should be put at that spot. If it's to be a nick, say that it is a nick. If you need a number, say it needs a number.

bot.expose(cmd)

bot.expose makes the command given available to the bot (called "exposing" here). This, however, doesn't create a help entry; you will need to use bot.createHelpDetails for that. As such, I recommend against using this function in any command code you write.

bot.getUserOpStatus(nick)

bot.getUserOpStatus gets the operator prefix for the given nick, or an empty string if the user is not either an operator or present in chat.

bot.makePersistent(varname)

bot.makePersistent makes a variable that you declare persistent, i.e. if the bot has to be shut down for some reason, the variable's value will be saved, and reassigned to that variable when the bot is restarted. Because of this, it can only be used with global variables.

bot.sendPrivateMessage(target, message)
bot.sendPrivateMessage(target, message, parm1)
bot.sendPrivateMessage(target, message, parm1, parm2)
bot.sendPrivateMessage(target, message, parm1, parm2, parm3)
bot.sendPrivateMessage(target, message, parm1, parm2, parm3, parm4)
bot.sendPrivateMessage(target, message, parm1, parm2, parm3, parm4, parm5)
bot.sendPrivateMessage(target, message, parm1, parm2, parm3, parm4, parm5, parm6)
bot.sendPrivateMessage(target, message, parm1, parm2, parm3, parm4, parm5, parm6, parm7)
bot.sendPrivateMessage(target, message, parm1, parm2, parm3, parm4, parm5, parm6, parm7, parm8)
bot.sendPrivateMessage(target, message, parm1, parm2, parm3, parm4, parm5, parm6, parm7, parm8, parm9)

bot.sendPrivateMessage posts a message to a specific target (the chat room, or another user).

parm1 through parm9 are values that can be substituted into message at %1 to %9 respectively; i.e. parm1 will be exchanged for %1, parm2 for %2, and so on. For example,
Code:
bot.sendPrivateMessage(bot.ircChannel, "Hello, %1.", bot.currentCaller)
will send "Hello, ArmyOfOne" to the chat room (if I was the one who called the command).

bot.unmakePersistent(varname)

bot.unmakePersistent makes any variable you previously made persistent no longer persistent, i.e. the bot will no longer retain the variable's value when it shuts down.
Logged
Pages: [1]   Go Up
  Print  
 
Jump to: