libircpp manual

Welcome to the libircpp manual.
  1. Introduction
  2. Hello World
  3. Compiling and installing
  4. Signals
  5. Example: op-me bot
  6. Messages
  7. Users and Channels
  8. User and Channel Lists
  9. Example: Channel Logger
  10. Planned features

5. Example: op-me bot

In this chapter we will make a simple bot that can op you on your channel. As before, we'll start with the code, which is very similar to Hello World, but with an additional function, msg_handler().
#include <libircpp/libircpp.h>

using namespace std;
using namespace ircpp;

void msg_handler(const message& msg);

int main(int argc, char **argv)
{
        session* ircsession = new session();
        
        ircsession->set_nick("opmebot");
        ircsession->set_username("opmebot");
        ircsession->set_realname("libircpp example op-me bot");

        ircsession->sig_privmsg_msg.connect(msg_handler);

        ircsession->connect("my.irc.server.net"); 
        ircsession->cmd_join("#mychannel");

        ircsession->run();
}

void msg_handler(const message& msg)
{
        if(!msg.to().is_channel()) {
                return;
        }

        const channel& c = msg.to().to_channel();

        if(msg.param(0) == ".op") {
                c.cmd_mode("+o " + msg.from().name());
        }
}
Starting at the top:
#include <libircpp/libircpp.h>

using namespace std;
using namespace ircpp;
The standard include and namespace stuff - the same as in Hello World.
void msg_handler(const message& msg);
We declare a function msg_handler. This will be our callback function, which will be called whenever a PRIVMSG message arrives.
int main(int argc, char **argv)
{
	session* ircsession = new session();
	
	ircsession->set_nick("opmebot");
	ircsession->set_username("opmebot");
	ircsession->set_realname("libircpp example op-me bot");

	ircsession->sig_privmsg_msg.connect(msg_handler);

	ircsession->connect("my.irc.server.net"); 
	ircsession->cmd_join("#mychannel");

	ircsession->run();
}
The main() function is almost identical to Hello World. We create a session, and set the nick, username, and realname. Then, in bold, we have added a line to connect our new message handler to the session's sig_privmsg_msg signal. This means that our function will be called whenever any PRIVMSG messages arrive (remember PRIVMSGs are both private and channel messages). We then connect to an IRC server, and join a channel (remember to modify these two lines to point to your irc server and channel). We have removed the cmd_privmsg call that said "Hello World". Finally, we call run() to start processing messages, as before.
void msg_handler(const message& msg)
{
Here is the beginning of our message handler. Notice that it takes one parameter, a const reference to a message object, called msg. Most of the parameters passed to your functions will be message objects, which represent one IRC message coming from the server. More about this in the next chapter. The parameter is declared const, so you can't modify the message object by accident. If you forget the const in your message handlers' parameters, you'll get some large and incomprehensible errors from boost!
	if(!msg.to().is_channel()) {
		return;
	}
The first thing we check is that the message we've received is going to a channel. If it's a private message, we want to ignore it, because we won't know which channel the user wants opping on. So, if the message's "to" parameter is not a channel, we return without doing anything. More about messages and their parameters in the next chapter.
	const channel& c = msg.to().to_channel();
Now that we know that the message is a channel message, we extract a reference to that channel's object. msg.to() can be either a user or a channel, so this is essentially a typecasting operation. More about this, and why it's necessary, in the next chapter.
	if(msg.param(0) == ".op") {
		c.cmd_mode("+o " + msg.from().name());
	}
We then check to see what the text of the message is. The message object's param() function returns one word of the message, 0 being the first word, 1 the second, etc. We check to see if the first word is ".op".

If it is, we try to op the user that sent the message, by sending a MODE command. We could do this using the session's cmd_mode function, and specifying the name of the channel as the MODE target. However, the channel object also has a cmd_mode function, and using that saves us the trouble. So, we call the channel's cmd_mode function, with a string like "+o joebloggs". This is the equivalent of typing "/mode #channel +o joebloggs" on irc. For "joebloggs" we use the name of the sender of the message, retrieved with msg.from().name().

Compiling and Running

You can find the source code for this example in the test/ directory as opmebot.cpp, along with the other examples. You can compile it like this:
g++ -o opmebot -lircpp -lboost_signals opmebot.cpp
Or statically like this:
g++ -o opmebot opmebot.cpp /usr/lib/libircpp.a /usr/lib/libboost_signals.a
When you run it, you should see it join your channel again. Op it, and then type .op - it should op you.

Note that this bot is completely insecure - it will op anyone who asks it to, so don't op it somewhere too public!

If you wanted to make it more secure, you could modify it so it only accepted the .op command in private message, with a channel name and a password. You can use the session object's find_channel() function to get a channel object when you only have its name.

Next: Messages, Users and Channels