v0.0.0-...-07bfc4e Latest Latest

This package is not in the latest version of its module.

Go to latest
Published: Jun 7, 2024 License: ISC, BSD-3-Clause Imports: 18 Imported by: 0



This is an event-based IRC client library. It is a fork of thoj/go-ircevent.



See examples/simple.go for a working example, but this illustrates the API:

irc := ircevent.Connection{
	Server:      "",
	UseTLS:      true,
	Nick:        "ircevent-test",
	Debug:       true,
	RequestCaps: []string{"server-time", "message-tags"},

irc.AddConnectCallback(func(e ircmsg.Message) { irc.Join("#ircevent-test") })

irc.AddCallback("PRIVMSG", func(event ircmsg.Message) {
	// event.Source is the source;
	// event.Params[0] is the target (the channel or nickname the message was sent to)
	// and event.Params[1] is the message itself

err := irc.Connect()
if err != nil {

The read loop executes all callbacks in serial on a single goroutine, respecting the order in which messages are received from the server. All callbacks must complete before the next message can be processed; if your callback needs to trigger a long-running task, you should spin off a new goroutine for it.


These methods can be used from inside callbacks, or externally:

irc.Send(command, params...)
irc.SendWithTags(tags, command, params...)
irc.Privmsg(target, message)
irc.Privmsgf(target, formatString, params...)

The ircevent.Connection object is synchronized internally, so these methods can be run from any goroutine without external locking.




View Source
const (
	Version = "WeebDataHoarder/irc-go"

	CAPTimeout = time.Second * 15
View Source
const (
	StateConnecting   = "connecting"
	StateReconnecting = "reconnecting"
	StateDisconnected = "disconnected"
	StateConnected    = "connected"
View Source
const (
	LevelDebug  = -10
	LevelNotice = -1
	LevelInfo   = 0
	LevelWarn   = 1
	LevelError  = 2
View Source
const (
	ChannelModeA = ChannelModeType(iota)
View Source
const (
	RPL_WELCOME            = "001"
	RPL_YOURHOST           = "002"
	RPL_CREATED            = "003"
	RPL_MYINFO             = "004"
	RPL_ISUPPORT           = "005"
	RPL_SNOMASKIS          = "008"
	RPL_BOUNCE             = "010"
	RPL_TRACELINK          = "200"
	RPL_TRACEUNKNOWN       = "203"
	RPL_TRACEUSER          = "205"
	RPL_TRACESERVER        = "206"
	RPL_TRACESERVICE       = "207"
	RPL_TRACENEWTYPE       = "208"
	RPL_TRACECLASS         = "209"
	RPL_ENDOFSTATS         = "219"
	RPL_UMODEIS            = "221"
	RPL_SERVLIST           = "234"
	RPL_SERVLISTEND        = "235"
	RPL_STATSUPTIME        = "242"
	RPL_STATSOLINE         = "243"
	RPL_LUSERCLIENT        = "251"
	RPL_LUSEROP            = "252"
	RPL_LUSERUNKNOWN       = "253"
	RPL_LUSERME            = "255"
	RPL_ADMINME            = "256"
	RPL_ADMINLOC1          = "257"
	RPL_ADMINLOC2          = "258"
	RPL_ADMINEMAIL         = "259"
	RPL_TRACELOG           = "261"
	RPL_TRACEEND           = "262"
	RPL_TRYAGAIN           = "263"
	RPL_LOCALUSERS         = "265"
	RPL_GLOBALUSERS        = "266"
	RPL_WHOISCERTFP        = "276"
	RPL_AWAY               = "301"
	RPL_USERHOST           = "302"
	RPL_ISON               = "303"
	RPL_UNAWAY             = "305"
	RPL_NOWAWAY            = "306"
	RPL_WHOISREGNICK       = "307"
	RPL_WHOISUSER          = "311"
	RPL_WHOISSERVER        = "312"
	RPL_WHOWASUSER         = "314"
	RPL_ENDOFWHO           = "315"
	RPL_WHOISIDLE          = "317"
	RPL_ENDOFWHOIS         = "318"
	RPL_WHOISSPECIAL       = "320"
	RPL_LIST               = "322"
	RPL_LISTEND            = "323"
	RPL_UNIQOPIS           = "325"
	RPL_CREATIONTIME       = "329"
	RPL_WHOISACCOUNT       = "330"
	RPL_NOTOPIC            = "331"
	RPL_TOPIC              = "332"
	RPL_TOPICWHOTIME       = "333"
	RPL_TOPICTIME          = "333"
	RPL_WHOISBOT           = "335"
	RPL_INVITING           = "341"
	RPL_SUMMONING          = "342"
	RPL_INVITELIST         = "346"
	RPL_EXCEPTLIST         = "348"
	RPL_VERSION            = "351"
	RPL_WHOREPLY           = "352"
	RPL_NAMREPLY           = "353"
	RPL_WHOSPCRPL          = "354"
	RPL_LINKS              = "364"
	RPL_ENDOFLINKS         = "365"
	RPL_ENDOFNAMES         = "366"
	RPL_BANLIST            = "367"
	RPL_ENDOFBANLIST       = "368"
	RPL_ENDOFWHOWAS        = "369"
	RPL_INFO               = "371"
	RPL_MOTD               = "372"
	RPL_ENDOFINFO          = "374"
	RPL_MOTDSTART          = "375"
	RPL_ENDOFMOTD          = "376"
	RPL_WHOISHOST          = "378"
	RPL_WHOISMODES         = "379"
	RPL_YOUREOPER          = "381"
	RPL_REHASHING          = "382"
	RPL_YOURESERVICE       = "383"
	RPL_TIME               = "391"
	RPL_USERSSTART         = "392"
	RPL_USERS              = "393"
	RPL_ENDOFUSERS         = "394"
	RPL_NOUSERS            = "395"
	ERR_UNKNOWNERROR       = "400"
	ERR_NOSUCHNICK         = "401"
	ERR_NOSUCHSERVER       = "402"
	ERR_NOORIGIN           = "409"
	ERR_NORECIPIENT        = "411"
	ERR_NOTEXTTOSEND       = "412"
	ERR_NOTOPLEVEL         = "413"
	ERR_WILDTOPLEVEL       = "414"
	ERR_BADMASK            = "415"
	ERR_INPUTTOOLONG       = "417"
	ERR_NOMOTD             = "422"
	ERR_NOADMININFO        = "423"
	ERR_FILEERROR          = "424"
	ERR_NOTONCHANNEL       = "442"
	ERR_NOLOGIN            = "444"
	ERR_KEYSET             = "467"
	ERR_LINKCHANNEL        = "470"
	ERR_UNKNOWNMODE        = "472"
	ERR_BADCHANMASK        = "476"
	ERR_NEEDREGGEDNICK     = "477" // conflicted with ERR_NOCHANMODES
	ERR_BANLISTFULL        = "478"
	ERR_NOPRIVILEGES       = "481"
	ERR_RESTRICTED         = "484"
	ERR_NOOPERHOST         = "491"
	ERR_HELPNOTFOUND       = "524"
	ERR_CANNOTSENDRP       = "573"
	RPL_WHOWASIP           = "652"
	RPL_WHOISSECURE        = "671"
	RPL_HELPSTART          = "704"
	RPL_HELPTXT            = "705"
	RPL_ENDOFHELP          = "706"
	ERR_NOPRIVS            = "723"
	RPL_MONONLINE          = "730"
	RPL_MONOFFLINE         = "731"
	RPL_MONLIST            = "732"
	RPL_ENDOFMONLIST       = "733"
	ERR_MONLISTFULL        = "734"
	RPL_LOGGEDIN           = "900"
	RPL_LOGGEDOUT          = "901"
	ERR_NICKLOCKED         = "902"
	RPL_SASLSUCCESS        = "903"
	ERR_SASLFAIL           = "904"
	ERR_SASLTOOLONG        = "905"
	ERR_SASLABORTED        = "906"
	ERR_SASLALREADY        = "907"
	RPL_SASLMECHS          = "908"


View Source
var (
	ClientDisconnected = errors.New("Could not send because client is disconnected")
	ServerTimedOut     = errors.New("Server did not respond in time")
	ServerDisconnected = errors.New("Disconnected by server")
	SASLFailed         = errors.New("SASL setup timed out. Does the server support SASL?")

	CapabilityNotNegotiated = errors.New("The IRCv3 capability required for this was not negotiated")
	NoLabeledResponse       = errors.New("The server failed to send a labeled response to the command")

	ClientHasQuit = errors.New("client has called Quit()")


This section is empty.


type Batch

type Batch struct {
	Items []*Batch

Batch represents an IRCv3 batch, or a line within one. There are two cases: 1. (Batch).Command == "BATCH". This indicates the start of an IRCv3 batch; the embedded Message is the initial BATCH command, which may contain tags that pertain to the batch as a whole. (Batch).Items contains zero or more *Batch elements, pointing to the contents of the batch in order. 2. (Batch).Command != "BATCH". This is an ordinary IRC line; its tags, command, and parameters are available as members of the embedded Message. In the context of labeled-response, there is a third case: a `nil` value of *Batch indicates that the server failed to respond in time.

type BatchCallback

type BatchCallback func(*Batch) bool

type Callback

type Callback func(ircmsg.Message)

type CallbackID

type CallbackID struct {
	// contains filtered or unexported fields

CallbackID Tuple type for uniquely identifying callbacks

type ChannelModeType

type ChannelModeType byte

type Connection

type Connection struct {
	// config data, user-settable
	// Server host:port combo of server
	Server string
	// TLSConfig Used to configure TLS settings for server with UseTLS, and configure CertFP auth method
	TLSConfig    *tls.Config
	Nick         string
	User         string
	RealName     string   // IRC realname/gecos
	WebIRC       []string // parameters for the WEBIRC command
	Password     string   // server password (PASS command)
	RequestCaps  []string // IRCv3 capabilities to request (failure is non-fatal)
	SASLLogin    string   // SASL credentials to log in with (failure is fatal by default)
	SASLPassword string
	SASLMech     string
	SASLOptional bool // make SASL failure non-fatal
	QuitMessage  string
	Version      string
	// Timeout How early to timeout an unresponsive connection Defaults to 1m
	Timeout time.Duration
	// KeepAlive How often to send our own PING messages. Defaults to 4m
	KeepAlive time.Duration
	// ReconnectFrequency rate at which reconnects will be done. Defaults to 2m
	ReconnectFrequency time.Duration
	// ReconnectVariance random amount to add to ReconnectFrequency each retry
	ReconnectVariance time.Duration
	MaxLineLen        int // maximum line length, not including tags
	UseTLS            bool
	UseSASL           bool
	EnableCTCP        bool
	DebugTraffic      func(incoming bool, line string)
	AllowPanic        bool // if set, don't recover() from panics in callbacks
	AllowTruncation   bool // if set, truncate lines exceeding MaxLineLen and send them
	// set this to configure how the connection is made (e.g. via a proxy server):
	DialContext func(ctx context.Context, network, addr string) (net.Conn, error)

	ErrorFunc  ErrorFunc
	LoggerFunc LoggerFunc
	// contains filtered or unexported fields

func (*Connection) AcknowledgedCaps

func (irc *Connection) AcknowledgedCaps() (result map[string]string)

AcknowledgedCaps Return IRCv3 CAPs actually enabled on the connection, together with their values if applicable. The resulting map is shared, so do not modify it.

func (*Connection) Action

func (irc *Connection) Action(target, message string) error

Action Send (action) message to a target (channel or nickname). No clear RFC on this one...

func (*Connection) Actionf

func (irc *Connection) Actionf(target, format string, a ...interface{}) error

Actionf Send formatted (action) message to a target (channel or nickname).

func (*Connection) AddBatchCallback

func (irc *Connection) AddBatchCallback(callback func(*Batch) bool) CallbackID

AddBatchCallback adds a callback for handling BATCH'ed server responses. All available BATCH callbacks will be invoked in an undefined order, stopping at the first one to return a value of true (indicating successful processing). If no batch callback returns true, the batch will be "flattened" (i.e., its messages will be processed individually by the normal event handlers). Batch callbacks can be removed as usual with RemoveCallback.

func (*Connection) AddCallback

func (irc *Connection) AddCallback(command string, callback func(ircmsg.Message)) CallbackID

AddCallback Register a callback to handle an IRC command (or numeric). A callback is a function which takes only an ircmsg.Message object as parameter. Valid commands are all IRC commands, including numerics. This function returns the ID of the registered callback for later management.

func (*Connection) AddConnectCallback

func (irc *Connection) AddConnectCallback(callback func(ircmsg.Message)) (id CallbackID)

AddConnectCallback Convenience function to add a callback that will be called once the connection is completed (this is traditionally referred to as "connection registration").

func (*Connection) AddDisconnectCallback

func (irc *Connection) AddDisconnectCallback(callback func(ircmsg.Message)) (id CallbackID)

AddDisconnectCallback Adds a callback to be run when disconnection from the server is detected; this may be a connectivity failure, a server-initiated disconnection, or a client-initiated Quit(). These callbacks are run after the last message from the server is processed, before any reconnection attempt. The contents of the Message object supplied to the callback are undefined.

func (*Connection) BatchNegotiated

func (irc *Connection) BatchNegotiated() bool

func (*Connection) ChannelModeToPrefix

func (irc *Connection) ChannelModeToPrefix() (result map[byte]byte)

func (*Connection) ChannelModes

func (irc *Connection) ChannelModes() (result map[byte]ChannelModeType)

func (*Connection) ClearCallback

func (irc *Connection) ClearCallback(command string)

ClearCallback Remove all callbacks from a given event code.

func (*Connection) CompareEqualString

func (irc *Connection) CompareEqualString(a, b string) bool

CompareEqualString Compares two strings for case-insensitive equality Rules are obtained via RPL_ISUPPORT CASEMAPPING parameter. If not specified UTF-8 lowercase will be applied by default

func (*Connection) Connect

func (irc *Connection) Connect() (err error)

Connect to a given server using the current connection configuration. This function also takes care of identification if a password is provided. RFC 1459 details:

func (*Connection) Connected

func (irc *Connection) Connected() bool

Connected Returns true if the connection is connected to an IRC server.

func (*Connection) CurrentNick

func (irc *Connection) CurrentNick() string

CurrentNick Determine nick currently used with the connection.

func (*Connection) GetLabeledResponse

func (irc *Connection) GetLabeledResponse(tags map[string]string, command string, params ...string) (batch *Batch, err error)

GetLabeledResponse sends an IRC message using the IRCv3 labeled-response specification, then synchronously waits for the response, which is returned as a *Batch. If the server fails to respond correctly, an error will be returned.

func (*Connection) GetReplyTarget

func (irc *Connection) GetReplyTarget(msg ircmsg.Message) string

GetReplyTarget attempts to determine where replies to a PRIVMSG or NOTICE should be sent (a channel if the message was sent to a channel, a nick if the message was a direct message from a valid nickname). If no valid reply target can be determined, it returns the empty string.

func (*Connection) HandleBatch

func (irc *Connection) HandleBatch(batch *Batch)

HandleBatch handles a *Batch using available handlers, "flattening" it if no handler succeeds. This can be used in a batch or labeled-response callback to process inner batches.

func (*Connection) HandleMessage

func (irc *Connection) HandleMessage(event ircmsg.Message)

HandleMessage handles an IRC line using the available handlers. This can be used in a batch or labeled-response callback to process an individual line.

func (*Connection) ISupport

func (irc *Connection) ISupport() (result map[string]string)

ISupport Returns the 005 RPL_ISUPPORT tokens sent by the server when the connection was initiated, parsed into key-value form as a map. The resulting map is shared, so do not modify it.

func (*Connection) Join

func (irc *Connection) Join(channel string) error

Join Use the connection to join a given channel. RFC 1459 details:

func (*Connection) LabelNegotiated

func (irc *Connection) LabelNegotiated() bool

func (*Connection) Lag

func (irc *Connection) Lag() time.Duration

Lag Returns the roundtrip latency This is obtained from our own PING to server, or via tagged time messages from server

func (*Connection) Loop

func (irc *Connection) Loop()

Loop Main loop to control the connection.

func (*Connection) MessageTagsNegotiated

func (irc *Connection) MessageTagsNegotiated() bool

func (*Connection) MultilineNegotiated

func (irc *Connection) MultilineNegotiated() bool

func (*Connection) Notice

func (irc *Connection) Notice(target, message string) error

Notice Send a notification to a nickname. This is similar to Privmsg but must not receive replies. RFC 1459 details:

func (*Connection) Noticef

func (irc *Connection) Noticef(target, format string, a ...interface{}) error

Noticef Send a formated notification to a nickname. RFC 1459 details:

func (*Connection) Part

func (irc *Connection) Part(channel string) error

Part Leave a given channel. RFC 1459 details:

func (*Connection) Ping

func (irc *Connection) Ping()

func (*Connection) PreferredNick

func (irc *Connection) PreferredNick() string

PreferredNick Returns the expected or desired nickname for the connection; if the real nickname is different, the client will periodically attempt to change to this one.

func (*Connection) Privmsg

func (irc *Connection) Privmsg(target, message string) error

Privmsg Send (private) message to a target (channel or nickname). RFC 1459 details:

func (*Connection) Privmsgf

func (irc *Connection) Privmsgf(target, format string, a ...interface{}) error

Privmsgf Send formated string to specified target (channel or nickname).

func (*Connection) Quit

func (irc *Connection) Quit()

Quit the current connection and disconnect from the server RFC 1459 details:

func (*Connection) Reconnect

func (irc *Connection) Reconnect()

Reconnect forces the client to reconnect to the server. TODO try to ensure buffered messages are sent?

func (*Connection) RemoveCallback

func (irc *Connection) RemoveCallback(id CallbackID)

RemoveCallback Remove callback i (ID) from the given event code.

func (*Connection) RemoveCallbacks

func (irc *Connection) RemoveCallbacks(ids ...CallbackID)

RemoveCallbacks Remove multiple callback i (ID) from the given event code.

func (*Connection) ReplaceCallback

func (irc *Connection) ReplaceCallback(id CallbackID, callback func(ircmsg.Message)) bool

ReplaceCallback Replace callback i (ID) associated with a given event code with a new callback function.

func (*Connection) Send

func (irc *Connection) Send(command string, params ...string) error

Send an IRC message without tags.

func (*Connection) SendIRCMessage

func (irc *Connection) SendIRCMessage(msg ircmsg.Message) error

SendIRCMessage Send a built ircmsg.Message.

func (*Connection) SendRaw

func (irc *Connection) SendRaw(message string) error

SendRaw Send a raw string.

func (*Connection) SendWithLabel

func (irc *Connection) SendWithLabel(callback func(*Batch), tags map[string]string, command string, params ...string) error

SendWithLabel sends an IRC message using the IRCv3 labeled-response specification. Instead of being processed by normal event handlers, the server response to the command will be collected into a *Batch and passed to the provided callback. If the server fails to respond correctly, the callback will be invoked with `nil` as the argument.

func (*Connection) SendWithTags

func (irc *Connection) SendWithTags(tags map[string]string, command string, params ...string) error

SendWithTags Send an IRC message with tags.

func (*Connection) SetNick

func (irc *Connection) SetNick(n string)

SetNick Set (new) nickname. RFC 1459 details:

type ErrorFunc

type ErrorFunc func(state string, err error)

type LabelCallback

type LabelCallback func(*Batch)

type LoggerFunc

type LoggerFunc func(state string, level LoggerLevel, format string, v ...any)

type LoggerLevel

type LoggerLevel int


Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL