csbot.irc module

exception csbot.irc.IRCParseError[source]

Bases: Exception

Raised by IRCMessage.parse() when a message can’t be parsed.

class csbot.irc.IRCMessage[source]

Bases: csbot.irc._IRCMessage

Represents an IRC message.

The IRC message format, paraphrased and simplified from RFC2812, is:

message = [":" prefix " "] command {" " parameter} [" :" trailing]

This is represented as a namedtuple with the following attributes:

  • prefix (str or None) – Prefix part of the message, usually the origin
  • command (str) – IRC command
  • params (list of str) – List of command parameters (including trailing)
  • command_name (str) – Name of IRC command (see below)
  • raw (str) – The raw IRC message

The command_name attribute is intended to be the “readable” form of the command. Usually it will be the same as command, but numeric replies recognised in RFC2812 will have their corresponding name instead.

REGEX = re.compile('(:(?P<prefix>\\S+) )?(?P<command>\\S+)(?P<params>( (?!:)\\S+)*)( :(?P<trailing>.*))?')

Regular expression to extract message components from a message.


Commands to force trailing parameter (:blah) for

classmethod parse(line)[source]

Create an IRCMessage object by parsing a raw message.

classmethod create(command, params=None, prefix=None)[source]

Create an IRCMessage from its core components.

The raw and command_name attributes will be generated based on the message details.


Get a more readable version of the raw IRC message.

Pretty much identical to the raw IRC message, but numeric commands that have names end up being NUMERIC/NAME.

pad_params(length, default=None)[source]

Pad parameters to length with default.

Useful when a command has optional parameters:

>>> msg = IRCMessage.parse(':nick!user@host KICK #channel other')
>>> channel, nick, reason = msg.params
Traceback (most recent call last):
ValueError: need more than 2 values to unpack
>>> channel, nick, reason = msg.pad_params(3)
class csbot.irc.IRCUser[source]

Bases: csbot.irc._IRCUser

Provide access to the parts of an IRC user string.

The following parts of the user string are available, set to None if that part of the string is absent:

  • raw – Raw user string
  • nick – Nick of the user
  • user – Username of the user (excluding leading ~)
  • host – Hostname of the user
>>> u = IRCUser.parse('my_nick!some_user@host.name')
>>> u.nick
>>> u.user
>>> u.host
REGEX = re.compile('(?P<raw>(?P<nick>[^!]+)(!~*(?P<user>[^@]+))?(@(?P<host>.+))?)')

Username parsing regex. Stripping out the “~” might be a Freenode peculiarity…

classmethod parse(raw)[source]

Create an IRCUser from a raw user string.

class csbot.irc.IRCCodec[source]

Bases: codecs.Codec

The encoding scheme to use for IRC messages.

IRC messages are “just bytes” with no encoding made explicit in the protocol definition or the messages. Ideally we’d like to handle IRC messages as proper strings.

encode(input, errors='strict')[source]

Encode a message as UTF-8.

decode(input, errors='strict')[source]

Decode a message.

IRC messages could pretty much be in any encoding. Here we just try the two most likely candidates: UTF-8, falling back to CP1252. Unfortunately, any encoding where every byte is valid (e.g. CP1252) makes it impossible to detect encoding errors - if input isn’t UTF-8 or CP1252-compatible, the result might be a bit odd.

class csbot.irc.IRCClient(*, loop=None, **kwargs)[source]

Bases: object

Internet Relay Chat client protocol.

A line-oriented protocol for communicating with IRC servers. It handles receiving data at several layers of abstraction:

It also handles sending data at several layers of abstraction:

  • send_line(): raw IRC command, e.g. self.send_line('JOIN #cs-york-dev')
  • send(): IRCMessage, e.g. self.send(IRCMessage.create('JOIN', params=['#cs-york-dev']))
  • <action>(...): e.g. self.join('#cs-york-dev').

The API and implementation is inspired by irc3 and Twisted.

  • TODO: limit send rate
  • TODO: limit PRIVMSG/NOTICE send length
  • TODO: More sophisticated CTCP? (see Twisted)
