Documentation
¶
Overview ¶
Package client implements an IRC client. It handles protocol basics such as initial connection and responding to server PINGs, and has optional state tracking support which will keep tabs on every nick present in the same channels as the client. Other features include SSL support, automatic splitting of long lines, and panic recovery for handlers.
Incoming IRC messages are parsed into client.Line structs and trigger events based on the IRC verb (e.g. PRIVMSG) of the message. Handlers for these events conform to the client.Handler interface; a HandlerFunc type to wrap bare functions is provided a-la the net/http package.
Creating a client, adding a handler and connecting to a server looks soemthing like this, for the simple case:
// Create a new client, which will connect with the nick "myNick" irc := client.SimpleClient("myNick") // Add a handler that waits for the "disconnected" event and // closes a channel to signal everything is done. disconnected := make(chan struct{}) c.HandleFunc("disconnected", func(c *client.Conn, l *client.Line) { close(disconnected) }) // Connect to an IRC server. if err := c.ConnectTo("irc.freenode.net"); err != nil { log.Fatalf("Connection error: %v\n", err) } // Wait for disconnection. <-disconnected
Index ¶
- Constants
- func DefaultNewNick(old string) string
- func SplitMessage(msg string, splitLen int) (msgs []string)
- type ClientConfig
- type Connection
- func (conn *Connection) Action(t, msg string)
- func (conn *Connection) Authenticate(message string)
- func (conn *Connection) Away(message ...string)
- func (conn *Connection) Cap(subcommmand string, capabilities ...string)
- func (conn *Connection) Close() error
- func (conn *Connection) Config() *ClientConfig
- func (conn *Connection) Connect() error
- func (conn *Connection) ConnectContext(ctx context.Context) error
- func (conn *Connection) ConnectTo(host string, pass ...string) error
- func (conn *Connection) ConnectToContext(ctx context.Context, host string, pass ...string) error
- func (conn *Connection) Connected() bool
- func (conn *Connection) Ctcp(t, ctcp string, arg ...string)
- func (conn *Connection) CtcpReply(t, ctcp string, arg ...string)
- func (conn *Connection) DisableStateTracking()
- func (conn *Connection) EnableStateTracking()
- func (conn *Connection) Handle(name string, h Handler) Remover
- func (conn *Connection) HandleBG(name string, h Handler) Remover
- func (conn *Connection) HandleFunc(name string, hf HandlerFunc) Remover
- func (conn *Connection) HasCapability(cap string) bool
- func (conn *Connection) Invite(nick, channel string)
- func (conn *Connection) Join(channel string, key ...string)
- func (conn *Connection) Kick(channel, nick string, message ...string)
- func (conn *Connection) LogPanic(line *Line)
- func (conn *Connection) Me() *state.Nick
- func (conn *Connection) Mode(t string, modestring ...string)
- func (conn *Connection) Nick(nick string)
- func (conn *Connection) Notice(t, msg string)
- func (conn *Connection) Oper(user, pass string)
- func (conn *Connection) Part(channel string, message ...string)
- func (conn *Connection) Pass(password string)
- func (conn *Connection) Ping(message string)
- func (conn *Connection) Pong(message string)
- func (conn *Connection) Privmsg(t, msg string)
- func (conn *Connection) Privmsgf(t, format string, a ...interface{})
- func (conn *Connection) Privmsgln(t string, a ...interface{})
- func (conn *Connection) Quit(message ...string)
- func (conn *Connection) Raw(rawline string)
- func (conn *Connection) StateTracker() state.Tracker
- func (conn *Connection) String() string
- func (conn *Connection) SupportsCapability(cap string) bool
- func (conn *Connection) Topic(channel string, topic ...string)
- func (conn *Connection) User(ident, name string)
- func (conn *Connection) VHost(user, pass string)
- func (conn *Connection) Version(t string)
- func (conn *Connection) Who(nick string)
- func (conn *Connection) Whois(nick string)
- type Handler
- type HandlerFunc
- type Line
- type Remover
Constants ¶
const ( REGISTER = "REGISTER" CONNECTED = "CONNECTED" DISCONNECTED = "DISCONNECTED" ACTION = "ACTION" AUTHENTICATE = "AUTHENTICATE" AWAY = "AWAY" CAP = "CAP" CTCP = "CTCP" CTCPREPLY = "CTCPREPLY" ERROR = "ERROR" INVITE = "INVITE" JOIN = "JOIN" KICK = "KICK" MODE = "MODE" NICK = "NICK" NOTICE = "NOTICE" OPER = "OPER" PART = "PART" PASS = "PASS" PING = "PING" PONG = "PONG" PRIVMSG = "PRIVMSG" QUIT = "QUIT" TOPIC = "TOPIC" USER = "USER" VERSION = "VERSION" VHOST = "VHOST" WHO = "WHO" WHOIS = "WHOIS" )
const ( CAP_LS = "LS" CAP_REQ = "REQ" CAP_ACK = "ACK" CAP_NAK = "NAK" CAP_END = "END" )
Variables ¶
This section is empty.
Functions ¶
func DefaultNewNick ¶
Because networks limit nick lengths, the easy approach of appending an '_' to a nick that is already in use can cause problems. When the length limit is reached, the clients idea of what its nick is ends up being different from the server. Hilarity ensues. Thanks to github.com/purpleidea for the bug report! Thanks to 'man ascii' for
func SplitMessage ¶ added in v1.0.0
SplitMessage splits a message > splitLen chars at:
- the end of the last sentence fragment before splitLen
- the end of the last word before splitLen
- splitLen itself
Types ¶
type ClientConfig ¶ added in v1.0.0
type ClientConfig struct { // Set this to provide the Nick, Ident and Name for the client to use. // It is recommended to call Connection.Me to get up-to-date information // about the current state of the client's IRC nick after connecting. // This is because the nick might be dynamically updated to account // for occupied nicks. Me *state.Nick // Hostname to connect to and optional connect password. // Changing these after connection will have no effect until the // client reconnects. Server, Pass string // Are we connecting via SSL? Do we care about certificate validity? // Changing these after connection will have no effect until the // client reconnects. SSL bool SSLConfig *tls.Config // To connect via proxy set the proxy url here. // Changing these after connection will have no effect until the // client reconnects. Proxy string // Local address to bind to when connecting to the server. LocalAddr string // To attempt RFC6555 parallel IPv4 and IPv6 connections if both // address families are returned for a hostname, set this to true. // Passed through to https://golang.org/pkg/net/#Dialer DualStack bool // Enable IRCv3 capability negotiation. EnableCapabilityNegotiation bool // A list of capabilities to request to the server during registration. Capabilities []string // SASL configuration to use to authenticate the connection. Sasl sasl.Client // Replaceable function to customise the 433 handler's new nick. // By default the current nick's last character is "incremented". // See DefaultNewNick implementation below for details. NewNick func(string) string // Client->server ping frequency, in seconds. Defaults to 3m. // Set to 0 to disable client-side pings. PingFreq time.Duration // The duration before a connection timeout is triggered. Defaults to 1m. // Set to 0 to wait indefinitely. Timeout time.Duration // Set this to true to disable flood protection and false to re-enable. Flood bool // Sent as the reply to a CTCP VERSION message. Version string // Sent as the default QUIT message if Quit is called with no args. QuitMessage string // Configurable panic recovery for all handlers. // Defaults to logging an error, see LogPanic. Recover func(*Connection, *Line) // Split PRIVMSGs, NOTICEs and CTCPs longer than SplitLen characters // over multiple lines. Default to 450 if not set. SplitLen int }
ClientConfig contains options that can be passed to Client to change the behavior of the library during use. It is recommended that NewClientConfig is used to create this struct rather than instantiating one directly. Passing a ClientConfig with no Nick in the Me field to Client will result in unflattering consequences.
func NewClientConfig ¶ added in v1.0.0
func NewClientConfig(nick string, args ...string) *ClientConfig
NewClientConfig creates a ClientConfig struct containing sensible defaults. It takes one required argument: the nick to use for the client. Subsequent string arguments set the client's ident and "real" name, but these are optional.
type Connection ¶ added in v1.0.0
type Connection struct {
// contains filtered or unexported fields
}
Connection encapsulates a connection to a single IRC server. One can be created with Client or SimpleClient.
func Client ¶
func Client(cfg *ClientConfig) *Connection
Client takes a Config struct and returns a new Conn ready to have handlers added and connect to a server.
func SimpleClient ¶
func SimpleClient(nick string, args ...string) *Connection
SimpleClient creates a new Conn, passing its arguments to NewConfig. If you don't need to change any client options and just want to get started quickly, this is a convenient shortcut.
func (*Connection) Action ¶ added in v1.0.0
func (conn *Connection) Action(t, msg string)
Action sends a CTCP "ACTION" to the target nick or channel t.
func (*Connection) Authenticate ¶ added in v1.0.0
func (conn *Connection) Authenticate(message string)
Authenticate send an AUTHENTICATE command to the server.
func (*Connection) Away ¶ added in v1.0.0
func (conn *Connection) Away(message ...string)
Away sends an AWAY command to the server. If a message is provided it sets the client's away status with that message, otherwise it resets the client's away status.
AWAY AWAY :message
func (*Connection) Cap ¶ added in v1.0.0
func (conn *Connection) Cap(subcommmand string, capabilities ...string)
Cap sends a CAP command to the server.
CAP subcommand CAP subcommand :message
func (*Connection) Close ¶ added in v1.0.0
func (conn *Connection) Close() error
Close tears down all connection-related state. It is called when either the sending or receiving goroutines encounter an error. It may also be used to forcibly shut down the connection to the server.
func (*Connection) Config ¶ added in v1.0.0
func (conn *Connection) Config() *ClientConfig
Config returns a pointer to the Config struct used by the client. Many of the elements of Config may be changed at any point to affect client behavior. To disable flood protection temporarily, for example, a handler could do:
conn.Config().Flood = true // Send many lines to the IRC server, risking "excess flood" conn.Config().Flood = false
func (*Connection) Connect ¶ added in v1.0.0
func (conn *Connection) Connect() error
Connect connects the IRC client to the server configured in Config.Server. To enable explicit SSL on the connection to the IRC server, set Config.SSL to true before calling Connect(). The port will default to 6697 if SSL is enabled, and 6667 otherwise. To enable connecting via a proxy server, set Config.Proxy to the proxy URL (example socks5://localhost:9000) before calling Connect().
Upon successful connection, Connected will return true and a REGISTER event will be fired. This is mostly for internal use; it is suggested that a handler for the CONNECTED event is used to perform any initial client work like joining channels and sending messages.
func (*Connection) ConnectContext ¶ added in v1.0.0
func (conn *Connection) ConnectContext(ctx context.Context) error
ConnectContext works like Connect but uses the provided context.
func (*Connection) ConnectTo ¶ added in v1.0.0
func (conn *Connection) ConnectTo(host string, pass ...string) error
ConnectTo connects the IRC client to "host[:port]", which should be either a hostname or an IP address, with an optional port. It sets the client's Config.Server to host, Config.Pass to pass if one is provided, and then calls Connect.
func (*Connection) ConnectToContext ¶ added in v1.0.0
ConnectToContext works like ConnectTo but uses the provided context.
func (*Connection) Connected ¶ added in v1.0.0
func (conn *Connection) Connected() bool
Connected returns true if the client is successfully connected to an IRC server. It becomes true when the TCP connection is established, and false again when the connection is closed.
func (*Connection) Ctcp ¶ added in v1.0.0
func (conn *Connection) Ctcp(t, ctcp string, arg ...string)
Ctcp sends a (generic) CTCP message to the target nick or channel t, with an optional argument.
PRIVMSG t :\001CTCP arg\001
func (*Connection) CtcpReply ¶ added in v1.0.0
func (conn *Connection) CtcpReply(t, ctcp string, arg ...string)
CtcpReply sends a (generic) CTCP reply to the target nick or channel t, with an optional argument.
NOTICE t :\001CTCP arg\001
func (*Connection) DisableStateTracking ¶ added in v1.0.0
func (conn *Connection) DisableStateTracking()
DisableStateTracking causes the client to stop tracking information about the channels and nicks it knows of. It will also wipe current state from the state tracker.
func (*Connection) EnableStateTracking ¶ added in v1.0.0
func (conn *Connection) EnableStateTracking()
EnableStateTracking causes the client to track information about all channels it is joined to, and all the nicks in those channels. This can be rather handy for a number of bot-writing tasks. See the state package for more details.
NOTE: Calling this while connected to an IRC server may cause the state tracker to become very confused all over STDERR if logging is enabled. State tracking should enabled before connecting or at a pinch while the client is not joined to any channels.
func (*Connection) Handle ¶ added in v1.0.0
func (conn *Connection) Handle(name string, h Handler) Remover
Handle adds the provided handler to the foreground set for the named event. It will return a Remover that allows that handler to be removed again.
func (*Connection) HandleBG ¶ added in v1.0.0
func (conn *Connection) HandleBG(name string, h Handler) Remover
HandleBG adds the provided handler to the background set for the named event. It may go away in the future. It will return a Remover that allows that handler to be removed again.
func (*Connection) HandleFunc ¶ added in v1.0.0
func (conn *Connection) HandleFunc(name string, hf HandlerFunc) Remover
HandleFunc adds the provided function as a handler in the foreground set for the named event. It will return a Remover that allows that handler to be removed again.
func (*Connection) HasCapability ¶ added in v1.0.0
func (conn *Connection) HasCapability(cap string) bool
HasCapability returns true if the given capability has been acked by the server during negotiation.
func (*Connection) Invite ¶ added in v1.0.0
func (conn *Connection) Invite(nick, channel string)
Invite sends an INVITE command to the server.
INVITE nick channel
func (*Connection) Join ¶ added in v1.0.0
func (conn *Connection) Join(channel string, key ...string)
Join sends a JOIN command to the server with an optional key.
JOIN channel [key]
func (*Connection) Kick ¶ added in v1.0.0
func (conn *Connection) Kick(channel, nick string, message ...string)
Kick sends a KICK command to remove a nick from a channel.
KICK channel nick [:message]
func (*Connection) LogPanic ¶ added in v1.0.0
func (conn *Connection) LogPanic(line *Line)
LogPanic is used as the default panic catcher for the client. If, like me, you are not good with computer, and you'd prefer your bot not to vanish into the ether whenever you make unfortunate programming mistakes, you may find this useful: it will recover panics from handler code and log the errors.
func (*Connection) Me ¶ added in v1.0.0
func (conn *Connection) Me() *state.Nick
Me returns a state.Nick that reflects the client's IRC nick at the time it is called. If state tracking is enabled, this comes from the tracker, otherwise it is equivalent to conn.cfg.Me.
func (*Connection) Mode ¶ added in v1.0.0
func (conn *Connection) Mode(t string, modestring ...string)
Mode sends a MODE command for a target nick or channel t. If no mode strings are provided this requests that a 324 response is sent by the server for the target. Otherwise the mode strings are concatenated with spaces and sent to the server. This allows e.g.
conn.Mode("#channel", "+nsk", "mykey") MODE t MODE t modestring
func (*Connection) Nick ¶ added in v1.0.0
func (conn *Connection) Nick(nick string)
Nick sends a NICK command to the server.
NICK nick
func (*Connection) Notice ¶ added in v1.0.0
func (conn *Connection) Notice(t, msg string)
Notice sends a NOTICE to the target nick or channel t. If msg is longer than ClientConfig.SplitLen characters, multiple NOTICEs will be sent to the target containing sequential parts of msg.
NOTICE t :msg
func (*Connection) Oper ¶ added in v1.0.0
func (conn *Connection) Oper(user, pass string)
Oper sends an OPER command to the server.
OPER user pass
func (*Connection) Part ¶ added in v1.0.0
func (conn *Connection) Part(channel string, message ...string)
Part sends a PART command to the server with an optional part message.
PART channel [:message]
func (*Connection) Pass ¶ added in v1.0.0
func (conn *Connection) Pass(password string)
Pass sends a PASS command to the server.
PASS password
func (*Connection) Ping ¶ added in v1.0.0
func (conn *Connection) Ping(message string)
Ping sends a PING command to the server, which should PONG.
PING :message
func (*Connection) Pong ¶ added in v1.0.0
func (conn *Connection) Pong(message string)
Pong sends a PONG command to the server.
PONG :message
func (*Connection) Privmsg ¶ added in v1.0.0
func (conn *Connection) Privmsg(t, msg string)
Privmsg sends a PRIVMSG to the target nick or channel t. If msg is longer than Config.SplitLen characters, multiple PRIVMSGs will be sent to the target containing sequential parts of msg. PRIVMSG t :msg
func (*Connection) Privmsgf ¶ added in v1.0.0
func (conn *Connection) Privmsgf(t, format string, a ...interface{})
Privmsgf is the variadic version of Privmsg that formats the message that is sent to the target nick or channel t using the fmt.Sprintf function.
func (*Connection) Privmsgln ¶ added in v1.0.0
func (conn *Connection) Privmsgln(t string, a ...interface{})
Privmsgln is the variadic version of Privmsg that formats the message that is sent to the target nick or channel t using the fmt.Sprintln function. Note: Privmsgln doesn't add the '\n' character at the end of the message.
func (*Connection) Quit ¶ added in v1.0.0
func (conn *Connection) Quit(message ...string)
Quit sends a QUIT command to the server with an optional quit message.
QUIT [:message]
func (*Connection) Raw ¶ added in v1.0.0
func (conn *Connection) Raw(rawline string)
Raw sends a raw line to the server, should really only be used for debugging purposes but may well come in handy.
func (*Connection) StateTracker ¶ added in v1.0.0
func (conn *Connection) StateTracker() state.Tracker
StateTracker returns the state tracker being used by the client, if tracking is enabled, and nil otherwise.
func (*Connection) String ¶ added in v1.0.0
func (conn *Connection) String() string
Dumps a load of information about the current state of the connection to a string for debugging state tracking and other such things.
func (*Connection) SupportsCapability ¶ added in v1.0.0
func (conn *Connection) SupportsCapability(cap string) bool
SupportsCapability returns true if the server supports the given capability.
func (*Connection) Topic ¶ added in v1.0.0
func (conn *Connection) Topic(channel string, topic ...string)
Topic() sends a TOPIC command for a channel. If no topic is provided this requests that a 332 response is sent by the server for that channel, which can then be handled to retrieve the current channel topic. If a topic is provided the channel's topic will be set.
TOPIC channel TOPIC channel :topic
func (*Connection) User ¶ added in v1.0.0
func (conn *Connection) User(ident, name string)
User sends a USER command to the server.
USER ident 12 * :name
func (*Connection) VHost ¶ added in v1.0.0
func (conn *Connection) VHost(user, pass string)
VHost sends a VHOST command to the server.
VHOST user pass
func (*Connection) Version ¶ added in v1.0.0
func (conn *Connection) Version(t string)
Version sends a CTCP "VERSION" to the target nick or channel t.
func (*Connection) Who ¶ added in v1.0.0
func (conn *Connection) Who(nick string)
Who sends a WHO command to the server.
WHO nick
func (*Connection) Whois ¶ added in v1.0.0
func (conn *Connection) Whois(nick string)
Whois sends a WHOIS command to the server.
WHOIS nick
type Handler ¶
type Handler interface {
Handle(*Connection, *Line)
}
Handlers are triggered on incoming Lines from the server, with the handler "name" being equivalent to Line.Cmd. Read the RFCs for details on what replies could come from the server. They'll generally be things like "PRIVMSG", "JOIN", etc. but all the numeric replies are left as ascii strings of digits like "332" (mainly because I really didn't feel like putting massive constant tables in).
Foreground handlers have a guarantee of protocol consistency: all the handlers for one event will have finished before the handlers for the next start processing. They are run in parallel but block the event loop, so care should be taken to ensure these handlers are quick :-)
Background handlers are run in parallel and do not block the event loop. This is useful for things that may need to do significant work.
type HandlerFunc ¶
type HandlerFunc func(*Connection, *Line)
HandlerFunc allows a bare function with this signature to implement the Handler interface. It is used by Connection.HandleFunc.
func (HandlerFunc) Handle ¶
func (hf HandlerFunc) Handle(conn *Connection, line *Line)
type Line ¶
type Line struct { Tags map[string]string Nick, Ident, Host, Src string Cmd, Raw string Args []string Time time.Time }
We parse an incoming line into this struct. Line.Cmd is used as the trigger name for incoming event handlers and is the IRC verb, the first sequence of non-whitespace characters after ":nick!user@host", e.g. PRIVMSG.
Raw =~ ":nick!user@host cmd args[] :text" Src == "nick!user@host" Cmd == e.g. PRIVMSG, 332
func ParseLine ¶
ParseLine creates a Line from an incoming message from the IRC server.
It contains special casing for CTCP messages, most notably CTCP ACTION. All CTCP messages have the \001 bytes stripped from the message and the CTCP command separated from any subsequent text. Then, CTCP ACTIONs are rewritten such that Line.Cmd == ACTION. Other CTCP messages have Cmd set to CTCP or CTCPREPLY, and the CTCP command prepended to line.Args.
ParseLine also parses IRCv3 tags, if received. If a line does not have the tags section, Line.Tags will be nil. Tags are optional, and will only be included after the correct CAP command.
http://ircv3.net/specs/core/capability-negotiation-3.1.html http://ircv3.net/specs/core/message-tags-3.2.html
func (*Line) Public ¶
Public returns true if the line is the result of an IRC user sending a message to a channel the client has joined instead of directly to the client.
NOTE: This is very permissive, allowing all 4 RFC channel types even if your server doesn't technically support them.