LIBIRCCLIENT(1)
π LIBIRCCLIENT β the manual, but make it cute π
okay bestie, welcome to libircclient, the manual page for the Libircclient Documentation β¨ she's a whole icon, she's in section 1, and she's about to change your IRC-bot-building life. grab a boba, we're going in π§π
πΈ INTRODUCTION πΈ
π Introduction π
β Overview β
So. Libircclient is this small but extremely powerful library that implements the client IRC protocol β yes, the whole thing. She's designed to be small, fast, portable, and compatible with the RFC standards plus all the non-standard-but-popular features everyone actually uses. If you're building IRC clients and bots, she is literally the moment. no cap π
β¨ Features β¨
okay so the resume is stacked. let's read it together:
- Comprehensive C API β she speaks C and she speaks it fluently π«Ά
- Full coverage of the IRC protocol using providing functions
- Supports multiple simultaneous connections to different IRC servers β or even to the same server (iconic behavior honestly)
- Supports both plain and SSL connections to IRC servers, with optional certificate check π
- Full multi-threading support β the library is thread-safe, periodt
- All the processing can be handled by a single thread even if you're running multiple connections β efficient queen π
- Non-blocking, asynchronous event-based interface, implemented with callbacks
- Extra support for socket-based applications that use
select()(iykyk) - CTCP support with optional build-in reply code
- Supports CTCP PING β which is necessary to pass the βspoof checkβ that most IRC servers run π
- Flexible DCC support, including both DCC chat and DCC file transfer
- Can both initiate and react to initiated DCC
- Can accept or decline DCC sessions asynchronously β she's flexible like that
- Written in plain C, with a very small binary size (around
30Kdepending on platform) β tiny but mighty π¦ - Compatible with all tested IRC clients β
- Free software, licensed under the LGPLv3 license
- Supports Linux as well as any POSIX-compliant Unix, Mac OS X and Microsoft Windows π
- Supports 32/64bit architectures as well as non-x86 architectures
- IPv6 support β optional, must be compiled in
- OpenSSL support β optional, must be compiled in
- Cocoa interface by Nathan Ollerenshaw π«
- Comprehensive documentation, examples and the FAQ
π Known issues π
ngl bestie, we have to be honest here. Even though it's possible by using multiple sessions, the library is not suitable to connect to a large number of IRC servers simultaneously. If you still wanna do it, you'd have to overcome the following:
- You cannot use the main loop in
irc_run(), because it only supports one session. You would have to useirc_add_select_descriptors() - You'd have to handle reconnections separately by processing the relevant
irc_process_select_descriptors()return values - If you wish to use poll/epoll() instead of
select(), you'd have to write more logic, as it is not directly supported. See the FAQ. - The library is not optimized to have a low per-connection memory footprint. Each non-SSL connection uses at least
4K, with around32Kper connection for SSL.
π yeah. it's giving "small library, big per-connection appetite." plan accordingly.
π Author π
This library is created by George Yunaev, copyright 2004-2016. Please see http://www.ulduzsoft.com/linux/libircclient π«Ά
βοΈ License βοΈ
Libircclient is licensed under the Lesser General Public License version 3 or higher. The complete license text is provided in the Appendix. π
π¦ INTEGRATION π¦
π« Integration π«
πΈ Requirements πΈ
π₯οΈ Supported operating systems and compilers π₯οΈ
The library has been extensively tested on Linux x86 and x86_64. It has also been tested on Solaris x86, Linux on ARM and Linux on MIPS platforms, on Mac OS X on x86, and on various versions of Microsoft Windows. she gets around π
π¨ Compilation π¨
On Linux, FreeBSD and Mac OS X, the library has to be compiled and installed before use β unless you're using a precompiled package provided by your operating system distribution. And if that package exists, bestie, use it, because it would be updated from the central repository whenever bugs get fixed. slay.
On Microsoft Windows, the official library binaries are provided, so you don't have to build it. Unless you have experience building with Cygwin, you're advised not to build from source and to use the official binary instead. don't be a hero π
π Required libraries π
The library depends only on libc (glibc-devel on Linux) and gcc, although the examples also require libstdc++ (libstdc++-devel) and g++. The minimum supported version is glibc 2.2 β although if IPv6 is requested, you need at least glibc 2.4. so check your versions, bestie π«Ά
If the library is built with SSL support, the openssl development package (openssl-devel) needs to be installed.
On Microsoft Windows, Cygwin with the necessary development packages must be installed (and openssl-devel as well).
π οΈ Compiling π οΈ
The library is configured and built the standard Unix way:
./configure [--enable-openssl] [--enable-ipv6]
make
classic. we love a ./configure && make moment β¨
π¦ Installing π¦
Although no install is necessary to use the libraries, the install target is provided for convenience and could be invoked via:
sudo make install
yes bestie, sudo. she's fancy π
π Linking π
Link your application with either libircclient.a or libircclient.so depending on your needs. If you use the system-provided library, please link with libircclient.so. π
If you have built the library with SSL support, you will need to link with the OpenSSL libraries; add -lcrypto -lssl to your LDFLAGS.
On Microsoft Windows, please link with libircclient.lib, which implicitly links with libircclient.dll.
π§ Coding π§
π Initialization π
π Include the headers π
Before using the library you need to include the library header libircclient.h. You may also want to include libirc_rfcnumeric.h, which provides the RFC codes:
#include "libircclient.h"
#include "libirc_rfcnumeric.h"
π£ Create event handlers π£
Unlike most network protocols such as HTTP or SMTP, the IRC protocol is event-based. The events come from the server asynchronously. Some events are triggered by your action (like joining the channel or changing your nick), some are triggered by other IRC users (like sending you a message), and some are triggered by the IRC server itself (like sending operation notes or invoking NickServ services).
Libircclient helps handle those events by providing the event handling structure. It declares the events you can define in your application, and when such an event is received from the server, the appropriate callback will be called. The number of events you need to handle depends on the complexity of your client and the functionality it supports.
Generally there are only two events you must handle to provide bare minimum functionality: event_connect and event_numeric. However, it is recommended to create an event dump function and use it for all unused events, to make sure you don't miss an important event because you expected the wrong one. See the function dump_event in the file examples/irctest.c. π«Ά
πͺ Windows-specific initialization πͺ
If you link with the static library on Microsoft Windows, you need to initialize the Winsock2 library before calling the library functions. It could be done by following:
WSADATA wsaData;
if ( WSAStartup ( MAKEWORD (2, 2), &wsaData) != 0 )
// report an error
However, if you link with the dynamic library (libircclient.dll), which is default if you use the official build, this is not needed β because the DLL initializes it automatically on load. convenient queen β¨
π± Create an IRC session π±
To use the library, at least one IRC session needs to be created. One session can be used to establish a single connection to one IRC server for one nick. However, more than one session can be created if needed. π¦
To create a session, call the irc_create_session() function:
// The IRC callbacks structure
irc_callbacks_t callbacks;
// Init it
memset ( &callbacks, 0, sizeof(callbacks) );
// Set up the mandatory events
callbacks.event_connect = event_connect;
callbacks.event_numeric = event_numeric;
// Set up the rest of events
// Now create the session
irc_session_t * session = irc_create_session( &callbacks );
if ( !session )
// Handle the error
This code could be repeated as many times as needed to create multiple sessions. And the same callback structure could be reused for multiple sessions. efficient π
βοΈ Set options βοΈ
Besides debugging, there are two options you may need to use. The LIBIRC_OPTION_STRIPNICKS enables automatic parsing of nicknames, and since it is hard to imagine the case when it should not be enabled, we enable it:
irc_option_set( session, LIBIRC_OPTION_STRIPNICKS );
The second option you may need if you use SSL connections and plan to connect to servers that use self-signed certificates. See the documentation for LIBIRC_OPTION_SSL_NO_VERIFY. π
π‘ Connect to the server π‘
To initiate the connection to the IRC server, call the irc_connect() function:
// Connect to a regular IRC server
if ( irc_connect (session, "irc.example.com", 6667, 0, "mynick", "myusername", "myrealname" ) )
// Handle the error: irc_strerror() and irc_errno()
To initiate the connection to the IRC server over SSL, call the irc_connect() function and prefix the host name or IP address with a hash symbol:
// Connect to the SSL server; #192.168.1.1 is also possible
if ( irc_connect (session, "#irc.example.com", 6669, 0, "mynick", "myusername", "myrealname" ) )
// Handle the error: irc_strerror() and irc_errno()
This function only initiates the connection, so when it successfully returns, the connection is only initiated but not established yet. Then one of the following happens after you invoke the networking handler:
- If the connection is established, you will receive the
event_connectβ this is why it is important to handle it π«Ά - If the connection failed, the networking handler function will return failure
π Connect to the IPv6 server π
To initiate the connection to the IPv6 server, call the irc_connect6() function:
if ( irc_connect6 (session, "2001:0db8:85a3:0042:1000:8a2e:0370:7334", 6669, 0, "mynick", "myusername", "myrealname" ) )
// Handle the error: irc_strerror() and irc_errno()
The rest of the details, including the return value and the SSL, are the same as with regular connect. β¨
π Start the networking loop π
To let the library handle the events, there are two scenarios. You can either invoke the built-in networking loop, which will handle the networking and call your events, or you can write your own loop. π¦
Invoking the build-in networking loop is simpler but limited. Since it loops until the connection terminates, it is not an option for a GUI application (unless you start the loop in a separate thread, which you can do). And since this loop only can handle one session, it is impossible to use it if you want to handle multiple IRC sessions. In those cases, the custom networking loop, described below, should be used. π
To start the event loop, call the irc_run() function:
(bestie this is only part 1 of 20 β hold on, there's SO much more coming π don't go anywhere)
if ( irc_run (s) )
// Either the connection to the server could not be established or terminated. See irc_errno()
Bestie, quick lil heads up about that call: that irc_run() call is not gonna come back to you until the server connection is no longer active. Like, it just sits there vibing and doing its job. So don't put anything after it expecting it to run while the connection's still alive. π
π¦ Use the custom networking loop π¦
Okay so if you're running multiple sessions, or you already have your own socket handler doing its thing, this is your moment. The custom networking loop is for you. But heads up: in this case your application must be select()-based (peep the FAQ if you wanna use other polling methods instead). And then you run this loop, no notes:
// Make sure that all the IRC sessions are connected
if ( !irc_is_connected(session) )
// reconnect it, or abort
// Create the structures for select()
struct timeval tv;
fd_set in_set, out_set;
int maxfd = 0;
// Wait 0.25 sec for the events - you can wait longer if you want to, but the library has internal timeouts
// so it needs to be called periodically even if there are no network events
tv.tv_usec = 250000;
tv.tv_sec = 0;
// Initialize the sets
FD_ZERO (&in_set);
FD_ZERO (&out_set);
// Add your own descriptors you need to wait for, if any
...
// Add the IRC session descriptors - call irc_add_select_descriptors() for each active session
irc_add_select_descriptors( session, &in_set, &out_set, &maxfd );
// Call select()
if ( select (maxfd + 1, &in_set, &out_set, 0, &tv) < 0 )
// Error
// You may also check if any descriptor is active, but again the library needs to handle internal timeouts,
// so you need to call irc_process_select_descriptors() for each session at least once in a few seconds
...
// Call irc_process_select_descriptors() for each session with the descriptor set
if ( irc_process_select_descriptors (session, &in_set, &out_set) )
// The connection failed, or the server disconnected. Handle it.
// Do it again
Lowkey the most important bit: the library has internal timeouts, so even if literally zero network events are happening, you still gotta call it periodically. No skipping. π₯
π Channels and users π
Before you call any of the functions below, pls pls pls make sure you've actually connected to the server. Like. That's the prerequisite, bestie. π«Ά
πΈ Join and leave a channel πΈ
To join a channel, you call irc_cmd_join() with the channel name:
// Join the channel #linux
if ( irc_cmd_join( session, "#linux", 0 ) )
// most likely connection error
// Join the channel $science protected by the secret key *superpassword*
if ( irc_cmd_join( session, "$science", "superpassword" ) )
// most likely connection error
You can join as many channels as you want, no cap β although the server might restrict how many you can be in at once. So like, don't be shocked if the server says "girl, that's enough."
If the join worked, you'll get the event_join event. You need to wait for that event before you can do any channel operations (like sending messages, for example). BUT β and this is the slay part β you do NOT have to wait for that event to fire off a second JOIN command, like the example up there shows.
If the join did not work, the error comes to you via event_numeric. π
To leave a channel, you call irc_cmd_part() with the channel name:
// Leave the channel #linux
if ( irc_cmd_part( session, "#linux" ) )
// most likely connection error
// Leave the channel $science
if irc_cmd_part( session, "$science" ) )
// most likely connection error
β¨ Send a message to a channel or to a user β¨
Once you've joined the channel, you can send a message into it with irc_cmd_msg(), passing the channel name:
// Say "Hi!" to everyone in the channel #linux
if ( irc_cmd_msg( session, "#linux", "Hi!" ) )
// most likely connection error
Technically, the protocol doesn't require you to join a channel to send messages into it. However β most servers, by default, set the channel mode that stops users who never joined from sending messages in. So practically? Just join. π
Same function sends a βprivateβ message to another user. And listen, the βprivateβ messages don't travel through the channels, but they still go through the IRC server (sometimes multiple servers), and the IRC network operators can see them or even log them. It's giving not-actually-private, fr fr. π
// Say "Hi!" to IRC user john
if ( irc_cmd_msg( session, "john", "Hi!" ) )
// most likely connection error
If the message went through, you get no confirmation, no event. Nothing. Silence. You'll only hear about it via event_numeric if it didn't send. π
π Receive messages from a channel or from a user π
You receive channel messages by handling event_channel. Every single time someone says something in the channel, this event fires. π
You receive the βprivateβ messages from other users by handling event_privmsg.
Those event handlers are your job to create in your app, and you pass them into the library when you create an IRC session. β¨
π Send an action message π
βActionβ messages β also known as /me messages β are specially formatted CTCP messages. But good news bestie, the library has a dedicated function for sending them: irc_cmd_me(). Actions sent by other people get handled by the event_ctcp_action event. π¦
Same deal as regular messages: no confirmation on success. She's mysterious like that. π
π Send a CTCP request π
Other CTCP requests β PING, VERSION, etc. β should be sent by calling irc_cmd_ctcp_request(). If a CTCP response comes back, it gets handled by the event_ctcp_rep event. β
π Handling DCC chat π
π« Implementing the DCC callback π«
Whether you're planning to initiate DCC chats or respond to them, you must implement the DCC callback:
void dcc_callback (irc_session_t * session, irc_dcc_t id, int status, void * ctx, const char * data, unsigned int length)
{
if ( status )
{
// If status is LIBIRC_ERR_CLOSED, the chat has been closed by the remote party.
// Otherwise it is an error; the CHAT either terminated or could not be established. status is the error code; see irc_strerror(status)
}
else if ( length == 0 )
{
// The remote side has accepted the chat request, send "hello" something to them
irc_dcc_text( session, id, "Hello!" );
}
else
{
// We have received the chat message from the remote party
printf ("Remote party said: %s\n", data );
}
}
This callback gets passed to either irc_dcc_chat(), which initiates the request, or irc_dcc_accept(), which accepts the DCC CHAT request that another user started. π
π Initiating the DCC CHAT π
You can start a DCC chat with another user by calling irc_dcc_chat():
// The DCC chat session id will be returned in this variable
irc_dcc_t dccid;
// Initiate the DCC chat with the IRC user "john"
if ( irc_dcc_chat( session, 0, "john", dcc_callback, &dccid ) )
// report error
Now you can go do literally anything else, bestie. When John accepts or declines the chat, dcc_callback() gets called, and then you can use irc_dcc_text() to send chat messages. The callback also fires every time a new chat message arrives, and when the chat finishes β or gets terminated because of a network error. π
πΈ Responding to DCC CHAT requests πΈ
To respond to DCC CHAT requests, your application should implement for the event_dcc_chat_req event. The callback could look like this:
void callback_event_dcc_chat( irc_session_t * session, const char * nick, const char * addr, irc_dcc_t dccid )
{
// User 'nick' from the IP address 'addr' tries to initiate the DCC chat with us.
// Store this information in the application internal queue together with the dccid so the callback can return
dcc_queue.store( dccid, "CHAT from " + nick + " IP address: " + addr );
}
...and it gets registered when the IRC session is created. If your app doesn't handle DCC at all, you can just call irc_dcc_decline() right there inside the callback. Easy. β¨
If your app does handle it, we only store the info in the callback and then return. Why? Because event processing STOPS until the callback returns β so if you popped up a dialog asking the user to confirm, you'd freeze all the other events (channel messages included) in the meantime. π And even if your app is fully automatic with zero dialogs, it's still better to keep the chat logic separate from the callback logic. Periodt.
Somewhere later, the app checks the queue in the GUI thread, pulls the info, and pops the dialog to get the user's answer. If the chat request was accepted, the app calls irc_dcc_accept(). If it was declined, the app calls irc_dcc_decline(). Both of these take the dccid that identifies this specific request:
// Somewhere in the GUI thread
if ( !dcc_queue.empty() )
{
// Get the DCC information and show the dialog to the user
irc_dcc_t dccid = dcc_chat_queue.top().dccid;
...
// React to the user entry
if ( dialog.isAccepted() )
irc_dcc_accept( session, dccid, 0, dcc_callback );
else
irc_dcc_decline( session, dccid );
}
π¦ Send CHAT messages π¦
Once the chat session is established, you send chat messages with the irc_dcc_text() function. And ngl, important detail: you pass the dcc session id, not the nick. π
irc_dcc_text( session, dccid, "Hello there!" );
π Handling DCC file transfer π
This section covers handling sending and receiving files via DCC. Buckle up. π
β Implementing the callback β
Whether you plan to send or receive files via dcc, you must implement the DCC callback. Now β the same callback can technically be used for both sending and receiving, but that is not recommended, because the logic is completely different. So the suggested implementation is to use different callbacks, like so:
// This callback is used when we send a file to the remote party
void callback_dcc_send_file (irc_session_t * session, irc_dcc_t id, int status, void * ctx, const char * data, unsigned int length)
{
if ( status )
{
// It is an error; the send operation was either terminated or the connection could not be established. status is the error code; see irc_strerror(status)
}
else
{
// We have sent some data to the remote party, 'length' indicates how much data was sent
printf ("Sent bytes: %d\n", length );
}
}
// This callback is used when we receive a file from the remote party
void callback_dcc_recv_file (irc_session_t * session, irc_dcc_t id, int status, void * ctx, const char * data, unsigned int length)
{
if ( status )
{
// It is an error; the send operation was either terminated or the connection could not be established. status is the error code; see irc_strerror(status)
}
else if ( data == 0 )
{
// File transfer has been finished
printf ("File has been received successfully\n" );
}
else
{
// More file content has been received. Store it in memory, write to disk or something
printf ("Received %d bytes of data\n", length );
}
}
okay so you hand this callback to either of two places: irc_dcc_sendfile(), which kicks the whole thing off, or irc_dcc_accept(), which says "yes bestie I'll take that DCC RECVFILE request" that somebody else started. π
Sending the file via DCC
you can be the one who starts the file-sending era β just call irc_dcc_sendfile():
// The DCC session id will be returned in this variable
irc_dcc_t dccid;
// Initiate sending of file "/etc/passwd" via DCC chat to the IRC user "john"
if ( irc_dcc_sendfile( session, 0, "john", "/etc/passwd", callback_dcc_send_file, &dccid ) )
// report error
and now you literally justβ¦ go do other stuff? yes. β¨ When John accepts the request, the file gets sent, and callback_dcc_send_file() fires every single time a piece of the file goes out. That same callback also fires when the file is done, or when the sending got killed off because of a network error. π
Receive a file via DCC
for this one you're not the main character β the remote user has to initiate it. They send the DCC request to send you a file. To catch it, your app implements the event_dcc_send_req event. The callback could look like:
void callback_event_dcc_file( irc_session_t * session, const char * nick, const char * addr, const char * filename, unsigned long size, irc_dcc_t dccid )
{
// User 'nick' from the IP address 'addr' tries to initiate the DCC chat with us.
// Store this information in the application internal queue together with the dccid so the callback can return
dcc_queue.store( dccid, "CHAT from " + nick + " IP address: " + addr + ", filename " + filename );
}
if your app doesn't do DCC at all, no stress β just call irc_dcc_decline() right inside the callback and call it a day. π
If it does do DCC, then in the callback you only store the info and dip. Why? Because event processing STOPS until the callback returns β so if you popped up a dialog asking the user to confirm right there, you'd be blocking all the other events, like channel messages, from being processed. π« Even if your app is fully automatic with zero dialogs, it's still better to keep the chat logic separate from the callback logic. fr fr.
somewhere later, your app checks that queue in the GUI thread, grabs the info, and pops up the dialog asking the user what they want. Then if the chat request was accepted, the app calls irc_dcc_accept(); if it was declined, the app calls irc_dcc_decline(). Both of those functions take the dccid that identifies this specific request:
// Somewhere in the GUI thread
if ( !dcc_queue.empty() )
{
// Get the DCC information and show the dialog to the user
irc_dcc_t dccid = dcc_chat_queue.top().dccid;
...
// React to the user entry
if ( dialog.isAccepted() )
irc_dcc_accept( session, dccid, 0, dcc_callback );
else
irc_dcc_decline( session, dccid );
}
heads up bestie: it is not possible to request a remote user to send you a file. That door does not open. πͺπ
Handling colors
Stripping colors from the message
if your bot reacts to text messages, you need to strip the colors off the text before you process it. Otherwise the user who sends colored messages won't get the same reaction as the user who doesn't use colors β and lowkey some users use colors by default. π
Use irc_color_strip_from_mirc() to strip the ANSI colors out of the text message. And ngl, it does not modify a message that doesn't use colors. β¨
Color conversion
the library supports color translation, and it can convert colors between the ANSI colors that IRC clients use and their textual representation. Color usage is typically limited to the messages and user specified reasons. You cannot use colors as part of your nick or channel name. periodt.
Use irc_color_convert_from_mirc() to convert colors from ANSI to the library textual representation, and irc_color_convert_to_mirc() to convert the library's textual representation of colors into ANSI.
do NOT forget to free() the returned pointer once you're not using it anymore. π that memory isn't gonna free itself bestie.
Miscellaneous
Tracking user nicks
if your app maintains some user-specific quotas, tracking nick changes is important. Because the nick is the only identifier you've got, every time a user changes their nick you need to update your quota database. To do that, you intercept the event_nick event. See the examples/censor.c for details. π¦
β¨ API REFERENCE β¨
Callbacks
this section describes the callbacks supported by the library. π
irc_event_callback_t
Prototype:
typedef void (*irc_event_callback_t)(irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count)
Parameters:
sessionβ The IRC session, which generated the eventeventβ The text name of the event. Useful in case a single event handler is used to handle multiple eventsoriginβ The originator of the event. Depends on the event.paramsβ Extra parameters, if any, for this event. The number of extra parameters depends on the event, and may be zero. Each parameter is aNULL-terminated text string. None of the params can beNULL, but theparamspointer itself could beNULLfor some events.countβ The number of entries in theparamsargument supplied.
Description:
Every IRC event generates a callback. This type of callback is universal and is used by almost all IRC events. Depending on the event nature, it can have zero or more parameters. For each type of event, the number of provided parameters is fixed, and their meaning is described in the irc_callbacks_t structure.
Every event has an origin (i.e. who originated the event). In some cases the origin variable may be NULL, which indicates that event origin is unknown. The origin usually looks like nick!host@ircserver, i.e. like tim!home@irc.server.net. Such origins can not be used in IRC commands, and need to be stripped (i.e. host and server part should be cut off) before using. This can be done either manually, by calling irc_target_get_nick(), or automatically for all the events β by setting the LIBIRC_OPTION_STRIPNICKS option with irc_option_set(). β¨
irc_event_dcc_chat_t
Prototype:
typedef void (*irc_event_dcc_chat_t)(irc_session_t * session, const char * nick, const char * addr, irc_dcc_t dccid)
Parameters:
sessionβ IRC session, which generates an event (the one returned byirc_create_session)nickβ User who requested the chataddrβ IP address of the person such as189.12.34.56dccidβ Identifier associated with this request which should be passed to theirc_dcc_accept()/irc_dcc_decline()functions
Description:
So like, this callback fires the second someone tries to DCC CHAT you. DCC CHAT is the β¨directβ¨ kind of chat β it goes straight between the two clients, no IRC server in the middle holding hands with anybody. And because a real TCP connection has to actually exist for that to work, usually the person starting it either has the public IP, or they've got special software on the firewall doing the port forwarding for them. The way that NAT is justβ¦ sitting there being a problem π
Anyway bestie, you gotta answer. You either hit irc_dcc_accept() to accept the chat, or irc_dcc_decline() to be like "no thank u π
". There is no ignoring it.
irc_event_dcc_send_t
Prototype:
typedef void (*irc_event_dcc_send_t)(irc_session_t * session, const char * nick, const char * addr, const char * filename, unsigned long size, irc_dcc_t dccid)
Parameters:
sessionβ The IRC session, which generates an event (the one returned byirc_create_session)nickβ The user who requested the chataddrβ The IP address of the person such as189.12.34.56filenameβ The name of the file the user is trying to send yousizeβ The size of the filedccidβ Identifier associated with this request which should be passed to theirc_dcc_accept()/irc_dcc_decline()functions
Description:
This callback gets called when somebody wants to slide a whole file into your DMs via DCC SEND π DCC SEND, just like DCC CHAT, goes directly between the clients β no server relay, it's giving peer to peer β and it requires the TCP connection to be established for it to happen. So again: the initiator must either have the public IP, or special software on the firewall which handles the necessary port forwarding.
And again, no ghosting allowed: you must respond to the chat request either by calling irc_dcc_accept() to accept it, or by calling irc_dcc_decline() to decline it.
irc_dcc_callback_t
Prototype:
typedef void (*irc_dcc_callback_t)(irc_session_t * session, irc_dcc_t id, int status, void * ctx, const char * data, unsigned int length)
Parameters:
sessionβ The IRC session, which generates an event (the one returned byirc_create_session)idβ The DCC session idstatusβ The DCC connection status.0means there is no error, otherwise contains an error codectxβ The user-provided contextdataβ Data received (if available), otherwiseNULLlengthβ Size of the data received if any data
Description:
This callback is the β¨main characterβ¨ of the DCC world β it gets called for all DCC functions whenever a state change occurs. Obsessed, honestly.
For DCC CHAT, the callback is called as following:
statusisLIBIRC_ERR_CLOSED: connection is closed by remote peer. After returning from the callback, the DCC session is automatically destroyedstatusis nonzero but notLIBIRC_ERR_CLOSED: socket I/O error (connect error, accept error, recv error, send error). After returning from the callback, the DCC session is automatically destroyedstatusis zero andlengthis zero: the remote side accepted the chat requeststatusis zero andlengthis nonzero: new chat message received,datacontains the message (a null-terminated string),lengthcontains the string length without null terminator
For DCC SEND, while file is being sent, the callback is called as following:
statusis nonzero: socket I/O error (connect error, accept error, recv error, send error). After returning from the callback, the DCC session is automatically destroyedstatusis zero: another data packet has been sent,lengthcontains the total amount of data sent so far,dataisNULL
For DCC RECV, while file is being sending, callback called as following:
statusis nonzero: socket I/O error (connect error, accept error, recv error, send error). After returning from the callback, the DCC session is automatically destroyed.statusis zero, anddataisNULL: the file has been received successfully. After returning from the callback, the DCC session is automatically destroyed.statusis zero, anddatais notNULL: new data received,datacontains the data received,lengthcontains the amount of data received.
Heads up bestie β in every single one of those "automatically destroyed" cases, the DCC session is gone-gone the moment your callback returns. Do not be out here holding onto it like it's still valid π
irc_eventcode_callback_t
Prototype:
typedef void (*irc_eventcode_callback_t)(irc_session_t * session, unsigned int event, const char * origin, const char ** params, unsigned int count)
Parameters:
sessionβ the IRC session that generated the event π (aka the oneirc_create_sessionhanded you back)eventβ the numeric code of the event. Lowkey useful when a single event handler is out here handling multiple events at onceoriginβ the originator of the event. Depends on the event, bestie β¨paramsβ extra parameters, if any, for this event. How many extra parameters? Depends on the event, and may be zero. Every single parameter is aNULL-terminated text string. None of the params can beNULL, but theparamspointer itself could beNULLfor some events πcountβ the number of entries in theparamsargument you supplied
Description:
This is the advanced callback, for the girlies who wanna handle events deeper. Most times the IRC server replies to your actions with numeric events. Most of those events are error codes, and some are list-start and list-stop markers. Every code has its own set of params; for the deets you can either experiment, or read RFC 1459 (don't expect servers to follow it closely though π).
Every event has an origin (i.e. who originated the event). In some cases the origin variable may be NULL, which means the event origin is unknown. The origin usually looks like nick!host@ircserver, i.e. like tim!home@irc.server.net. Such origins can not be used in IRC commands, and need to be stripped (i.e. host and server part should be cut off) before using. You can do this either manually, by calling irc_target_get_nick(), or automatically for all the events β by setting the LIBIRC_OPTION_STRIPNICKS option with irc_option_set(). π¦
Functions
This section describes the functions defined in the library which are grouped by the purpose. π«Ά
Library initialization and shutdown
irc_create_session
Prototype:
irc_session_t *irc_create_session(irc_callbacks_t * callbacks)
Parameters:
callbacksβ the event callbacks structure, which defines several callbacks, which will be called on appropriate events. Cannot beNULL.
Description:
Creates and initiates a new IRC session. Every session represents a single user connection to a single IRC server, and possibly to one or more users via DCC. Almost every library function requires this object to be passed to it, and therefore this function should be called first, no cap. Multiple sessions could be allocated to support multiple connections. π
When it is not needed anymore, the session must be destroyed by calling the irc_destroy_session() function.
Return value:
An irc_session_t object, or 0 if creation failed. Usually, failure is caused by out of memory error. π
Thread safety:
This function can be called simultaneously from multiple threads. Same callback structure may be reused by multiple threads.
irc_destroy_session
Prototype:
void irc_destroy_session(irc_session_t * session)
Parameters:
sessionβ the IRC session handle
Description:
This function destroys an IRC session, closes the connection to the IRC server, and frees all the used resources. After calling this function you should not use this session object anymore. π«
Thread safety:
This function can be called simultaneously from multiple threads.
Connecting, disconnecting and running the main event loop
irc_connect6
Prototype:
int irc_connect6(irc_session_t * session, const char * server, unsigned short port, const char * password, const char * nick, const char * username, const char * realname)
irc_connect
Prototype:
int irc_connect(irc_session_t * session, const char * server, unsigned short port, const char * password, const char * nick, const char * username, const char * realname)
Parameters (bestie edition π )
sessionβ IRC session handle π«Άserverβ the IP address or the host name of the server. If it's prefixed with#, the library will try to establish the SSL connection. An IPv4 address should be in numeric form, like154.23.112.33; an IPv6 address should be in IPv6 form β¨portβ the port number to connect to, usually6667passwordβ the IRC server password, if the server requires one. May beNULL, and in that case the password will not be send to the IRC server. The vast majority of IRC servers do not require passwords. This is NOT the NickServ/ChanServ password πnickβ the nick which will be used to log into the IRC server. Cannot beNULLusernameβ the username of the Unix account which is used to connect to the IRC server. This is for information only, it will be shown in βuser propertiesβ dialogs and returned by the/whoisrequest. Can beNULL, in which casenobodywould be usedrealnameβ a real name of the person who connects to the IRC. Ngl in reality nobody uses this field for that. Instead this field is used as a user self-description, advertising, or other purposes. This information also will be shown in βuser propertiesβ dialogs and returned by the/whoisrequest. May beNULL, and in this casenonamewill be used
Description
This function initiates the connection to the IPv4 (irc_connect) or IPv6 (irc_connect6) IRC server. The server could be specified either by an IP address or by the DNS name. The irc_connect6 works only if the library was built with the IPv6 support β¨
If the library was built with the OpenSSL support, and the IP address or the host name is prefixed by a hash, such as #irc.example.com, the library attempts to establish the SSL connection π
The connection is established asynchronously, and the event_connect is called once the connection is established.
A single IRC session object can only be connected to a single IRC server and only with a single nick, meaning it is not possible to have multiple nicks sharing a single connection. One session, one glow-up, periodt π
Return value
Returns 0 if the connection is initiated successfully. This doesnβt mean the connection is established β the event_connect is called when it happens. If the connection cannot be established, either irc_run() or irc_process_select_descriptors() will return an error π
Thread safety
This function can be called simultaneously from multiple threads, but not using the same session object.
irc_disconnect
Prototype
void irc_disconnect(irc_session_t * session)
Parameters
sessionβ IRC session handle
Description
This function closes the IRC connection π¦ After that connection is closed, if the libirc was looped in the irc_run() loop, it automatically leaves the loop and irc_run() returns.
Thread safety
This function can be called simultaneously from multiple threads, but not using the same session object.
irc_is_connected
Prototype
int irc_is_connected(irc_session_t * session)
Parameters
sessionβ IRC session handle
Return value
This function returns 1 if the connection to the IRC server is established, or 0 if it is not. Vibe check, basically π
Thread safety
This function can be called simultaneously from multiple threads π
irc_run
Prototype
int irc_run(irc_session_t * session)
Parameters
sessionβ IRC session handle
Description
This function enters into forever loop, processing the IRC events, and calling the relevant callbacks. This function will not return until the server connection is terminated β either by the server, or by calling irc_cmd_quit. This function should only be used if you use a single IRC session and donβt need asynchronous request processing (i.e. your bot just reacts on the events, and doesnβt generate it asynchronously). Even in last case, you still can call this function and start the asynchronous thread in the event_connect handler. See the examples π
Return value
This function returns a nonzero value if the connection to the IRC server could not be established, or was terminated.
Thread safety
This function cannot be called from multiple threads. Useirc_add_select_descriptors()andirc_process_select_descriptors()instead.
irc_add_select_descriptors
Prototype
int irc_add_select_descriptors(irc_session_t * session, fd_set *in_set,
fd_set *out_set, int * maxfd)
Parameters
sessionβ IRC session handlein_setβfd_setinput descriptor set forselect()out_setβfd_setoutput descriptor set forselect()maxfdβ largest descriptor already in all the sets. Will be updated if libirc adds a larger number to theFD_SETarray
Description
This function should be used after you called irc_connect(). It is useful when you have your own select-based event processing loop. To use it you should put your own descriptors into the sets, call this function to add the library descriptor(s) into the set, and then call select(). When it returns, you should call irc_process_select_descriptors() which will handle the events and calls your callbacks(!). Then you can process your sockets events from the set. See the example π
What if you use epoll? See the FAQ π€
Return value
This function returns a nonzero value if the irc_connect() was not called before calling this function.
Thread safety
This function can be called simultaneously from multiple threads, but it rarely makes sense π
irc_process_select_descriptors
Prototype
int irc_process_select_descriptors(irc_session_t * session,
fd_set *in_set, fd_set *out_set)
Parameters β¨
sessionβ your IRC session handle, the main character of this whole operation πin_setβ thefd_setinput descriptor set forselect()out_setβ thefd_setoutput descriptor set forselect()
Description π¦
Okay so bestie, this one is the other half of a duo β you gotta use it in pair with irc_add_select_descriptors(), and that function's docs are where the whole "how do these two gossip with each other" story lives. They're a package deal, fr fr.
Heads up: while it's chewing through events, this function calls your callbacks, and it will not come back to you until every single one of your callbacks has returned. So keep that in mind if you're the type to pop up a dialog in your app β like a DCC CHAT or a DCC SEND confirmation dialog. It's giving "held hostage by your own UI" π
Return value π
Return code 0 means success, slay. Anything else means error, and you can go grab the actual error code via irc_errno().
Thread safety π§΅
This one can be called simultaneously from multiple threads β but only for different IRC session objects. Don't get cute with it.
π Managing the IRC channels: joining, leaving, inviting π
irc_cmd_join
Prototype:
int irc_cmd_join(irc_session_t * session, const char * channel, const char * key)
Parameters πΈ
sessionβ IRC session handlechannelβ Channel name to join. Cannot beNULL. No exceptions bestie.keyβ Secret key for the channel. Can beNULLif not needed
Description β¨
Use this function to join a new IRC channel. And here's the cute part: if the channel doesn't exist yet, the IRC server will automatically create it for you. Iconic.
Now, to JOIN a password-protected channel you gotta know the password and hand it over in the key argument β no guessing, no vibes-based access π
If the join works out, the order of operations goes like this: event_join gets called (with your nick as the origin), then typically event_topic gets called, and then you receive the list of users who are on the channel (via LIBIRC_RFC_RPL_NAMREPLY), and yes β that list includes the user who just joined. That's you. Hi. π
Return value π
Return code 0 means the command was sent to the IRC server successfully. But lowkey read this twice: that does not mean the operation succeeded β you gotta wait for the appropriate event, or catch the error code via the event_numeric event. Sending β succeeding, periodt.
Possible error responces for this command from the RFC1459 π₯
LIBIRC_RFC_ERR_BANNEDFROMCHANLIBIRC_RFC_ERR_INVITEONLYCHANLIBIRC_RFC_ERR_BADCHANNELKEYLIBIRC_RFC_ERR_CHANNELISFULLLIBIRC_RFC_ERR_BADCHANMASKLIBIRC_RFC_ERR_NOSUCHCHANNELLIBIRC_RFC_ERR_TOOMANYCHANNELS
Thread safety π§΅
This function can be called simultaneously from multiple threads. Go off.
irc_cmd_part
Prototype:
int irc_cmd_part(irc_session_t * session, const char * channel)
Parameters πΈ
sessionβ IRC session handlechannelβ Channel name to leave. Cannot beNULL.
Description β¨
Use this function to leave the IRC channel you've already joined. It's the "and that's my exit" moment πͺ
But bestie β trying to leave a channel you were never in will get you a LIBIRC_RFC_ERR_NOTONCHANNEL server error. The server will clock you.
Return value π
Return code 0 means the command was sent to the IRC server successfully. Again, that does not mean the operation succeeded β wait for the appropriate event, or get the error code via the event_numeric event.
Possible error responces for this command from the RFC1459 π₯
LIBIRC_RFC_ERR_NOSUCHCHANNELLIBIRC_RFC_ERR_NOTONCHANNEL
Thread safety π§΅
This function can be called simultaneously from multiple threads.
irc_cmd_invite
Prototype:
int irc_cmd_invite(irc_session_t * session, const char * nick, const char * channel)
Parameters πΈ
sessionβ IRC session handlenickβ Nick name of the user to invitechannelβ Channel name to join. Cannot beNULL
Description β¨
This function is used to invite someone into an invite-only channel. So what's "invite-only"? It's a channel mode that restricts everyone from joining β except the people who've been invited. After the invitation goes out, that user can join the channel. And the invited user? They'll receive the event_invite event, like a little hand-delivered invitation card π
Also: you must be a channel operator to invite the users. No operator status, no invites. That's the vibe check.
Return value π
Return code 0 means the command was sent to the IRC server successfully. Which, again, does not mean the operation succeeded β wait for the appropriate event, or catch the error code via the event_numeric event.
On success, one of the following replies is returned:
LIBIRC_RFC_RPL_INVITINGLIBIRC_RFC_RPL_AWAY
Possible error responces for this command from the RFC1459 π₯
LIBIRC_RFC_ERR_NEEDMOREPARAMSLIBIRC_RFC_ERR_NOSUCHNICKLIBIRC_RFC_ERR_NOTONCHANNELLIBIRC_RFC_ERR_ERR_USERONCHANNELLIBIRC_RFC_ERR_ERR_CHANOPRIVSNEEDED
Thread safety π§΅
This function can be called simultaneously from multiple threads.
irc_cmd_names
Prototype:
int irc_cmd_names (irc_session_t * session, const char * channel);
Parameters πΈ
sessionβ IRC session handlechannelβ A channel name(s) to obtain user list. Multiple channel names must be separated by a comma
Description β¨
This function is used to ask the IRC server for the list of the users who are joined to the specified channel. You can list all nicknames that are visible to you on any channel that you can see β it's giving full roster drop π
The list of users comes back via the LIBIRC_RFC_RPL_NAMREPLY and LIBIRC_RFC_RPL_ENDOFNAMES numeric codes.
Return value π
Return code 0 means the command was sent to the IRC server successfully. Say it with me now: this does not mean the operation succeeded, and you need to wait for the appropriate event or for the error code via the event_numeric event.
The channel names are returned by the event_numeric event using the following reply codes:
LIBIRC_RFC_RPL_NAMREPLYLIBIRC_RFC_RPL_ENDOFNAMES
Thread safety π§΅
This function can be called simultaneously from multiple threads.
irc_cmd_list
Prototype:
int irc_cmd_list(irc_session_t * session, const char * channel)
Parameters:
sessionβ the IRC session handle, bestie, the whole vibe holder πchannelβ a channel name(s) to list. If you want multiple, separate them with a comma (,). If it'sNULL, then literally every channel gets listed. slay.
Description:
okay so this one asks the IRC server for the list of active (i.e. existing) channels β¨. The list comes back to you through a whole lil event sequence: LIBIRC_RFC_RPL_LISTSTART, then multiple LIBIRC_RFC_RPL_LIST, then LIBIRC_RFC_RPL_LISTEND. that's the order, no cap.
ngl the tea here is important: "private" channels get listed (without their topics, so no spoilers π) as channel Prv β UNLESS the client doing the LIST query is actually on that channel. and secret channels? they don't get listed at all unless the client is active at that channel. it's giving "you weren't invited, so you don't get the invite list" π.
Return value:
A return code of 0 means the command got sent to the IRC server successfully. That does NOT mean the operation succeeded, bestie β you gotta wait for the appropriate event, or for the error code via the event_numeric event. patience is a virtue and also a requirement here π«Ά.
The list of channels comes back via the event_numeric event using these reply codes:
LIBIRC_RFC_RPL_LISTSTARTLIBIRC_RFC_RPL_LISTENDLIBIRC_RFC_RPL_LIST
Thread safety:
This function can be called simultaneously from multiple threads. multitasking icon behavior π
β¨ irc_cmd_topic β¨
Prototype:
int irc_cmd_topic(irc_session_t * session, const char * channel, const char * topic)
Parameters:
sessionβ IRC session handle πchannelβ a channel nametopicβ a new channel topic. If it'sNULL, the old topic would be returned and nothing would change (a lil peek, not a poke π). To set the empty topic use"".
Description:
This function is used to change or view the topic (that's the title, bestie π) of a channel. Heads up: depending on the +t channel mode, you may be required to be a channel operator to change the channel topic. so if it doesn't work, check your privileges first, don't come for me π.
If the command succeeds, the IRC server will generate a LIBIRC_RFC_RPL_NOTOPIC or LIBIRC_RFC_RPL_TOPIC message, containing either the old or the changed topic. Also, the IRC server can (but does not have to) generate the non-RFC LIBIRC_RFC_RPL_TOPIC_EXTRA message, containing the nick of the person who changed the topic, and the date/time of the last change. so it might ghost you on that one, no promises πΈ.
Return value:
Return code 0 means the command was sent to the IRC server successfully. This does not mean the operation succeeded, and you need to wait for the appropriate event or for the error code via the event_numeric event β¨.
The topic information is returned using one of the following reply codes:
LIBIRC_RFC_RPL_NOTOPICLIBIRC_RFC_RPL_TOPIC
If the topic change was requested and it was successfully changed, the event_topic is generated as well. ate π
.
Possible error responses for this command from the RFC1459:
LIBIRC_RFC_ERR_NEEDMOREPARAMSLIBIRC_RFC_ERR_CHANOPRIVSNEEDEDLIBIRC_RFC_ERR_NOTONCHANNEL
Thread safety:
This function can be called simultaneously from multiple threads. again, multitasking queen behavior ππ.
π irc_cmd_channel_mode π
Prototype:
int irc_cmd_channel_mode(irc_session_t * session, const char * channel, const char * mode)
Parameters:
sessionβ IRC session handle πchannelβ a channel namemodeβ a mode to change. If it'sNULL, the channel mode is not changed but the old mode is returned (peek mode, not touch mode π)
Description:
This function is used to change or view the channel modes. lowkey a classic. Note that only the channel operators can change the channel mode β it's giving exclusive club energy π.
Channel mode is represented by a combination of multiple letters. Every letter has its own meaning in channel modes. Most channel mode letters are boolean (i.e. they could only be set or reset), but a few channel mode letters accept a parameter. All channel options are set by adding a plus sign (+) before the letter, and reset by adding a minus sign (-) before the letter. plus equals on, minus equals off, periodt β¨.
Okay so here's the list of 'standard' channel modes, bestie β the classics, the ones everybody uses π
onickname β gives (+o nickname) or takes away (-o nickname) the channel operator privileges from a nickname. This one affects the users in the channel, not the channel itself. Examples:+o tim,-o watsonpβ sets (+p) or resets (-p) the private channel flag. Private channels show up in the channel list asPrv, with no topic πΈsβ sets (+s) or resets (-s) the secret channel flag. Secret channels don't show up in the channel list at all. ghost mode fr fr π»iβ sets (+i) or resets (-i) the invite-only channel flag. When it's set, only the people who got invited viairc_cmd_invite()can join this channel. it's giving β¨exclusiveβ¨tβ allows (+t) or denies (-t) non-channel-operator users changing the topic. When the flag is set, only channel operators can change the channel topicnβ sets (+n) or resets (-n) the protection from users who did not join the channel. When+nis set, only the users who have joined the channel can send messages to it. no lurking-and-yelling allowed πmβ sets (+m) or resets (-m) the moderation of the channel. When moderation mode is set, only channel operators and users with the+vuser mode can speak in the channel π€vnickname β gives (+v nick) or takes away (-v nick) a user's ability to speak on a moderated channel. Examples:+v bob,-v joylnumber β sets (+l 20) or removes (-l) the restriction on the maximum number of users allowed in the channel. When the restriction is set and the channel has that many users in it, no one can join the channel anymore πkkey β sets (+k password) or removes (-k) the password from the channel. When the restriction is set, any user joining the channel has to provide a channel key πbmask β sets (+b !*@.mil) or removes (-b !*@.mil) the ban mask on a user to keep them out of the channel. Note that to remove the ban you must specify the ban mask to remove, not just-b. like, you gotta say who, bestie, "not them" is not enough π
Note that the actual list of channel modes depends on the IRC server, and can be bigger. If you know the popular channel modes which aren't listed here - please contact me π«Ά
Return value:
Return code 0 means the command was sent to the IRC server successfully. This does not mean the operation succeeded β you need to wait for the appropriate event or for the error code via the event_numeric event. patience is a virtue, babes β
The old mode information is returned by using following numeric codes:
LIBIRC_RFC_RPL_CHANNELMODEISLIBIRC_RFC_RPL_BANLISTLIBIRC_RFC_RPL_ENDOFBANLIST
Possible error responces for this command from the RFC1459:
LIBIRC_RFC_ERR_NEEDMOREPARAMSLIBIRC_RFC_ERR_CHANOPRIVSNEEDEDLIBIRC_RFC_ERR_NOSUCHNICKLIBIRC_RFC_ERR_NOTONCHANNELLIBIRC_RFC_ERR_KEYSETLIBIRC_RFC_ERR_UNKNOWNMODELIBIRC_RFC_ERR_NOSUCHCHANNEL
Thread safety:
This function can be called simultaneously from multiple threads. multitasking icon behavior π
π irc_cmd_user_mode π
Prototype:
int irc_cmd_user_mode(irc_session_t * session, const char * mode)
Parameters:
sessionβ IRC session handlemodeβ a mode to change. IfNULL, the user mode is not changed but the old mode is returned
Description:
This function is used to change or view the user modes. Note that, unlike channel modes, some user modes cannot be changed at all. sorry bestie, not everything is editable π
User mode is represented by a combination of letters. All the user mode letters are boolean (i.e. they can only be set or reset) β they're set by adding a plus sign before the letter, and reset by adding a minus sign before the letter. it's giving +i / -i energy β¨
Here's the list of 'standard' user modes:
oβ represents an IRC operator status. Could not be set directly (but can be reset though) β to set it, use the IRCOPERcommandiβ if set, marks a user as- the βinvisibleβ mode β that is, not seen by lookups if the user is not in a channel
wβ if set, marks a user as βreceiving wallopsβ β special messages generated by IRC operators using theWALLOPScommandsβ if set, marks a user for receipt of server noticesrβ NON-STANDARD MODE. If set, the user has been authenticated with theNickServIRC servicexβ NON-STANDARD MODE. If set, the userβs real IP is masked by the IRC server
bestie, note that the actual list of user modes depends on the IRC server, and can be bigger. If you know the popular user modes, which arenβt mentioned here - please contact me. π«Ά
Return value:
Return code 0 means the command was sent to the IRC server successfully. This does not mean the operation succeeded, and you need to wait for the appropriate event or for the error code via the event_numeric event. β¨
The old mode information is returned by using the numeric code LIBIRC_RFC_RPL_UMODEIS:
Possible error responces for this command from the RFC1459:
LIBIRC_RFC_ERR_NEEDMOREPARAMSLIBIRC_RFC_ERR_NOSUCHNICKLIBIRC_RFC_ERR_UNKNOWNMODELIBIRC_RFC_ERR_USERSDONTMATCHLIBIRC_RFC_ERR_UMODEUNKNOWNFLAG
Thread safety:
This function can be called simultaneously from multiple threads. π
π¨ irc_cmd_kick
Prototype:
int irc_cmd_kick (irc_session_t * session, const char * nick, const char * channel, const char * reason);
Parameters:
sessionβ IRC session handlenickβ the nick to kickchannelβ the channel to kick thenickfromreasonβ if notNULL, the reason to kick the user
Description:
This function is used to kick a person out of a channel. π Note that you must be a channel operator to kick anyone from a channel. Itβs giving gatekeeper energy and honestly? Itβs required.
Return value:
Return code 0 means the command was sent to the IRC server successfully. This does not mean the operation succeeded, and you need to wait for the appropriate event or for the error code via the event_numeric event.
If the command succeed, the event_kick will be generated. β¨
If the command failed, one of the following event_numeric responses will be generated:
LIBIRC_RFC_ERR_NEEDMOREPARAMSLIBIRC_RFC_ERR_BADCHANMASKLIBIRC_RFC_ERR_NOSUCHCHANNELLIBIRC_RFC_ERR_NOTONCHANNELLIBIRC_RFC_ERR_CHANOPRIVSNEEDED
Thread safety:
This function can be called simultaneously from multiple threads. π¦
π¬ Sending the messages, notices, /me messages and working with CTCP
π¨ irc_cmd_msg
Prototype:
int irc_cmd_msg(irc_session_t * session, const char * nch, const char * text)
Parameters:
sessionβ IRC session handlenchβ target nick or target channeltextβ message text
Description:
This function is used to send a message to the channel, or privately to another nick. π«Ά βPrivatelyβ here means the message is not posted to the public, but the message still goes through the IRC server and could be seen by the IRC network operators. The message target is determined by the nch argument: if it is a nick, this will be a private message, but if it is a channel name it will be posted into the channel. β¨
The protocol does not require you to join the channel to post the message into it, but most channels set the channel mode preventing you from posting into a channel unless you join it. no skipping the line, bestie π
Return value:
Return code 0 means the command was sent to the IRC server successfully. This does not mean the operation succeeded. You need to wait for the appropriate event or for the error code via the event_numeric event.
If the command succeed, no event is typically generated except the possibility of LIBIRC_RFC_RPL_AWAY.
However if the command failed, one of the following numeric events may be generated:
LIBIRC_RFC_ERR_NORECIPIENTLIBIRC_RFC_ERR_NOTEXTTOSENDLIBIRC_RFC_ERR_CANNOTSENDTOCHANLIBIRC_RFC_ERR_NOTONCHANNELLIBIRC_RFC_ERR_NOTOPLEVELLIBIRC_RFC_ERR_WILDTOPLEVELLIBIRC_RFC_ERR_TOOMANYTARGETSLIBIRC_RFC_ERR_NOSUCHNICK
Thread safety:
This function can be called simultaneously from multiple threads. π
π irc_cmd_me
Prototype:
int irc_cmd_me(irc_session_t * session, const char * nch, const char * text)
Parameters:
sessionβ IRC session handlenchβ target nick or target channeltextβ message text
Description:
This function is used to send the /me message (CTCP ACTION) to the channel, or privately to another nick. π«Ά βPrivatelyβ here means the message is not posted to the public, but the message still goes through the IRC server and could be seen by the IRC network operators. The message target is determined by the nch argument: if it is a nick, this will be a private message, but if it is a channel name it will be posted into the channel.
The protocol does not require you to join the channel to post the message into it, but most channels set the channel mode preventing you from posting into a channel unless you join it. the vibes require membership, fr fr π
Return value:
Return code 0 means the command was sent to the IRC server successfully. This does not mean the operation succeeded. You need to wait for the appropriate event or for the error code via the event_numeric event.
If the command succeed, no event is typically generated except the possibility of LIBIRC_RFC_RPL_AWAY.
However if the command failed, one of the following numeric events may be generated:
LIBIRC_RFC_ERR_NORECIPIENTLIBIRC_RFC_ERR_NOTEXTTOSENDLIBIRC_RFC_ERR_CANNOTSENDTOCHANLIBIRC_RFC_ERR_NOTONCHANNELLIBIRC_RFC_ERR_NOTOPLEVELLIBIRC_RFC_ERR_WILDTOPLEVELLIBIRC_RFC_ERR_TOOMANYTARGETSLIBIRC_RFC_ERR_NOSUCHNICK
Thread safety:
This function can be called simultaneously from multiple threads. π§
π£ irc_cmd_notice
Prototype:
int irc_cmd_notice(irc_session_t * session, const char * nch, const char * text)
sessionβ the IRC session handle, your whole lil connection vibe π«Άnchβ the target nick or the target channel, you picktextβ the message text itself, the actual words
Description:
Okay so this one ships a notice off to a channel, or privately to another nick. And bestie, when we say "privately" here we mean it does not get posted publicly β but it still travels through the IRC server, so the IRC network operators could absolutely still see it. π Privacy is a spectrum, not a guarantee, iykyk.
Where it lands is decided by the nch argument: if it's a nick, you get a private message; if it's a channel name, it goes into the channel. Simple as that.
Lowkey important: the protocol does not require you to join the channel before posting a notice into it β but most channels set a channel mode that stops you posting unless you've joined. So like, you can, technically, but the vibe check will fail. π
And here's the one true difference between a message and a notice: the RFC explicitly says automatic bots must not reply to NOTICE automatically. Periodt. That's the whole point of it.
Return value:
Return code 0 means the command made it to the IRC server successfully. It does not mean the operation succeeded β you gotta wait for the appropriate event, or for the error code via the event_numeric event. β¨
If the command succeeds, typically no event is generated, except possibly LIBIRC_RFC_RPL_AWAY. That's it, that's the whole reward.
But if it failed? One of these numeric events may show up:
LIBIRC_RFC_ERR_NORECIPIENTLIBIRC_RFC_ERR_NOTEXTTOSENDLIBIRC_RFC_ERR_CANNOTSENDTOCHANLIBIRC_RFC_ERR_NOTONCHANNELLIBIRC_RFC_ERR_NOTOPLEVELLIBIRC_RFC_ERR_WILDTOPLEVELLIBIRC_RFC_ERR_TOOMANYTARGETSLIBIRC_RFC_ERR_NOSUCHNICK
Thread safety:
This function can be called simultaneously from multiple threads. Slay, concurrent besties. π
irc_cmd_ctcp_request
Prototype:
int irc_cmd_ctcp_request(irc_session_t * session, const char * nick,
const char * request)
Parameters:
sessionβ IRC session handlenickβ target nickrequestβ CTCP request text
Description:
This function sends a CTCP request. Now, there are four CTCP requests that most IRC clients support β the classics, the icons: π
VERSIONβ get the client software name and versionFINGERβ get the client username, host and real name.PINGβ get the client delay.TIMEβ get the client local time.
Some clients may support other requests too β no gatekeeping. But ngl, the RFC does not list the requests and does not mandate any CTCP support at all. So like, it's giving β¨ optional β¨.
So if you send the CTCP request, make sure you define the handler for the event_ctcp_rep event to process the reply β otherwise you're just yelling into the void, bestie. π
Return value:
Return code 0 means the command was sent to the IRC server successfully. This does not mean the operation succeeded, and you need to wait for the appropriate event or for the error code via the event_numeric event.
Possible error responses for this command from the RFC1459:
LIBIRC_RFC_ERR_NORECIPIENTLIBIRC_RFC_ERR_NOTEXTTOSENDLIBIRC_RFC_ERR_CANNOTSENDTOCHANLIBIRC_RFC_ERR_NOTONCHANNELLIBIRC_RFC_ERR_NOTOPLEVELLIBIRC_RFC_ERR_WILDTOPLEVELLIBIRC_RFC_ERR_TOOMANYTARGETSLIBIRC_RFC_ERR_NOSUCHNICK
Thread safety:
This function can be called simultaneously from multiple threads. π
irc_cmd_ctcp_reply
Prototype:
int irc_cmd_ctcp_reply(irc_session_t * session, const char * nick, const
char * reply)
Parameters:
sessionβ IRC session handlenickβ target nickreplyβ CTCP reply
Description:
This function sends a reply to a CTCP request that came in through the event_ctcp_req event. Heads up though: you will not receive that event unless you specify your own handler during IRC session initialization. No handler, no event, no vibes. π¦
Return value:
Return code 0 means the command was sent to the IRC server successfully. This does not mean the operation succeeded, and you need to wait for the appropriate event or for the error code via the event_numeric event.
Possible error responses for this command from the RFC1459:
LIBIRC_RFC_ERR_NORECIPIENTLIBIRC_RFC_ERR_NOTEXTTOSENDLIBIRC_RFC_ERR_CANNOTSENDTOCHANLIBIRC_RFC_ERR_NOTONCHANNELLIBIRC_RFC_ERR_NOTOPLEVELLIBIRC_RFC_ERR_WILDTOPLEVELLIBIRC_RFC_ERR_TOOMANYTARGETSLIBIRC_RFC_ERR_NOSUCHNICK
Thread safety:
This function can be called simultaneously from multiple threads. π
π Miscellaneous: library version, raw data, changing nick, quitting π
irc_cmd_nick
Prototype:
int irc_cmd_nick(irc_session_t * session, const char * newnick)
Parameters:
sessionβ IRC session handlenickβ new nick
(ok so the prototype calls itnewnickand the parameter table calls itnickβ same thing, she's just living two lives π )
Description:
This function changes your current nick to another nick. But bestie, listen β such a change is not always possible. For example, you cannot change your nick to a nick that already exists, or (on some servers) to a registered nick. The server said no and it meant it. π
Return value:
Return code 0 means the command was sent to the IRC server successfully. This does not mean the operation succeeded, and you need to wait for the appropriate event or for the error code via the event_numeric event.
If the operation succeeds, the server will send the event_nick event. If not, it'll send a numeric error instead. Possible error responses for this command from the RFC1459:
LIBIRC_RFC_ERR_NONICKNAMEGIVENLIBIRC_RFC_ERR_ERRONEUSNICKNAMELIBIRC_RFC_ERR_NICKNAMEINUSELIBIRC_RFC_ERR_NICKCOLLISION
Thread safety:
This function can be called simultaneously from multiple threads. π«Ά
irc_cmd_whois
Prototype:
int irc_cmd_whois(irc_session_t * session, const char * nick)
Parameters β¨
sessionβ the IRC session handle, obvs π«Άnickβ a nick, or a whole comma-separated list of nicks, to query the info about π
Description πΈ
Okay bestie, this function is the gossip machine. It queries various info about a nick. How much you actually get back depends on the IRC server, but typically it's giving: the username, the real name (as defined by the client at login), which IRC server they're on, the channels they're in, idle time, away mode, and so on and so forth. The whole dossier. π
Return value π
Return code 0 means the command was sent to the IRC server successfully. That does NOT mean the operation succeeded, okay?! You have to sit there and wait for the appropriate event_numeric event. Patience, babe. π
If the request succeeds, all that info comes back through these numeric codes:
LIBIRC_RFC_RPL_WHOISUSERLIBIRC_RFC_RPL_WHOISCHANNELSLIBIRC_RFC_RPL_WHOISSERVERLIBIRC_RFC_RPL_AWAYLIBIRC_RFC_RPL_WHOISOPERATORLIBIRC_RFC_RPL_WHOISIDLELIBIRC_RFC_RPL_ENDOFWHOISβ this event is the one that terminates the WHOIS information π
And the possible error responses for this command from the RFC1459:
LIBIRC_RFC_ERR_NOSUCHSERVERLIBIRC_RFC_ERR_NOSUCHNICKLIBIRC_RFC_ERR_NONICKNAMEGIVEN
Thread safety π§
This function can be called simultaneously from multiple threads. No cap.
irc_cmd_quit π
Prototype
int irc_cmd_quit(irc_session_t * session, const char * reason)
Parameters
sessionβ IRC session handle π«Άreasonβ if it's notNULL, the reason you're quitting π
Description
This function sends the QUIT command to the IRC server. That command forces the IRC server to close the IRC connection and terminate the session. Done. Bye. βοΈ
Now, the difference between this and just calling irc_disconnect is that this one lets you specify the reason to quit, and that reason gets shown to literally all the users in the channels you joined. It also makes it crystal clear that you left the IRC channels on purpose, and not because you just randomly got disconnected. Main character exit, not a glitch. π
Return value
Return code 0 means the command was sent to the IRC server successfully. Again β this does not mean the operation succeeded, and you need to wait for the appropriate event, or for the error code via the event_numeric event.
Thread safety
This function can be called simultaneously from multiple threads. π¦
irc_send_raw π
Prototype
int irc_send_raw (irc_session_t * session, const char * format, ...);
Parameters
sessionβ IRC session handle π«Άformatβ aprintf-type formatting string, followed by the format arguments β¨
Description
This function sends raw data as-is straight to the IRC server. Use it when you need to generate a server command that libircclient doesn't (yet) provide directly. DIY queen energy. π
Return value
Return code 0 means the command was sent to the IRC server successfully. It does not mean the operation succeeded, and you need to wait for the appropriate event, or for the error code via the event_numeric event.
Thread safety
This function can be called simultaneously from multiple threads. π
irc_target_get_nick π§
Prototype
void irc_target_get_nick(const char * origin, char *nick, size_t size)
Parameters
originβ the nick in the common IRC server format, such astim!root@mycomain.comπ¨nickβ the buffer to retrieve the parsed nick name πsizeβ the size of thenickbuffer. If the parsed nick is larger than the buffer size, it will be truncated βοΈ
Description
So for most events the IRC server hands you an origin β that's the person who generated the event β in the so-called "common" form, like nick!host@domain. But all the irc_cmd_* functions only want a plain old nick. That's where this lil cutie comes in: it parses that origin and pulls out the nick, storing it in the user-provided buffer. π
A buffer of size 128 should be enough for most nicks. π
Thread safety
This function can be called simultaneously from multiple threads. π«Ά
irc_target_get_host πΈ
Prototype
void irc_target_get_host(const char * target, char *host, size_t size)
Parameters
originβ the nick in the common IRC server format, such astim!root@mycomain.comπ¨hostβ the buffer to retrieve the parsed hostname πsizeβ the size of thehostbuffer. If the parsed nick is larger than the buffer size, it will be truncated βοΈ
Description
Same vibe as before, bestie: for most events the IRC server returns an origin β the person who generated the event β in the so-called "common" form, like nick!host@domain. This function parses that origin and pulls out the host, storing it in the user-provided buffer. π
Thread safety
This function can be called simultaneously from multiple threads. π
DCC initiating and accepting chat sessions, sending and receiving files π¦
irc_dcc_chat π
Prototype
int irc_dcc_chat(irc_session_t * session, void * ctx, const char * nick,
irc_dcc_callback_t callback, irc_dcc_t * dccid)
β¨ Parameters β¨
sessionβ the IRC session handle π«Άctxβ a user-defined context that gets passed straight to the callback. It may beNULL, no pressure πnickβ the target nickcallbackβ the DCC callback that's gonna handle DCC and chat events for youdccidβ if this function succeeds, the DCC session identifier is stored in this field. that's your little chat ticket, keep it safe π
Description
okay so this function requests a DCC CHAT between you and another IRC user. DCC CHAT is like private chat, except it goes directly between the two of you and bypasses the IRC server entirely. lowkey iconic. but here's the thing β the DCC CHAT request must be accepted by the other side before you can send anything. no acceptance, no messages. periodt.
When the chat is accepted, declined, terminated, or some data is received, the callback function is called. to be specific, the callback gets called when:
- the chat request is accepted;
- the chat request is denied;
- the new chat message is received;
- the chat is terminated by the remote party;
See the details in irc_dcc_callback_t declaration. iykyk πΈ
Return value
Return code 0 means the command was sent to the IRC server successfully. β οΈ but that does not mean the operation succeeded β you need to wait for the appropriate event, or for the error code via the event_numeric event. sent β succeeded, bestie, don't get it twisted.
Possible error responces for this command from the RFC1459:
LIBIRC_RFC_ERR_NORECIPIENTLIBIRC_RFC_ERR_NOTEXTTOSENDLIBIRC_RFC_ERR_CANNOTSENDTOCHANLIBIRC_RFC_ERR_NOTONCHANNELLIBIRC_RFC_ERR_NOTOPLEVELLIBIRC_RFC_ERR_WILDTOPLEVELLIBIRC_RFC_ERR_TOOMANYTARGETSLIBIRC_RFC_ERR_NOSUCHNICK
Thread safety
This function can be called simultaneously from multiple threads. multi-threaded queen behavior, we love to see it π
π¦ irc_dcc_msg π¦
Prototype
int irc_dcc_msg(irc_session_t * session, irc_dcc_t dccid, const char * text)
Parameters
sessionβ IRC session handledccidβ DCC session identifier for the DCC CHAT session which is activetextβ NULL-terminated message to send
Description
This function is used to send the DCC CHAT message to an active DCC CHAT. and for it to be active? the DCC CHAT request must be initiated by one side and accepted by another side. both sides had to show up, fr fr. π
Return value
Return code 0 means success. any other value means error, and the error code may be obtained through irc_errno(). π
Thread safety
This function can be called simultaneously from multiple threads. β¨
π irc_dcc_accept π
Prototype
int irc_dcc_accept(irc_session_t * session, irc_dcc_t dccid, void * ctx, irc_dcc_callback_t callback)
sessionβ the IRC session handle πdccidβ the DCC session identifier, the one the callback handed back to youctxβ your own user-defined context, which gets passed along to the callback. It can beNULL, no pressure β¨callbackβ the DCC callback that'll be used for DCC and chat events
Description
okay so this one accepts an incoming remote DCC chat or file transfer request π«Ά The moment the request is accepted, that callback starts getting called for all the further DCC events, including the very end of the DCC session. Go peek at the DCC callback info for the deets.
Timing check, bestie β° You should call this only after you've received eitherevent_dcc_chat_reqorevent_dcc_send_reqevents. And good news: you do not have to callirc_dcc_accept()orirc_dcc_decline()right there inside your event processing function β you can totally just stash thedccid, return, and call those functions later, whenever. BUT. To avoid memory leaks you must call eitherirc_dcc_decline()orirc_dcc_accept()for any incoming DCC request within 60 seconds of receiving it. Sixty. Seconds. Don't ghost it π
Return value
Return code 0 means success β¨ Any other value means error, and you can grab the error code through irc_errno().
Thread safety
This function can be called simultaneously from multiple threads. Slay, concurrency π
irc_dcc_decline
Prototype
int irc_dcc_decline(irc_session_t * session, irc_dcc_t dccid)
Parameters
sessionβ the IRC session handledccidβ the DCC session identifier that the callback returned to you
Description
This function declines a remote DCC chat or file transfer request. Politely. A no. A "not today" π
Same rule as its sibling: call this only after you've received either event_dcc_chat_req or event_dcc_send_req events. You don't have to fire irc_dcc_accept() or irc_dcc_decline() immediately inside the event processing function β store the dccid, come back later, live your life. However, to prevent memory leaks you must call either irc_dcc_decline() or irc_dcc_accept() for any incoming DCC request within 60 seconds after receiving it. The clock is literally ticking π
Do not use this function to forcefully close a DCC session you already accepted or initiated. That's a different job. Use irc_dcc_destroy() instead. Wrong tool, wrong vibe β
Return value
Return code 0 means success. Any other value means error, and the error code may be obtained through irc_errno().
Thread safety
This function can be called simultaneously from multiple threads. π
irc_dcc_sendfile
Prototype
int irc_dcc_sendfile(irc_session_t * session, void * ctx, const char * nick, const char * filename, irc_dcc_callback_t callback, irc_dcc_t * dccid)
Parameters
sessionβ the IRC session handlectxβ user-defined context which will be passed to the callback. May beNULLnickβ the target nickfilenameβ the full path to the file which will be sent. It must be an existing file, no imaginary files pls πcallbackβ the DCC callback which will be used for DCC and chat eventsdccidβ if this function succeeds, the DCC session identifier gets stored in this field
Description
This function generates a DCC SEND request to send the file π€ Once it's accepted, the file goes off to the remote party and the DCC session is closed. You can check the send operation's progress and its result in the callback β see the DCC callback information. It's giving "package delivered" energy β¨
Return value
Return code 0 means the command was sent to the IRC server successfully. Careful though β that does not mean the operation succeeded. You need to wait for the appropriate event, or for the error code via the event_numeric event. Patience, bestie π§
Possible error responces for this command from the RFC1459:
LIBIRC_RFC_ERR_NORECIPIENTLIBIRC_RFC_ERR_NOTEXTTOSENDLIBIRC_RFC_ERR_CANNOTSENDTOCHANLIBIRC_RFC_ERR_NOTONCHANNELLIBIRC_RFC_ERR_NOTOPLEVELLIBIRC_RFC_ERR_WILDTOPLEVELLIBIRC_RFC_ERR_TOOMANYTARGETSLIBIRC_RFC_ERR_NOSUCHNICK
Thread safety
This function can be called simultaneously from multiple threads. Multithreaded and unbothered π
irc_dcc_destroy
Prototype
int irc_dcc_destroy(irc_session_t * session, irc_dcc_t dccid)
Parameters
sessionβ the IRC session handledccidβ DCC session identifier of a session to destroy
Description
This function closes the DCC connection (if there even is one available) and destroys the DCC session, freeing up all the resources it was using. You can call it anytime β even from callbacks, even from different threads. Anytime, anywhere π
Heads up though: when a DCC session is finished (whether it ended in success or in failure), you should not destroy it β it gets destroyed automatically. Let it rest, don't double-tap π
Return value
Return code 0 means success. Any other value means error, and the error code may be obtained through irc_errno().
Thread safety
This function can be called simultaneously from multiple threads. π₯
Handling the colored messages
irc_color_strip_from_mirc
Prototype
char * irc_color_strip_from_mirc(const char * message)
Parameters
messageβ the original message, colors and all π¨
Description
This function strips all the ANSI color codes out of the message and returns a brand new message with zero color information in it. Super useful for bots that react to strings β this way your bot doesn't get confused if the string is out here wearing colors πΈ
This function does not modify the message which doesn't use colors. If it ain't broke, don't touch it π
Return value
It hands you back a brand-new message with all the color codes stripped right out. π
But bestie, listen β the memory for that new message is allocated with malloc(), so you have to free() it when you're done with it. If the memory allocation failed, it returns 0.
Thread safety:
This function can be called simultaneously from multiple threads. π§΅β¨
π¨ irc_color_convert_from_mirc
Prototype:
char * irc_color_convert_from_mirc(const char * message)
Parameters:
messageβ Original message with colors
Description:
This one takes every color code and format option in your message and converts them all into libircclient's internal colors. Glow-up, but make it internal. β¨
Return value:
Returns a pointer to the new message, now with converted ANSI color codes and format options. For the deets, go peek at the irc_color_convert_to_mirc help.
And yeah, the memory for the new message is allocated using malloc(), so free() it when you're not using it anymore. If memory allocation failed, it returns 0.
Thread safety:
This function can be called simultaneously from multiple threads. π§΅
π irc_color_convert_to_mirc
Prototype:
char * irc_color_convert_to_mirc(const char * message)
Parameters:
messageβ Original message with colors
Description:
This function takes all the color codes and format options from libircclient's internal colors and converts them to the ANSI that mIRC and other IRC clients actually use. Glow-up round two, now in mIRC flavor. π
Return value:
Returns a new message with converted color codes and format options, or 0 if memory could not be allocated. Note that the memory for the new message is allocated using malloc(), so you should free() it when it is not used anymore.
Thread safety:
This function can be called simultaneously from multiple threads. π§΅
The color system of libircclient is designed to be easy to use, and portable between different IRC clients. Every color or format option is described using plain text commands written between square brackets. No cap, it's just brackets. π
The possible codes are:
[B]β¦[/B]β bold format mode. Everything between[B]and[/B]is written in bold. β¨[I]β¦[/I]β italic/reverse format mode. Everything between[I]and[/I]is written in italic, or reversed. (But real talk β because some clients are incapable of rendering italic text, most clients display this as normal text with the background and foreground colors swapped. π« )[U]β¦[/U]β underline format mode. Everything between[U]and[/U]is written underlined.[COLOR=RED]β¦[/COLOR]β write the text using specified foreground color. The color is set by using theCOLORkeyword, and equal sign followed by text color code (see below). π¨[COLOR=RED/BLUE]β¦[/COLOR]β write the text using specified foreground and background color. The color is set by using theCOLORkeyword, an equal sign followed by text foreground color code, a dash and a text background color code. ποΈ
The following colors are supported:
WHITEBLACKDARKBLUEDARKGREENREDBROWNPURPLEOLIVEYELLOWGREENTEALCYANBLUEMAGENTADARKGRAYLIGHTGRAY
Examples of color sequences:
Hello, [B]Tim[/B].
[U]Arsenal[/U] got a [COLOR=RED]red card[/COLOR]
The tree[U]s[/U] are [COLOR=GREEN/BLACK]green[/COLOR]
βοΈ Changing the library options
irc_get_version
Prototype:
void irc_get_version(unsigned int * high, unsigned int * low)
Parameters:
highβ Stores the high version numberlowβ Stores the low version number
Description:
This function returns the libircclient version. π You can use the version either to check whether required options are available, or to output the version. The preferred printf-like format string to output the version is:
printf ("Version: %d.%02d", high, low);
Thread safety:
This function can be called simultaneously from multiple threads. π§΅
irc_set_ctx
Prototype:
void irc_set_ctx(irc_session_t * session, void * ctx)
Parameters:
sessionβ IRC session handlectxβ User-defined context
Description:
This function sets the user-defined context for this IRC session. libircclient does not use this context β it's yours, bestie. π«Ά Its whole purpose is to store session-specific user data, which may be obtained later by calling irc_get_ctx. Note that libircclient just carries out this pointer. If you allocate some memory and store its address in ctx (the most common usage), it is your responsibility to free it before calling irc_destroy_session().
fr fr, don't forget to free it. That's a memory leak with your name on it. π
Thread safety:
This function can be called simultaneously from multiple threads. π§΅
irc_get_ctx
Prototype:
void * irc_get_ctx(irc_session_t * session)
Parameters:
sessionβ IRC session handle
Description:
This function returns the IRC session context, which was set by irc_set_ctx.
Return value:
If no context was set, this function returns NULL.
Thread safety:
This function can be called simultaneously from multiple threads. π§΅
irc_option_set
Prototype:
void irc_option_set(irc_session_t * session, unsigned int option)
Parameters:
sessionβ IRC session handleoptionβ One of the Libirc options to set
Description:
This function sets the libircclient option, changing libircclient behavior. See the options list for the meaning for every option. π
Thread safety:
This function can be called simultaneously from multiple threads. π§΅
irc_option_reset
Prototype:
void irc_option_reset(irc_session_t * session, unsigned int option)
Parameters:
sessionβ IRC session handleoptionβ One of the Libirc options to set
Description:
This function resets the libircclient option, changing libircclient behavior. See the options list for the meaning for every option. (Yes, the parameter description says "to set" here too β that's just how the original rolls. π)
Thread safety:
This function can be called simultaneously from multiple threads. π§΅
π¨ Handling the errors
irc_errno
Prototype:
int irc_errno(irc_session_t * session)
Parameters:
sessionβ IRC session handle
Description:
This function returns the last error code associated with the last operation of this IRC session. Possible error codes are defined in libirc_errors.h.
As usual, typical errno rules apply:
irc_errno()should be called ONLY if the called function fails;irc_errno()doesn't return0if the function succeeds; actually, the return value will be undefined.- you should call
irc_errno()IMMEDIATELY after the function fails, before calling any other libircclient function. β°
Return value:
The error code.
Thread safety:
This function can be called simultaneously from multiple threads. Local error code is per IRC context, not per thread. π§΅
irc_strerror
Prototype:
const char * irc_strerror(int ircerrno)
Parameters:
ircerrnoβ IRC error code returned byirc_errno()
Description:
This function returns the text representation of the given error code. So like, the human-readable translation. π¬
Return value:
Returns an internal English string with a short description of the error code.
Thread safety:
This function can be called simultaneously from multiple threads. π§΅
𧬠Types
This section describes various types defined by the library.
π irc_session_t
typedef struct irc_session_s irc_session_t
okay so this is THE handle, bestie, the one that irc_create_session() hands you. Most of the library function calls are gonna want this bad boy as a parameter, so keep it close. You can make as many handles as you want, no cap β each handle can be used to establish a single IRC connection to an IRC server as a single user. That's the whole vibe: one handle, one connection, one user.
And the moment you're done with a handle? It should be destroyed by calling irc_destroy_session(). Don't leave it hanging, that's giving chaos energy π«Ά
π¦ irc_dcc_session_t
typedef struct irc_dcc_session_s irc_dcc_session_t
This one describes a DCC session used by libircclient. Its members are internal to libircclient, so literally do not touch them directly. It's not for you, it's for the library. Respect the boundaries π
β irc_dcc_t
typedef unsigned int irc_dcc_t
This type is a DCC session identifier. It's what you use to identify the DCC sessions in callbacks and in various functions. Think of it as a little name tag for your DCC session so everyone knows who's who β¨
π irc_callbacks_t
typedef struct irc_callbacks_t
typedef struct
{
irc_event_callback_t event_connect;
irc_event_callback_t event_nick;
irc_event_callback_t event_quit;
irc_event_callback_t event_join;
irc_event_callback_t event_part;
irc_event_callback_t event_mode;
irc_event_callback_t event_umode;
irc_event_callback_t event_topic;
irc_event_callback_t event_kick;
irc_event_callback_t event_channel;
irc_event_callback_t event_privmsg;
irc_event_callback_t event_notice;
irc_event_callback_t event_channel_notice;
irc_event_callback_t event_invite;
irc_event_callback_t event_ctcp_req;
irc_event_callback_t event_ctcp_rep;
irc_event_callback_t event_ctcp_action;
irc_event_callback_t event_unknown;
irc_eventcode_callback_t event_numeric;
irc_event_dcc_chat_t event_dcc_chat_req;
irc_event_dcc_send_t event_dcc_send_req;
}
This is the event callbacks structure, and it's the one you use when you're registering the callbacks.
So here's the tea β β all the communication with the IRC network is based on events. Generally speaking, an event is anything generated by someone else in the network, or by the IRC server itself. "Someone sends you a message", "Someone has joined the channel", "Someone has quits IRC" β all of these are events, and they're all coming for you.
Every event has its own event handler, which is called when the appropriate event is received. You don't have to define all the event handlers β just define the handlers for the events you actually need to intercept, and set the remaining handler pointers to NULL. Main character energy is knowing what to ignore π
event_connect
This event is triggered when the connection to the IRC server is successfully established, and the MOTD is received. Depending on the server, it may also be possible to send the commands before this event.
This event uses irc_event_callback_t callback with the following values:
originβ Unused, set toNULLparamsβ Unused, set toNULL
event_nick
This event is triggered when the NICK message is received. It happens when one of the users (including you!) in one of the channels you're watching (aka have joined) changed their nick.
Changing your own nick will also generate this event. And heads up β the server may change your nick independently, so you must track this event. Don't sleep on it π
This event uses irc_event_callback_t callback with the following values:
originβ The original nick (may be yours!)paramsβparams[0]contains a new nick.
event_quit
This event is triggered when the QUIT message is received. It happens when one of the users in one of the channels you're watching (have joined) disconnected from the IRC server.
This event uses irc_event_callback_t callback with the following values:
originβ The user who disconnectedparamsβparams[0]is optional, contains the user-specified reason to quit
event_join
This event is triggered upon receipt of a JOIN message. It happens when a new user joins the channel you're watching (have joined). It also happens when you joined the new channel.
Note that you may be "forced" to join the channel (and therefore receive this event) without issuing the JOIN command. A typical case is when the NickServ bot on the server is configured to auto-join you to specific channels. Not you choosing the channel, the channel choosing you π«
This event uses irc_event_callback_t callback with the following values:
originβ The user who joined the channel (this may be you!)paramsβparams[0]contains the channel name
event_part
This event is triggered upon receipt of a PART message. It happens when a user leaves the channel you're watching (have joined). It also happens when you leave a channel. Sad girl hours π
This event uses irc_event_callback_t callback with the following values:
originβ The user who left the channel (this may be you!)paramsβparams[0]contains the channel name,params[1]is optional and contains the user-specified reason
event_mode
This event is triggered upon receipt of a channel MODE message. It happens when someone changed the mode(s) of the channel you're watching (have joined).
This event uses irc_event_callback_t callback with the following values:
originβ The user who performed the changeparamsβparams[0]contains the channel name,params[1]contains the channel mode changes, such as "+t", "-i",params[2]optional, contains the argument for the channel mode (for example, a nick for the+omode)
event_umode
This event is triggered upon receipt of a user MODE message. It happens when your user mode is changed. It's giving β¨personalizedβ¨
This event uses irc_event_callback_t callback with the following values:
originβ The user who performed the changeparamsβparams[0]contains the channel name,params[1]contains the user mode changes, such as "+t", "-i"
event_topic
This event is triggered upon receipt of a TOPIC message. It happens when someone changed the topic on the channel you're watching (have joined).
...this event hits up the irc_event_callback_t callback and hands it these goodies:
- origin β the user who performed the change π
- params β
params[0]holds the channel name, andparams[1](optional, bestie, it might not be there) holds the new topic
π₯ event_kick π₯
Okay so this one fires the second a KICK message lands. It's the drama event β someone (and yes, that includes you) kicked someone (and yes, that also includes you) out of the channel you're watching, aka the one you actually joined. π
And fr fr, you can absolutely kick yourself from the channel. Iconic, chaotic, we love a self-own.
This event uses irc_event_callback_t callback with the following values:
- origin β the user who did the action (this may be you, bestie)
- params β
params[0]holds the channel name;params[1](optional) holds the nick of the kicked;params[2](optional) holds the reason for the kick
πΈ event_channel πΈ
This one goes off on receipt of a PRIVMSG message sent to the channel. It happens when someone β but not you β sent a message to the channel you're watching (have joined).
Your own messages do not trigger this event. Not me, not my business, no thanks. BUT. The server can still "force" you to send a message to the channel by generating this event. So like... surprise, you're posting. π«Ά
This event uses irc_event_callback_t callback with the following values:
- origin β the user who sent a message
- params β
params[0]holds the channel name;params[1](optional) holds the message text
π event_privmsg π
Triggered upon receipt of a PRIVMSG message sent privately to you. It happens when someone sent you a message. DMs! In MY client? It's more likely than you think. π
This event uses irc_event_callback_t callback with the following values:
- origin β the user who sent a message
- params β
params[0]holds your nick;params[1](optional) holds the message text
π’ event_notice π’
This event is triggered upon receipt of a NOTICE message. This message is similar to PRIVMSG and matches the event_privmsg.
According to RFC 1459, the only difference between NOTICE and PRIVMSG is that you should NEVER automatically reply to NOTICE messages. NEVER. I said what I said. π€
Unfortunately, this rule is frequently violated by IRC servers itself β for example, NICKSERV messages require reply, and are sent as NOTICE. So the servers are the ones breaking the rules, not you. Vibe check failed on their end.
This event uses irc_event_callback_t callback with the following values:
- origin β the user who sent a message
- params β
params[0]holds the target nick name;params[1](optional) holds the message text
π event_channel_notice π
This event is triggered upon receipt of a NOTICE message. This message is similar to PRIVMSG and matches the event_channel.
According to RFC 1459, the only difference between NOTICE and PRIVMSG is that you should NEVER automatically reply to NOTICE messages. Yes, again. It's that serious. π
Unfortunately, this rule is frequently violated by IRC servers itself β for example, NICKSERV messages require reply, and are sent as NOTICE. Same mess, different channel. Sigh. π«
This event uses irc_event_callback_t callback with the following values:
- origin β the user who sent a message
- params β
params[0]holds the channel name;params[1](optional) holds the message text
π event_invite π
Triggered upon receipt of an INVITE message. It happens when someone invited you to a channel which has +i (invite-only) mode. Getting picked?? Being chosen?? Main character energy fr. π
This event uses irc_event_callback_t callback with the following values:
- origin β the user who invited you
- params β
params[0]holds your nick;params[1](optional) holds the channel name
See also: irc_cmd_invite()
π¦ event_ctcp_req π¦
This event is triggered upon receipt of an CTCP request. By default, the built-in CTCP request handler is used. So if you do nothing, the library's got you. Slay.
Mirc generates PING, FINGER, VERSION, TIME and ACTION messages which are automatically handled by the library if this event is not handled by your application. Those messages are replied automatically except the ACTION message, which triggers the event_ctcp_action event.
If you need to handle more types of the message, define this event handler, and check the source code of libirc_event_ctcp_internal function to see how to write your own CTCP request handler. Go read the source, bestie, it's giving homework but it's the useful kind. π
Note: you must support at least CTCP PING to pass the spoof check by some IRC servers. No cap, they will clock you. β°
Also you may find useful this question in FAQ: ref faq4
This event uses irc_event_callback_t callback with the following values:
- origin β the user who generated the message
- params β
params[0]holds the complete CTCP message
π§ event_ctcp_rep π§
This event is triggered upon receipt of an CTCP response. Thus if you generate the CTCP message and the remote user responded, this event handler will be called. It's giving "you asked, they answered, and the callback said hello." β¨
This event uses irc_event_callback_t callback with the following values:
originβ the user who generated the messageparamsβparams[0]contains the complete CTCP message
event_ctcp_action
This one fires the second a CTCP ACTION message lands in your lap. But β and this is important bestie β it only gets invoked if you did not define the event_ctcp_req_ event handler. So it's like, one or the other, okay? Pick your fighter. π
Those messages usually show up in the IRC client looking like this:
:: [08:32:55] * Michael is having fun [08:32:55] * Bobbyβs getting
jealous
This event uses irc_event_callback_t callback with the following values:
originβ the user who generated the messageparamsβparams[0]contains the content of ACTION message
event_unknown
Triggered when a message arrives that's unknown, i.e. one the library doesn't handle. It's giving "mystery box" energy. π
This event uses irc_event_callback_t callback with the following values:
originβ the user who generated the eventparamsβ zero or more parameters provided with the event
event_numeric
This fires on the receipt of every numeric message from the server. The incomplete list of those responses could be found in RFC 1429. And ngl, this event is necessary to handle for any meaningful client β like, if you skip it your client is lowkey just vibing and doing nothing. π
This event uses the dedicated irc_eventcode_callback_t_ callback. See the callback documentation.
event_dcc_chat_req
Fires when someone attempts to establish the DCC CHAT with you. Somebody wants to slide into your DMs, fr fr. π¬
This event uses the dedicated irc_event_dcc_chat_t callback. See the callback documentation.
event_dcc_send_req
Fires when someone attempts to send you the file via DCC SEND. Incoming files, bestie, check the sender. π
This event uses the dedicated irc_event_dcc_send_t callback. See the callback documentation.
Constants
This section describes contstants such as options and the error codes. β¨
Errors
LIBIRC_ERR_OK
(0): No error. We love a clean slate. π«Ά
LIBIRC_ERR_INVAL
(1): An invalid value was given for one of the arguments to a function. For example, supplying the NULL value as a channel argument of irc_cmd_join() produces this error.
LIBIRC_ERR_RESOLV
(2): The host name supplied for irc_connect() function could not be resolved into valid IP address.
LIBIRC_ERR_SOCKET
(3): The new socket could not be created or made non-blocking. Usually means that the server is out of resources, or (hopefully not) a bug in libircclient. See also faq_err_socket.
LIBIRC_ERR_CONNECT
(4): The socket could not connect to the IRC server, or to the destination DCC part. Usually means that either the IRC server is down or its address is invalid. For DCC the reason usually is the firewall on your or destination computer, which refuses DCC transfer.
LIBIRC_ERR_CLOSED
(5): The IRC connection was closed by the IRC server (which could mean that an IRC operator just have banned you from the server β test your client before connecting to a public server), or the DCC connection was closed by remote peer β for example, the other side just terminates the IRC application. Usually it is not an error.
LIBIRC_ERR_NOMEM
(6): There are two possible reasons for this error. First is that memory could not be allocated for libircclient internal use, and this error is usually fatal. Second reason is that the command buffer (which queues the commands ready to be sent to the IRC server) is full, and could not accept more commands yet. In the last case you should just wait, and repeat the command later. β³
LIBIRC_ERR_ACCEPT
(7): A DCC chat/send connection from the remote peer could not be accepted. Either the connection was just terminated before it is accepted, or there is a bug in libircclient.
LIBIRC_ERR_NODCCSEND
(9): A filename supplied to irc_dcc_sendfile() could not be sent. Either is is not a regular file (a directory or a socket, for example), or it could not be read. See also LIBIRC_ERR_OPENFILE.
LIBIRC_ERR_READ
(10): Either a DCC file could not be read (for example, was truncated during sending), or a DCC socket returns a read error, which usually means that the network connection is terminated.
LIBIRC_ERR_WRITE
(11): Either a DCC file could not be written (for example, there is no free space on disk), or a DCC socket returns a write error, which usually means that the network connection is terminated.
LIBIRC_ERR_STATE
(12): The function is called when it is not allowed to be called. For example, irc_cmd_join() was called before the connection to IRC server succeed, and event_connect is called. Bestie, timing is everything. β°
LIBIRC_ERR_TIMEOUT
(13): The DCC request is timed out. There is a timer for each DCC request, which tracks connecting, accepting and non-accepted/declined DCC requests. For every request this timer is currently set to 60 seconds. If the DCC request was not connected, accepted or declined during this time, it will be terminated with this error.
LIBIRC_ERR_OPENFILE
(14): The file specified in irc_dcc_sendfile() could not be opened.
LIBIRC_ERR_TERMINATED
(15): The connection to the IRC server was terminated.
LIBIRC_ERR_NOIPV6
(16): The function which requires IPv6 support was called, but the IPv6 support was not compiled into the application.
LIBIRC_ERR_SSL_NOT_SUPPORTED
(17): The SSL connection was required but the library was not compiled with SSL support.
LIBIRC_ERR_SSL_INIT_FAILED
(18): The SSL library could not be initialized.
LIBIRC_ERR_CONNECT_SSL_FAILED
(19): SSL handshare failed when attempting to connect to the server. Typically this means youβre trying to use SSL but attempting to connect to a non-SSL port.
LIBIRC_ERR_SSL_CERT_VERIFY_FAILED
(20): The server is using an invalid or the self-signed certificate. Use LIBIRC_OPTION_SSL_NO_VERIFY option to connect to it.
Options
LIBIRC_OPTION_DEBUG
If set, enables additional debug output which goes to STDOUT. π
LIBIRC_OPTION_STRIPNICKS
If set, strips the event origins automatically. Every event has an origin (i.e. who originated the event). The origin usually looks like nick!host@ircserver, i.e. like tim!home@irc.server.net. Such origins can not be used in IRC commands, and need to be stripped (i.e. host and server part should be cut off) before using. This can be done either manually by calling irc_target_get_nick(), or automatically for all the events if this option is set.
LIBIRC_OPTION_SSL_NO_VERIFY
By default the SSL connection is authenticated by verifying that the certificate presented by the server is signed by a known trusted certificate authority. Since those typically cost money, some IRC servers use the self-signed certificates. They provide the benefits of the SSL connection but since they are not signed by the Certificate Authority, their authencity cannot be verified. This option, if set, disables the certificate verification β the library will accept any certificate presented by the server.
β οΈ This option must be set before the irc_connect function is called.
π APPENDIX π
Frequently asked questions
Why do I get a LIBIRC_ERR_SOCKET error under Win32 when using a static library?
Because on Win32 you have to initialize the Winsock API before using it:
WSADATA wsaData;
if ( WSAStartup ( MAKEWORD (2, 2), &wsaData) != 0 )
// report an error
// Now you can use libircclient
You have to do it ONCE in your application, and since libircclient does not know whether you already initialized it or not, it does not contain any Winsock initialization code.
What does it mean that the IRC protocol is event-based?
The IRC protocol itself is asynchronous and server-driven. For you, this means the following:
- For any IRC command, it is not possible to obtain an immediate response whether the command succeed or not. Instead the server will send the reply in a short (or long) period of time.
- For some IRC command there is no βsuccessβ response at all. For example, when you send a text message, IRC server will not send anything to confirm that the message is already sent.
- You can send several commands to the IRC server, and then receive several replies regarding every command. The order of the replies you receive is generally undefined.
- A lot of IRC events sent to you is generated by other users, or the IRC server itself, and are sent to you just when they are generated.
- Long lists (for example, channel lists) are also sent as events. Moreover, these events could be separated by other events (message or notices). And it is your responsibility to separate the data (using event codes), and use some sort of data structure that will hold it until the data is complete. It is not possible to simply query the list of channels, and expect that its content will immediately arrive.
π¦ No cap: nothing arrives on demand, everything arrives on its schedule. Build for that and you're golden.
- You might send the request and get no response at all when it succeeds (think: sending a message). You might send the request and it only succeeds once you receive a response (and that response might show up after ten completely unrelated events, bestie, so don't panic). Or β plot twist β you can receive a response without ever sending a request, which is exactly what
JOINdoes: the server can just implicitlyJOINyou to a specific channel. Rude, but valid. π- Be prepared to expect the unexpected from the IRC server. Fr fr. For example, the server can change your nick (you'll see this on most servers, the ones using nickserv authentication). You can be "forced" to join the channel, to say something, to leave a channel, to change your usermode and so on. Listen to what the IRC server tells you, and do so. π
Why the irc_cmd_join function does not return an error? π
A typical example is the irc_cmd_join() call always returns success even when you attempt to join a password-protected channel. Then some time later the IRC server returns an error. The reason? The irc_cmd family of functions return success when the command is sent to the IRC server. The asynchronous nature of IRC makes it impossible to obtain the command result immediately. Please read the question above. (Yes, it's giving circular. It's still true. π)
How to register/auth with NICKSERV? π
There is no 'standard' way. NICKSERV, CHANSERV and so on are not specified by the RFC. They are IRC extensions which behave exactly like the other IRC users but with more power. Typically their messages are sent via Notice events, so you can use following algorithm to handle Nickserv registration:
static void event_notice (irc_session_t * session, const char * event,
const char * origin, const char ** params, unsigned int count)
{
char buf[256];
if ( !origin )
return;
if ( strcasecmp (origin, "nickserv") )
return;
if ( strstr (params[1], "This nick is not registered") == params[1] )
{
sprintf (buf, "REGISTER %s NOMAIL", gCfg.irc_nickserv_password);
irc_cmd_msg(session, "nickserv", buf);
}
else if ( strstr (params[1], "This nickname is registered and protected") == params[1] )
{
sprintf (buf, "IDENTIFY %s", gCfg.irc_nickserv_password);
irc_cmd_msg(session, "nickserv", buf);
}
else if ( strstr (params[1], "Password accepted - you are now recognized") == params[1] )
printf ("Nickserv authentication succeed.");
}
The idea is to parse the messages sent from NICKSERV, and if they're matched the specific patterns, react on them appropriately. iykyk π
What is CTCP? π¦
CTCP abbreviature is deciphered as "Client-to-Client Protocol". It is used between the IRC clients to query the remote client for some data, or to send some information β for example, /me messages are sent via CTCP. Slay, iconic, all that. β¨
There is no standard list of possible CTCP requests, and different IRC clients often add their own CTCP codes. The built-in handler reacts on TIME, VERSION, PING and FINGER CTCP queries. If you need to react on other requests, you'll have to write your own CTCP handler. See the source code of libirc_event_ctcp_internal function to get an idea how to write it. π₯
When I am made a chanop (+o) why do I not receive the event_umode? π
Becoming a channel operator changes the channel mode, not user mode. Therefore you will receive event_mode and not event_umode.
If you receive the event_umode with +o this means your user is an IRC server operator. Not the same thing, bestie, do not confuse them. π
What if my application uses epoll? πΈ
The library only directly supports the select()-based loops for historic reasons, so epoll and other polling methods are not supported directly by the library. However but if necessart, it could be emulated by converting descriptors between select and epoll as following:
- Call
irc_add_select_descriptorswith an emptyFD_SET - Extract the descriptors from the
fd_setarrays (rememberfd_arrayis a bitarray, not the value array). There may be more than one descriptor in case there are DCC sessions. - Pass those descriptors to
poll/epollusing relevant events (i.e. use theEPOLLINfor the descriptors in thein_set) - For those descriptors which triggered the events, fill up the relevant
in_setandout_setstructures (again, remember the bitmasks!) and pass them toirc_process_select_descriptors()
While this is cumbersome, the operations are very simple (basically bitmask operations on a small structure) and will not add any significant slowdown to your application. Lowkey elegant once it clicks. π§
GNU LESSER GENERAL PUBLIC LICENSE π
Version 3, 29 June 2007
Copyright Β© 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License.
"The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version".
The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version:
- a. under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or
- b. under the GNU GPL, with none of the additional permissions of this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following:
- a. Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License.
- b. Accompany the object code with a copy of the GNU GPL and this license document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following:
- a. Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License.
- b. Accompany the Combined Work with a copy of the GNU GPL and this license document.
- c. For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document.
- d. Do one of the following:
- 0. Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.
- 1. Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version.
- e. Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.)
5. Combined Libraries.
Okay so bestie, listen π you can literally put library stuff that's a work based on the Library side by side in one single library together with other library facilities that are not Applications and are not covered by this License, and then convey that whole combined library under terms of your choice β but only if you do both of these things, no skipping π ββοΈ:
a. You have to accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. Like, hand over the un-mixed version too, periodt. π
b. You have to give prominent notice with the combined library saying that part of it is a work based on the Library, and explaining where to find that accompanying uncombined form of the same work. So people know what's what and where the original-ish thing lives. π
β¨ 6. Revised Versions of the GNU Lesser General Public License β¨
The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. And likeβ¦ these new versions are gonna be similar in spirit to the present version, but they might differ in detail to address new problems or concerns. iykyk πΈ
Every version gets its own distinguishing version number. So here's the vibe check: if the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License βor any later versionβ applies to it, you have the option of following the terms and conditions of either that published version or of any later version published by the Free Software Foundation. Pick your lane, bestie π¦
If the Library as you received it does not specify a version number of the GNU Lesser General Public License, then you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. Literally any of them. β¨
And if the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply β that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. No takebacks, no cap. π
π Indices and tables π
genindexmodindexsearch
π AUTHOR π
George Yunaev
π COPYRIGHT π
2005-2016 George Yunaev, http://www.ulduzsoft.com/linux/libircclient/
And that's the whole entire page, bestie!! π«Ά You made it to the very end, which is main character energy fr fr. This one's version 1.9, dated Aug 26, 2018, and it's the LIBIRCCLIENT(1) manual page β go forth and slay β¨ππΈ
π¦ where this page comes from
- fedora 43: libircclient-devel 1.10-3.fc43 Β· LGPL-3.0-or-later
- fedora 43: libircclient-devel 1.10-3.fc43 Β· LGPL-3.0-or-later
- fedora 44: libircclient-devel 1.10-4.fc44 Β· LGPL-3.0-or-later
- fedora 44: libircclient-devel 1.10-4.fc44 Β· LGPL-3.0-or-later
- opensuse-leap 16.0: libircclient-devel 1.10-bp160.1.3 Β· LGPL-2.0-or-later
- opensuse-leap 16.0: libircclient-devel 1.10-bp160.1.3 Β· LGPL-2.0-or-later
- opensuse-leap 16.0: libircclient-devel 1.10-bp160.1.3 Β· LGPL-2.0-or-later
- opensuse-leap 16.0: libircclient-devel 1.10-bp160.1.3 Β· LGPL-2.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms