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

8. User and Channel Lists

Libircpp can keep track of the channels you're in, and the users in those channels with its user and channel lists. This saves you from having to keep account of joins, parts, quits, etc, and provides easy access to the user and channel objects.

There are three types of list: The channellist, the main userlist, and the channel userlists.

The Channel List

The Channel List contains channel objects for all the channels you are in. Channels are added to the list as soon as you join them, and removed as soon as you leave them - you do not need to add or remove channels yourself. You can access the channel list with the following three functions in the session object:
find_channel("#channel")    // Finds a channel object by its name, and returns it
channellist_begin()         // Returns an iterator to the beginning of the channel list
channellist_end()           // Returns an iterator to the end of the channel list
find_channel(), given the name of a channel, will find it in the list. If the channel is not found (you're not in it), it will return the null channel object.

channellist_begin() and channellist_end() return iterators of type const irclist<channel>::iterator that point to the beginning and end of the channellist respectively. You can use these to loop through the channel list from beginning to end, like this:

const irclist<channel>::iterator it;
for(it = s.channellist_begin(); it != s.channellist_end(); it++) {
	cout << it->name() << endl;
}

The Main Userlist

The main userlist contains user objects for all users who share a channel with you. Users are added to the list as soon as you join a channel with them (or they join a channel you're in), and are removed as soon as they leave the last channel you are in (or you leave a channel and they aren't in any other channels with you). You do not need to add or remove users yourself. The functions to access the main userlist are functionally identical to those for the channel list, and can be found in the session object:
find_user("joe")         // Finds a user object by its name, and returns it
userlist_begin()         // Returns an iterator to the beginning of the user list
userlist_end()           // Returns an iterator to the end of the user list
find_user(), given the nick of a user, will find it in the list. If the user is not found (you don't share a channel with them), it will return the null user object.

userlist_begin() and userlist_end() return iterators of type const irclist<user>::iterator that point to the beginning and end of the main userlist respectively. You can use these to loop through the main userlist from beginning to end, like this:

const irclist<user>::iterator it;
for(it = s.userlist_begin(); it != s.userlist_end(); it++) {
	cout << it->nick() << endl;
}

The Channel Userlists

In addition to the main userlist, each channel object has its own userlist, which contains a list of the users in that channel. Each channel object has three functions identical to those of the main userlist, which work in the same way as the main userlist:
find_user("joe")         // Finds a user object by its name, and returns it
userlist_begin()         // Returns an iterator to the beginning of the channel user list
userlist_end()           // Returns an iterator to the end of the channel user list
The user objects in the channel userlist are shared with the main userlist, and with other channel userlists, so there is only ever one user object per user, even if they are in multiple channels.

List Modes and Deleting User and Channel Objects

Libircpp's lists can run in three modes: automatic, manual, and off. The list modes relate to how the user and channel objects are created and deleted; in particular, what happens when they are removed from the lists.

List modes are set when the session is created, and may not be changed after that - so you must decide how you want the lists to operate before you connect to irc. The list modes are set as follows:

session s(automatic);    // Automatic mode
session s;               // Automatic mode is the default if you don't specify a mode
session s(manual);       // Manual mode
session s(off);          // Lists off
The modes work as follows:

Automatic mode

This is the default. In automatic mode, as soon as you leave a channel, or as soon as a user leaves the last channel you are in, they are removed from the lists and the user or channel object is automatically deleted. This is important if you keep a reference to the user or channel object outside of a single signal handler function. If you do this, you must connect to the user or channel's sig_deleting signal. When you receive this signal for the user or channel, you must clean up and delete all references to it as it will be deleted when your signal handler returns. For example:

u.sig_deleting.connect(user_delete_handler);
...
void user_delete_handler(const entity& e)
{
	const user& u = e.to_user();
	// Clean up your references to the user here
}
If you don't want to deal with this process, just remember not to keep hold of a reference to the user or channel outside of each signal handler.

Manual mode

This mode is for when you want to keep user and channel objects around after they have been removed from the lists. In manual mode, you are responsible for deleting user and channel objects. You must connect to either the users' and channels' sig_deletable signals, or the session's sig_user_deletable and sig_channel_deletable signals. The session signals are preferred, because they are emitted when any user or channel becomes deletable - otherwise you must ensure that every user in every channel has its signal connected to your handler. The signal informs you that you may now delete the user or channel when you are finished with it. If you don't, your program will leak memory. For example:

u.sig_deletable.connect(user_delete_handler);
...
void user_delete_handler(const entity& e)
{
	const user& u = e.to_user();
	// Clean up your references to the user here
	delete &u;
}

Off mode

If you choose "off" mode, the lists will not be used at all. No users and channels will be stored (all the users and channels in message objects will be temporary - see below).

Temporary user and channel objects

If a user or channel is not stored in the list, it will be marked as temporary. You can check this as follows:
if(u.is_temporary()) {
	// ..
}
If a user or channel is temporary, it will be deleted as soon as the signal handler returns. You should not store references to temporary list items. Users and channels may be created as temporary if:

Next: Example: Channel Logger