codec = <csbot.irc.IRCCodec object>

Codec for encoding/decoding IRC messages.

static DEFAULTS()

Generate a default configuration. Easier to call this and update the result than relying on dict.copy().

available_capabilities = None

Available client capabilities

enabled_capabilities = None

Enabled client capabilities


Run the bot, reconnecting when the connection is lost.


Connect to the IRC server.


Disconnect from the IRC server.

Use quit() for a more graceful disconnect.


Read and dispatch lines until the connection closes.


Callback for successful connection.

Register with the IRC server.


Handle a broken connection by attempting to reconnect.

Won’t reconnect if the broken connection was deliberate (i.e. close() was called).


Callback for received raw IRC message.


Callback for received parsed IRC message.


Send a raw IRC message to the server.

Encodes, terminates and sends data to the server.


Send an IRCMessage.


Enable client capability name.

Should wait for on_capability_enabled() before assuming it is enabled.


Disable client capability name.

Should wait for on_capability_disabled() befor assuming it is disabled.


Ask the server to set our nick.


Join a channel.

leave(channel, message=None)[source]

Leave a channel, with an optional message.

quit(message=None, reconnect=False)[source]

Leave the server.

If reconnect is False, then the client will not attempt to reconnect after the server closes the connection.

msg(to, message)[source]

Send message to a channel/nick.

act(to, action)[source]

Send action as a CTCP ACTION to a channel/nick.

notice(to, message)[source]

Send message as a NOTICE to a channel/nick.

set_topic(channel, topic)[source]

Try and set a channel’s topic.


Ask server to send the topic for channel.

Will cause on_topic_changed() at some point in the future.

ctcp_query(to, command, data=None)[source]

Send CTCP query.

ctcp_reply(to, command, data=None)[source]

Send CTCP reply.


Received welcome from server, now we can start communicating.

Welcome should include the accepted nick as the first parameter. This may be different to the nick we requested (e.g. truncated to a maximum length); if this is the case we store the new nick and fire the on_nick_changed() event.


Attempted nick is in use, try another.

Adds an underscore to the end of the current nick. If the server truncated the nick, replaces the last non-underscore with an underscore.


IRC PING/PONG keepalive.


Dispatch CAP subcommands to their own methods.


Response to CAP LS, giving list of available capabilities.


Response to CAP REQ, acknowledging capability changes.


Response to CAP REQ, rejecting capability changes.


Somebody’s nick changed.


Somebody joined a channel.


Somebody left a channel.


Somebody was kicked from a channel.


Somebody quit the server.


A channel’s topic changed.


Topic notification, usually after joining a channel.


Received a PRIVMSG.

TODO: Implement CTCP queries.


Received a NOTICE.

TODO: Implement CTCP replies.


Client capabilities are available.

Called with a set of client capability names when we get a response to CAP LS.


Client capability enabled.

Called when enabling client capability name has been acknowledged.


Client capability disabled.

Called when disabling client capability name has been acknowledged.


Successfully signed on to the server.


Changed nick.


Joined a channel.


Left a channel.

on_kicked(channel, by, reason)[source]

Kicked from a channel.

on_privmsg(user, to, message)[source]

Received a message, either directly or in a channel.

on_notice(user, to, message)[source]

Received a notice, either directly or in a channel.

on_action(user, to, action)[source]

Received CTCP ACTION. Common enough to deserve its own event.

on_ctcp_query_ACTION(user, to, data)[source]

Turn CTCP ACTION into on_action() event.

on_user_renamed(oldnick, newnick)[source]

User changed nick.

on_user_joined(user, channel)[source]

User joined a channel.

on_user_left(user, channel, message)[source]

User left a channel.

on_user_kicked(user, channel, by, reason)[source]

User kicked from a channel.

on_user_quit(user, message)[source]

User disconnected.

on_topic_changed(user, channel, topic)[source]

user changed the topic of channel to topic.