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

6. Messages

Most of the signals you receive will be because an IRC message has been received from the IRC server. These signals will have a single parameter of type const message&. These messages are emitted both by the session (if you want to receive all messages of a certain type), or by user and channel objects (for messages relating to that user or channel).

The message object sent in the signal has the following basic parts:

The Sender

The sender of the messages is a reference to a user object, accessed by the message object's from() function. The sender of the message is usually either a person on irc, or the IRC server itself. In the case of messages from the server, the server is represented by a special user object which you can retrieve by the session object's server() function. For example, if you wanted to see if a message was from the server or not, you might use code like this:
if(msg.from() == mysession->server()) {
	cout << "It's a server message" << endl;
}
else {
	cout << "It's a message from " << msg.from().nick() << endl;
}

The Command

The command tells you what the message is for. For example, JOIN, NOTICE, PRIVMSG, KICK, QUIT are all commands you are probably familiar with. In addition to these textual commands, there are a lot of "numerics", which the server sends. For example, the 001 numeric is the first thing sent when you connect. Numeric 311 is part of a /whois reply.

A message's command can be retrieved with its command() function, and it is an object. However, it has been designed so you can treat it like a number. This is very useful if you want to use a switch() statement on it:

switch(msg.command()) {
	case PRIVMSG:
		cout << "This message is a PRIVMSG" << endl;
		break;
	case QUIT:
		cout << "This message is a QUIT message" << endl;
		break;
	case 311:
		cout << "This message is a whois reply" << endl;
		break;
	default:
		cout << "This message is an unhandled message of type " << msg.command().str() << endl;
}
libircpp has a set of defines which define PRIVMSG, QUIT, and other textual commands as numbers so they can be directly compared with command objects. In addition, if you want a string representation of the command, just use msg.command().str() as shown above.

The Recipient

The recipient of a message is accessed with the message's to() function.

Messages can be sent to both users and channels. Because of this, the recipient could be either a user or a channel object. As explained in the next chapter, libircpp's user and channel objects are therefore derived from a base class called entity. The recipient is therefore of type entity, and you must convert it to a user or channel if you want to do any user-specific actions on it. For example:

if(msg.to().is_channel()) {
	const channel& c = msg.to().to_channel();
	process_channel_message(c); 					// Your function to process channel messages
}
else {
	const user& u = msg.to().to_user();
	process_private_message(u); 					// Your function to process private messages
}

The Target

In addition to the recipient, some messages have a target. For example the KICK message has a sender (the person doing the kicking), a recipient (the channel), and a target (the person being kicked). Another message which has a target parameter is the INVITE message.

If a message has a target, it can be retrieved with the message's target() function. If the message doesn't have a target, the target() function will return the null user. You can check for this as follows:

if(!msg.target()) {
	// Message has no target
}

The Parameters

After the sender, command, and recipient, most messages have parameters. For example, in the PRIVMSG message, the parameters are the text that the user has said. The message object provides two flexible ways of accessing message parameters.

The param() function allows you to access parameters one word at a time. For example, param(0) would give you the first word of the message, param(1) the second, etc. This is useful when you know which parameter of a message you want.

The params() function allows you to access all the parameters of a message as one string, or all parameters starting at a specified one, and ending at the end of the message. For example:

msg.params(0);			// Returns all parameters as one string
msg.params();			// Does the same as above
msg.params(2);			// Returns a string containing parameters, starting with the third parameter, and ending with the last
Normally, the param() and params() functions will skip the recipient and target, if present, and remove any colon at the beginning of the parameters. This normally gives a sensible starting point for the parameter list - e.g. for PRIVMSGs, params(0) is the beginning of the message the user typed. If you want to retrieve the unprocessed parameters, starting after the command, and with the colon intact, set the optional second parameter to param() and params() to true, like this:
msg.params(0, true);

The Raw Line

The message object also stores the raw line of text as received from the irc server. You can retrieve it with the message's raw_line() function.

MODE Messages

Modes can be set on both users and channels. When set on channels, mode changes may also have a parameter. For example, when giving channel operator status, the recipient is the channel, and the parameter is the user being opped. When setting a channel key, the key (password) is the parameter.

To make things more complicated, multiple mode changes may be combined into one line, and this is frequently done. An extreme example might be:

MODE #channel +oio-v+k joe fred ernest pasward
This must be parsed if the modes are to be kept track of, for example when indicating channel operators in a channel userlist.

To help deal with this, where mode messages contain multiple mode changes, libircpp can split the mode message up into individual mode changes. When a mode message is recieved, two separate signals are emitted: sig_mode_msg (once), and sig_singlemode_msg (once for each separate mode change). sig_singlemode_message consists of mode messages each of which contains only one mode change.

So, from the example above, if you had connected to sig_mode_msg, you would see:

+oio-v+k joe fred ernest pasward
And if you had connected to sig_singlemode_msg, you would see, as separate messages:
MODE #channel +o joe
MODE #channel +i
MODE #channel +o fred
MODE #channel -v ernest
MODE #channel -v ernest
MODE #channel +k pasward
It is important to note that the messages emitted by sig_singlemode_msg, while complete message objects, have been generated by libircpp, not the irc server. sig_mode_msg contains the messages as received by the server; sig_singlemode_msg is there only for convenience. In particular, if you were to parse both sig_mode_msg and sig_singlemode_msg, you would see every mode change twice.

Next: Users and Channels