girc

package module
v0.0.0-...-77b3e41 Latest Latest
Warning

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

Go to latest
Published: Oct 1, 2021 License: MIT Imports: 23 Imported by: 0

README

girc, a flexible IRC library for Go

Build Status Coverage Status GoDoc Go Report Card IRC Chat

Status

girc is fairly close to marking the 1.0.0 endpoint, which will be tagged as necessary, so you will be able to use this with care knowing the specific tag you're using won't have breaking changes

Features

  • Focuses on simplicity, yet tries to still be flexible.
  • Only requires standard library packages
  • Event based triggering/responses (example, and CTCP too!)
  • Documentation is mostly complete.
  • Support for almost all of the IRCv3 spec.
    • SASL Auth (currently only PLAIN and EXTERNAL is support by default, however you can simply implement SASLMech yourself to support additional mechanisms.)
    • Message tags (things like account-tag on by default)
    • account-notify, away-notify, chghost, extended-join, etc -- all handled seemlessly (cap.go for more info).
  • Channel and user tracking. Easily find what users are in a channel, if a user is away, or if they are authenticated (if the server supports it!)
  • Client state/capability tracking. Easy methods to access capability data (LookupChannel, LookupUser, GetServerOption (ISUPPORT), etc.)
  • Built-in support for things you would commonly have to implement yourself.

Installing

$ go get -u git.tcp.direct/kayos/girc-tcpd

Examples

See the examples within the documentation for real-world usecases. Here are a few real-world usecases/examples/projects which utilize girc:

Project Description
nagios-check-ircd Nagios utility for monitoring the health of an ircd
nagios-notify-irc Nagios utility for sending alerts to one or many channels/networks
matterbridge bridge between mattermost, IRC, slack, discord (and many others) with REST API

Working on a project and want to add it to the list? Submit a pull request!

Contributing

Please review the CONTRIBUTING doc for submitting issues/a guide on submitting pull requests and helping out.

License

Copyright (c) 2016 Liam Stanley <me@liamstanley.io>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

girc artwork licensed under CC 3.0 based on Renee French under Creative Commons 3.0 Attributions.

References

Documentation

Overview

Package girc provides a high level, yet flexible IRC library for use with interacting with IRC servers. girc has support for user/channel tracking, as well as a few other neat features (like auto-reconnect).

Much of what girc can do, can also be disabled. The goal is to provide a solid API that you don't necessarily have to work with out of the box if you don't want to.

See the examples below for a few brief and useful snippets taking advantage of girc, which should give you a general idea of how the API works.

Index

Constants

View Source
const (
	CTCP_ACTION     = "ACTION"
	CTCP_PING       = "PING"
	CTCP_PONG       = "PONG"
	CTCP_VERSION    = "VERSION"
	CTCP_USERINFO   = "USERINFO"
	CTCP_CLIENTINFO = "CLIENTINFO"
	CTCP_SOURCE     = "SOURCE"
	CTCP_TIME       = "TIME"
	CTCP_FINGER     = "FINGER"
	CTCP_ERRMSG     = "ERRMSG"
)

Standard CTCP based constants.

View Source
const (
	UPDATE_STATE     = "CLIENT_STATE_UPDATED"   // when channel/user state is updated.
	UPDATE_GENERAL   = "CLIENT_GENERAL_UPDATED" // when general state (client nick, server name, etc) is updated.
	ALL_EVENTS       = "*"                      // trigger on all events
	CONNECTED        = "CLIENT_CONNECTED"       // when it's safe to send arbitrary commands (joins, list, who, etc), trailing is host:port
	INITIALIZED      = "CLIENT_INIT"            // verifies successful socket connection, trailing is host:port
	DISCONNECTED     = "CLIENT_DISCONNECTED"    // occurs when we're disconnected from the server (user-requested or not)
	CLOSED           = "CLIENT_CLOSED"          // occurs when Client.Close() has been called
	STS_UPGRADE_INIT = "STS_UPGRADE_INIT"       // when an STS upgrade initially happens.
	STS_ERR_FALLBACK = "STS_ERR_FALLBACK"       // when an STS connection fails and fallbacks are supported.
)

Emulated event commands used to allow easier hooks into the changing state of the client.

View Source
const (
	DefaultPrefixes = "(ov)@+" // the most common default prefixes
	ModeAddPrefix   = "+"      // modes are being added
	ModeDelPrefix   = "-"      // modes are being removed

	ChannelPrefix      = "#" // regular channel
	DistributedPrefix  = "&" // distributed channel
	OwnerPrefix        = "~" // user owner +q (non-rfc)
	AdminPrefix        = "&" // user admin +a (non-rfc)
	HalfOperatorPrefix = "%" // user half operator +h (non-rfc)
	OperatorPrefix     = "@" // user operator +o
	VoicePrefix        = "+" // user has voice +v
)

User/channel prefixes :: RFC1459.

View Source
const (
	UserModeInvisible     = "i" // invisible
	UserModeOperator      = "o" // server operator
	UserModeServerNotices = "s" // user wants to receive server notices
	UserModeWallops       = "w" // user wants to receive wallops
)

User modes :: RFC1459; section 4.2.3.2.

View Source
const (
	ModeDefaults = "beI,k,l,imnpst" // the most common default modes

	ModeInviteOnly = "i" // only join with an invite
	ModeKey        = "k" // channel password
	ModeLimit      = "l" // user limit
	ModeModerated  = "m" // only voiced users and operators can talk
	ModeOperator   = "o" // operator
	ModePrivate    = "p" // private
	ModeSecret     = "s" // secret
	ModeTopic      = "t" // must be op to set topic
	ModeVoice      = "v" // speak during moderation mode

	ModeOwner        = "q" // owner privileges (non-rfc)
	ModeAdmin        = "a" // admin privileges (non-rfc)
	ModeHalfOperator = "h" // half-operator privileges (non-rfc)
)

Channel modes :: RFC1459; section 4.2.3.1.

View Source
const (
	ADMIN    = "ADMIN"
	AWAY     = "AWAY"
	CONNECT  = "CONNECT"
	DIE      = "DIE"
	ERROR    = "ERROR"
	INFO     = "INFO"
	INVITE   = "INVITE"
	ISON     = "ISON"
	JOIN     = "JOIN"
	KICK     = "KICK"
	KILL     = "KILL"
	LINKS    = "LINKS"
	LIST     = "LIST"
	LUSERS   = "LUSERS"
	MODE     = "MODE"
	MOTD     = "MOTD"
	NAMES    = "NAMES"
	NICK     = "NICK"
	NJOIN    = "NJOIN"
	NOTICE   = "NOTICE"
	OPER     = "OPER"
	PART     = "PART"
	PASS     = "PASS"
	PING     = "PING"
	PONG     = "PONG"
	PRIVMSG  = "PRIVMSG"
	QUIT     = "QUIT"
	REHASH   = "REHASH"
	RESTART  = "RESTART"
	SERVER   = "SERVER"
	SERVICE  = "SERVICE"
	SERVLIST = "SERVLIST"
	SQUERY   = "SQUERY"
	SQUIT    = "SQUIT"
	STATS    = "STATS"
	SUMMON   = "SUMMON"
	TIME     = "TIME"
	TOPIC    = "TOPIC"
	TRACE    = "TRACE"
	USER     = "USER"
	USERHOST = "USERHOST"
	USERS    = "USERS"
	VERSION  = "VERSION"
	WALLOPS  = "WALLOPS"
	WEBIRC   = "WEBIRC"
	WHO      = "WHO"
	WHOIS    = "WHOIS"
	WHOWAS   = "WHOWAS"
)

IRC commands :: RFC2812; section 3 :: RFC2813; section 4.

View Source
const (
	RPL_WELCOME           = "001"
	RPL_YOURHOST          = "002"
	RPL_CREATED           = "003"
	RPL_MYINFO            = "004"
	RPL_BOUNCE            = "005"
	RPL_ISUPPORT          = "005"
	RPL_USERHOST          = "302"
	RPL_ISON              = "303"
	RPL_AWAY              = "301"
	RPL_UNAWAY            = "305"
	RPL_NOWAWAY           = "306"
	RPL_WHOISUSER         = "311"
	RPL_WHOISSERVER       = "312"
	RPL_WHOISOPERATOR     = "313"
	RPL_WHOISIDLE         = "317"
	RPL_ENDOFWHOIS        = "318"
	RPL_WHOISCHANNELS     = "319"
	RPL_WHOWASUSER        = "314"
	RPL_ENDOFWHOWAS       = "369"
	RPL_LISTSTART         = "321"
	RPL_LIST              = "322"
	RPL_LISTEND           = "323"
	RPL_UNIQOPIS          = "325"
	RPL_CHANNELMODEIS     = "324"
	RPL_NOTOPIC           = "331"
	RPL_TOPIC             = "332"
	RPL_INVITING          = "341"
	RPL_SUMMONING         = "342"
	RPL_INVITELIST        = "346"
	RPL_ENDOFINVITELIST   = "347"
	RPL_EXCEPTLIST        = "348"
	RPL_ENDOFEXCEPTLIST   = "349"
	RPL_VERSION           = "351"
	RPL_WHOREPLY          = "352"
	RPL_ENDOFWHO          = "315"
	RPL_NAMREPLY          = "353"
	RPL_ENDOFNAMES        = "366"
	RPL_LINKS             = "364"
	RPL_ENDOFLINKS        = "365"
	RPL_BANLIST           = "367"
	RPL_ENDOFBANLIST      = "368"
	RPL_INFO              = "371"
	RPL_ENDOFINFO         = "374"
	RPL_MOTDSTART         = "375"
	RPL_MOTD              = "372"
	RPL_ENDOFMOTD         = "376"
	RPL_YOUREOPER         = "381"
	RPL_REHASHING         = "382"
	RPL_YOURESERVICE      = "383"
	RPL_TIME              = "391"
	RPL_USERSSTART        = "392"
	RPL_USERS             = "393"
	RPL_ENDOFUSERS        = "394"
	RPL_NOUSERS           = "395"
	RPL_TRACELINK         = "200"
	RPL_TRACECONNECTING   = "201"
	RPL_TRACEHANDSHAKE    = "202"
	RPL_TRACEUNKNOWN      = "203"
	RPL_TRACEOPERATOR     = "204"
	RPL_TRACEUSER         = "205"
	RPL_TRACESERVER       = "206"
	RPL_TRACESERVICE      = "207"
	RPL_TRACENEWTYPE      = "208"
	RPL_TRACECLASS        = "209"
	RPL_TRACERECONNECT    = "210"
	RPL_TRACELOG          = "261"
	RPL_TRACEEND          = "262"
	RPL_STATSLINKINFO     = "211"
	RPL_STATSCOMMANDS     = "212"
	RPL_ENDOFSTATS        = "219"
	RPL_STATSUPTIME       = "242"
	RPL_STATSOLINE        = "243"
	RPL_UMODEIS           = "221"
	RPL_SERVLIST          = "234"
	RPL_SERVLISTEND       = "235"
	RPL_LUSERCLIENT       = "251"
	RPL_LUSEROP           = "252"
	RPL_LUSERUNKNOWN      = "253"
	RPL_LUSERCHANNELS     = "254"
	RPL_LUSERME           = "255"
	RPL_ADMINME           = "256"
	RPL_ADMINLOC1         = "257"
	RPL_ADMINLOC2         = "258"
	RPL_ADMINEMAIL        = "259"
	RPL_TRYAGAIN          = "263"
	ERR_NOSUCHNICK        = "401"
	ERR_NOSUCHSERVER      = "402"
	ERR_NOSUCHCHANNEL     = "403"
	ERR_CANNOTSENDTOCHAN  = "404"
	ERR_TOOMANYCHANNELS   = "405"
	ERR_WASNOSUCHNICK     = "406"
	ERR_TOOMANYTARGETS    = "407"
	ERR_NOSUCHSERVICE     = "408"
	ERR_NOORIGIN          = "409"
	ERR_NORECIPIENT       = "411"
	ERR_NOTEXTTOSEND      = "412"
	ERR_NOTOPLEVEL        = "413"
	ERR_WILDTOPLEVEL      = "414"
	ERR_BADMASK           = "415"
	ERR_INPUTTOOLONG      = "417"
	ERR_UNKNOWNCOMMAND    = "421"
	ERR_NOMOTD            = "422"
	ERR_NOADMININFO       = "423"
	ERR_FILEERROR         = "424"
	ERR_NONICKNAMEGIVEN   = "431"
	ERR_ERRONEUSNICKNAME  = "432"
	ERR_NICKNAMEINUSE     = "433"
	ERR_NICKCOLLISION     = "436"
	ERR_UNAVAILRESOURCE   = "437"
	ERR_USERNOTINCHANNEL  = "441"
	ERR_NOTONCHANNEL      = "442"
	ERR_USERONCHANNEL     = "443"
	ERR_NOLOGIN           = "444"
	ERR_SUMMONDISABLED    = "445"
	ERR_USERSDISABLED     = "446"
	ERR_NOTREGISTERED     = "451"
	ERR_NEEDMOREPARAMS    = "461"
	ERR_ALREADYREGISTRED  = "462"
	ERR_NOPERMFORHOST     = "463"
	ERR_PASSWDMISMATCH    = "464"
	ERR_YOUREBANNEDCREEP  = "465"
	ERR_YOUWILLBEBANNED   = "466"
	ERR_KEYSET            = "467"
	ERR_CHANNELISFULL     = "471"
	ERR_UNKNOWNMODE       = "472"
	ERR_INVITEONLYCHAN    = "473"
	ERR_BANNEDFROMCHAN    = "474"
	ERR_BADCHANNELKEY     = "475"
	ERR_BADCHANMASK       = "476"
	ERR_NOCHANMODES       = "477"
	ERR_BANLISTFULL       = "478"
	ERR_NOPRIVILEGES      = "481"
	ERR_CHANOPRIVSNEEDED  = "482"
	ERR_CANTKILLSERVER    = "483"
	ERR_RESTRICTED        = "484"
	ERR_UNIQOPPRIVSNEEDED = "485"
	ERR_NOOPERHOST        = "491"
	ERR_UMODEUNKNOWNFLAG  = "501"
	ERR_USERSDONTMATCH    = "502"
)

Numeric IRC reply mapping :: RFC2812; section 5.

View Source
const (
	AUTHENTICATE = "AUTHENTICATE"
	MONITOR      = "MONITOR"
	STARTTLS     = "STARTTLS"

	CAP       = "CAP"
	CAP_ACK   = "ACK"
	CAP_CLEAR = "CLEAR"
	CAP_END   = "END"
	CAP_LIST  = "LIST"
	CAP_LS    = "LS"
	CAP_NAK   = "NAK"
	CAP_REQ   = "REQ"
	CAP_NEW   = "NEW"
	CAP_DEL   = "DEL"

	CAP_CHGHOST = "CHGHOST"
	CAP_AWAY    = "AWAY"
	CAP_ACCOUNT = "ACCOUNT"
	CAP_TAGMSG  = "TAGMSG"
)

IRCv3 commands and extensions :: http://ircv3.net/irc/.

View Source
const (
	RPL_LOGGEDIN     = "900"
	RPL_LOGGEDOUT    = "901"
	RPL_NICKLOCKED   = "902"
	RPL_SASLSUCCESS  = "903"
	ERR_SASLFAIL     = "904"
	ERR_SASLTOOLONG  = "905"
	ERR_SASLABORTED  = "906"
	ERR_SASLALREADY  = "907"
	RPL_SASLMECHS    = "908"
	RPL_STARTTLS     = "670"
	ERR_STARTTLS     = "691"
	RPL_MONONLINE    = "730"
	RPL_MONOFFLINE   = "731"
	RPL_MONLIST      = "732"
	RPL_ENDOFMONLIST = "733"
	ERR_MONLISTFULL  = "734"
)

Numeric IRC reply mapping for ircv3 :: http://ircv3.net/irc/.

View Source
const (
	RPL_STATSCLINE    = "213"
	RPL_STATSNLINE    = "214"
	RPL_STATSILINE    = "215"
	RPL_STATSKLINE    = "216"
	RPL_STATSQLINE    = "217"
	RPL_STATSYLINE    = "218"
	RPL_SERVICEINFO   = "231"
	RPL_ENDOFSERVICES = "232"
	RPL_SERVICE       = "233"
	RPL_STATSVLINE    = "240"
	RPL_STATSLLINE    = "241"
	RPL_STATSHLINE    = "244"
	RPL_STATSSLINE    = "245"
	RPL_STATSPING     = "246"
	RPL_STATSBLINE    = "247"
	RPL_STATSDLINE    = "250"
	RPL_NONE          = "300"
	RPL_WHOISCHANOP   = "316"
	RPL_KILLDONE      = "361"
	RPL_CLOSING       = "362"
	RPL_CLOSEEND      = "363"
	RPL_INFOSTART     = "373"
	RPL_MYPORTIS      = "384"
	ERR_NOSERVICEHOST = "492"
)

Numeric IRC event mapping :: RFC2812; section 5.3.

View Source
const (
	ERR_TOOMANYMATCHES = "416" // IRCNet.
	RPL_GLOBALUSERS    = "266" // aircd/hybrid/bahamut, used on freenode.
	RPL_LOCALUSERS     = "265" // aircd/hybrid/bahamut, used on freenode.
	RPL_TOPICWHOTIME   = "333" // ircu, used on freenode.
	RPL_WHOSPCRPL      = "354" // ircu, used on networks with WHOX support.
)

Misc.

Variables

View Source
var ErrConnNotTLS = errors.New("underlying connection is not tls")

ErrConnNotTLS is returned when Client.TLSConnectionState() is called, and the connection to the server wasn't made with TLS.

View Source
var ErrInvalidSource = errors.New("event has nil or invalid source address")

ErrInvalidSource is returned when a method needs to know the origin of an event, however Event.Source is unknown (e.g. sent by the user, not the server.)

View Source
var ErrNotConnected = errors.New("client is not connected to server")

ErrNotConnected is returned if a method is used when the client isn't connected.

Functions

func DefaultRecoverHandler

func DefaultRecoverHandler(client *Client, err *HandlerError)

DefaultRecoverHandler can be used with Config.RecoverFunc as a default catch-all for panics. This will log the error, and the call trace to the debug log (see Config.Debug), or os.Stdout if Config.Debug is unset.

func EncodeCTCP

func EncodeCTCP(ctcp *CTCPEvent) (out string)

EncodeCTCP encodes a CTCP event into a string, including delimiters.

func EncodeCTCPRaw

func EncodeCTCPRaw(cmd, text string) (out string)

EncodeCTCPRaw is much like EncodeCTCP, however accepts a raw command and string as input.

func Fmt

func Fmt(text string) string

Fmt takes format strings like "{red}" or "{red,blue}" (for background colors) and turns them into the resulting ASCII format/color codes for IRC. See format.go for the list of supported format codes allowed.

For example:

client.Message("#channel", Fmt("{red}{b}Hello {red,blue}World{c}"))

func Glob

func Glob(input, match string) bool

Glob will test a string pattern, potentially containing globs, against a string. The glob character is *.

func IsValidChannel

func IsValidChannel(channel string) bool

IsValidChannel validates if channel is an RFC compliant channel or not.

NOTE: If you are using this to validate a channel that contains a channel ID, (!<channelid>NAME), this only supports the standard 5 character length.

NOTE: If you do not need to validate against servers that support unicode, you may want to ensure that all channel chars are within the range of all ASCII printable chars. This function will NOT do that for compatibility reasons.

channel    =  ( "#" / "+" / ( "!" channelid ) / "&" ) chanstring
              [ ":" chanstring ]
chanstring =  0x01-0x07 / 0x08-0x09 / 0x0B-0x0C / 0x0E-0x1F / 0x21-0x2B
chanstring =  / 0x2D-0x39 / 0x3B-0xFF
                ; any octet except NUL, BELL, CR, LF, " ", "," and ":"
channelid  = 5( 0x41-0x5A / digit )   ; 5( A-Z / 0-9 )

func IsValidChannelMode

func IsValidChannelMode(raw string) bool

IsValidChannelMode validates a channel mode (CHANMODES).

func IsValidNick

func IsValidNick(nick string) bool

IsValidNick validates an IRC nickname. Note that this does not validate IRC nickname length.

nickname =  ( letter / special ) *8( letter / digit / special / "-" )
letter   =  0x41-0x5A / 0x61-0x7A
digit    =  0x30-0x39
special  =  0x5B-0x60 / 0x7B-0x7D

func IsValidUser

func IsValidUser(name string) bool

IsValidUser validates an IRC ident/username. Note that this does not validate IRC ident length.

The validation checks are much like what characters are allowed with an IRC nickname (see IsValidNick()), however an ident/username can:

1. Must either start with alphanumberic char, or "~" then alphanumberic char.

2. Contain a "." (period), for use with "first.last". Though, this may not be supported on all networks. Some limit this to only a single period.

Per RFC:

user =  1*( %x01-09 / %x0B-0C / %x0E-1F / %x21-3F / %x41-FF )
        ; any octet except NUL, CR, LF, " " and "@"

func StripRaw

func StripRaw(text string) string

StripRaw tries to strip all ASCII format codes that are used for IRC. Primarily, foreground/background colors, and other control bytes like reset, bold, italic, reverse, etc. This also is done in a specific way in order to ensure no truncation of other non-irc formatting.

func ToRFC1459

func ToRFC1459(input string) string

ToRFC1459 converts a string to the stripped down conversion within RFC 1459. This will do things like replace an "A" with an "a", "[]" with "{}", and so forth. Useful to compare two nicknames or channels. Note that this should not be used to normalize nicknames or similar, as this may convert valid input characters to non-rfc-valid characters. As such, it's main use is for comparing two nicks.

func TrimFmt

func TrimFmt(text string) string

TrimFmt strips all "{fmt}" formatting strings from the input text. See Fmt() for more information.

Types

type CMode

type CMode struct {
	// contains filtered or unexported fields
}

CMode represents a single step of a given mode change.

func (*CMode) Short

func (c *CMode) Short() string

Short returns a short representation of a mode without arguments. E.g. "+a", or "-b".

func (*CMode) String

func (c *CMode) String() string

String returns a string representation of a mode, including optional arguments. E.g. "+b user*!ident@host.*.com"

type CModes

type CModes struct {
	// contains filtered or unexported fields
}

CModes is a representation of a set of modes. This may be the given state of a channel/user, or the given state changes to a given channel/user.

func NewCModes

func NewCModes(channelModes, userPrefixes string) CModes

NewCModes returns a new CModes reference. channelModes and userPrefixes would be something you see from the server's "CHANMODES" and "PREFIX" ISUPPORT capability messages (alternatively, fall back to the standard) DefaultPrefixes and ModeDefaults.

func (*CModes) Apply

func (c *CModes) Apply(modes []CMode)

Apply merges two state changes, or one state change into a state of modes. For example, the latter would mean applying an incoming MODE with the modes stored for a channel.

func (*CModes) Copy

func (c *CModes) Copy() (nc CModes)

Copy returns a deep copy of CModes.

func (*CModes) Get

func (c *CModes) Get(mode string) (args string, ok bool)

Get returns the arguments for a given mode within this session, if it supports args.

func (*CModes) HasMode

func (c *CModes) HasMode(mode string) bool

HasMode checks if the CModes state has a given mode. E.g. "m", or "I".

func (*CModes) Parse

func (c *CModes) Parse(flags string, args []string) (out []CMode)

Parse parses a set of flags and args, returning the necessary list of mappings for the mode flags.

func (*CModes) String

func (c *CModes) String() string

String returns a complete set of modes for this given state (change?). For example, "+a-b+cde some-arg".

type CTCP

type CTCP struct {
	// contains filtered or unexported fields
}

CTCP handles the storage and execution of CTCP handlers against incoming CTCP events.

func (*CTCP) Clear

func (c *CTCP) Clear(cmd string)

Clear removes currently setup handler for cmd, if one is set.

func (*CTCP) ClearAll

func (c *CTCP) ClearAll()

ClearAll removes all currently setup and re-sets the default handlers.

func (*CTCP) Set

func (c *CTCP) Set(cmd string, handler func(client *Client, ctcp CTCPEvent))

Set saves handler for execution upon a matching incoming CTCP event. Use SetBg if the handler may take an extended period of time to execute. If you would like to have a handler which will catch ALL CTCP requests, simply use "*" in place of the command.

func (*CTCP) SetBg

func (c *CTCP) SetBg(cmd string, handler func(client *Client, ctcp CTCPEvent))

SetBg is much like Set, however the handler is executed in the background, ensuring that event handling isn't hung during long running tasks. See Set for more information.

type CTCPEvent

type CTCPEvent struct {
	// Origin is the original event that the CTCP event was decoded from.
	Origin *Event `json:"origin"`
	// Source is the author of the CTCP event.
	Source *Source `json:"source"`
	// Command is the type of CTCP event. E.g. PING, TIME, VERSION.
	Command string `json:"command"`
	// Text is the raw arguments following the command.
	Text string `json:"text"`
	// Reply is true if the CTCP event is intended to be a reply to a
	// previous CTCP (e.g, if we sent one).
	Reply bool `json:"reply"`
}

CTCPEvent is the necessary information from an IRC message.

func DecodeCTCP

func DecodeCTCP(e *Event) *CTCPEvent

DecodeCTCP decodes an incoming CTCP event, if it is CTCP. nil is returned if the incoming event does not have valid CTCP encoding.

type CTCPHandler

type CTCPHandler func(client *Client, ctcp CTCPEvent)

CTCPHandler is a type that represents the function necessary to implement a CTCP handler.

type Caller

type Caller struct {
	// contains filtered or unexported fields
}

Caller manages internal and external (user facing) handlers.

func (*Caller) Add

func (c *Caller) Add(cmd string, handler func(client *Client, event Event)) (cuid string)

Add registers the handler function for the given event. cuid is the handler uid which can be used to remove the handler with Caller.Remove().

func (*Caller) AddBg

func (c *Caller) AddBg(cmd string, handler func(client *Client, event Event)) (cuid string)

AddBg registers the handler function for the given event and executes it in a go-routine. cuid is the handler uid which can be used to remove the handler with Caller.Remove().

func (*Caller) AddHandler

func (c *Caller) AddHandler(cmd string, handler Handler) (cuid string)

AddHandler registers a handler (matching the handler interface) for the given event. cuid is the handler uid which can be used to remove the handler with Caller.Remove().

func (*Caller) AddTmp

func (c *Caller) AddTmp(cmd string, deadline time.Duration, handler func(client *Client, event Event) bool) (cuid string, done chan struct{})

AddTmp adds a "temporary" handler, which is good for one-time or few-time uses. This supports a deadline and/or manual removal, as this differs much from how normal handlers work. An example of a good use for this would be to capture the entire output of a multi-response query to the server. (e.g. LIST, WHOIS, etc)

The supplied handler is able to return a boolean, which if true, will remove the handler from the handler stack.

Additionally, AddTmp has a useful option, deadline. When set to greater than 0, deadline will be the amount of time that passes before the handler is removed from the stack, regardless of if the handler returns true or not. This is useful in that it ensures that the handler is cleaned up if the server does not respond appropriately, or takes too long to respond.

Note that handlers supplied with AddTmp are executed in a goroutine to ensure that they are not blocking other handlers. However, if you are creating a temporary handler from another handler, it should be a background handler.

Use cuid with Caller.Remove() to prematurely remove the handler from the stack, bypassing the timeout or waiting for the handler to return that it wants to be removed from the stack.

func (*Caller) Clear

func (c *Caller) Clear(cmd string)

Clear clears all of the handlers for the given event. This ignores internal handlers.

func (*Caller) ClearAll

func (c *Caller) ClearAll()

ClearAll clears all external handlers currently setup within the client. This ignores internal handlers.

func (*Caller) Count

func (c *Caller) Count(cmd string) int

Count is much like Caller.Len(), however it counts the number of registered handlers for a given command.

func (*Caller) Len

func (c *Caller) Len() int

Len returns the total amount of user-entered registered handlers.

func (*Caller) Remove

func (c *Caller) Remove(cuid string) (success bool)

Remove removes the handler with cuid from the handler stack. success indicates that it existed, and has been removed. If not success, it wasn't a registered handler.

func (*Caller) String

func (c *Caller) String() string

type Channel

type Channel struct {
	// Name of the channel. Must be rfc1459 compliant.
	Name string `json:"name"`
	// Topic of the channel.
	Topic string `json:"topic"`

	// UserList is a sorted list of all users we are currently tracking within
	// the channel. Each is the nickname, and is rfc1459 compliant.
	UserList []string `json:"user_list"`
	// Joined represents the first time that the client joined the channel.
	Joined time.Time `json:"joined"`
	// Modes are the known channel modes that the bot has captured.
	Modes CModes `json:"modes"`
}

Channel represents an IRC channel and the state attached to it.

func (Channel) Admins

func (ch Channel) Admins(c *Client) []*User

Admins returns a list of users which have half-op (if supported), or greater permissions (op, admin, owner, etc) in the given channel. See Perms.IsAdmin() for more information.

func (*Channel) Copy

func (ch *Channel) Copy() *Channel

Copy returns a deep copy of a given channel.

func (*Channel) Len

func (ch *Channel) Len() int

Len returns the count of users in a given channel.

func (*Channel) Lifetime

func (ch *Channel) Lifetime() time.Duration

Lifetime represents the amount of time that has passed since we have first joined the channel.

func (Channel) Trusted

func (ch Channel) Trusted(c *Client) []*User

Trusted returns a list of users which have voice or greater in the given channel. See Perms.IsTrusted() for more information.

func (*Channel) UserIn

func (ch *Channel) UserIn(name string) bool

UserIn checks to see if a given user is in a channel.

func (Channel) Users

func (ch Channel) Users(c *Client) []*User

Users returns a reference of *Users that the client knows the channel has If you're just looking for just the name of the users, use Channnel.UserList.

type Client

type Client struct {
	// Config represents the configuration. Please take extra caution in that
	// entries in this are not edited while the client is connected, to prevent
	// data races. This is NOT concurrent safe to update.
	Config Config

	// Handlers is a handler which manages internal and external handlers.
	Handlers *Caller
	// CTCP is a handler which manages internal and external CTCP handlers.
	CTCP *CTCP
	// Cmd contains various helper methods to interact with the server.
	Cmd *Commands
	// contains filtered or unexported fields
}

Client contains all of the information necessary to run a single IRC client.

func New

func New(config Config) *Client

New creates a new IRC client with the specified server, name and config.

func (*Client) ChannelList

func (c *Client) ChannelList() []string

ChannelList returns the (sorted) active list of channel names that the client is in. Panics if tracking is disabled.

func (*Client) Channels

func (c *Client) Channels() []*Channel

Channels returns the (sorted) active channels that the client is in. Panics if tracking is disabled.

func (*Client) Close

func (c *Client) Close()

Close closes the network connection to the server, and sends a CLOSED event. This should cause Connect() to return with nil. This should be safe to call multiple times. See Connect()'s documentation on how handlers and goroutines are handled when disconnected from the server.

func (*Client) ConnSince

func (c *Client) ConnSince() (since *time.Duration, err error)

ConnSince is the duration that has past since the client successfully connected to the server.

func (*Client) Connect

func (c *Client) Connect() error

Connect attempts to connect to the given IRC server. Returns only when an error has occurred, or a disconnect was requested with Close(). Connect will only return once all client-based goroutines have been closed to ensure there are no long-running routines becoming backed up.

Connect will wait for all non-goroutine handlers to complete on error/quit, however it will not wait for goroutine-based handlers.

If this returns nil, this means that the client requested to be closed (e.g. Client.Close()). Connect will panic if called when the last call has not completed.

func (*Client) DialerConnect

func (c *Client) DialerConnect(dialer Dialer) error

DialerConnect allows you to specify your own custom dialer which implements the Dialer interface.

An example of using this library would be to take advantage of the golang.org/x/net/proxy library:

proxyUrl, _ := proxyURI, err = url.Parse("socks5://1.2.3.4:8888")
dialer, _ := proxy.FromURL(proxyURI, &net.Dialer{Timeout: 5 * time.Second})
_ := girc.DialerConnect(dialer)

func (*Client) DisableTracking

func (c *Client) DisableTracking()

DisableTracking disables all channel/user-level/CAP tracking, and clears all internal handlers. Useful for highly embedded scripts with single purposes. This cannot be un-done on a client.

func (*Client) GetHost

func (c *Client) GetHost() (host string)

GetHost returns the current host of the active connection. Panics if tracking is disabled. May be empty, as this is obtained from when we join a channel, as there is no other more efficient method to return this info.

func (*Client) GetID

func (c *Client) GetID() string

GetID returns an RFC1459 compliant version of the current nickname. Panics if tracking is disabled.

func (*Client) GetIdent

func (c *Client) GetIdent() string

GetIdent returns the current ident of the active connection. Panics if tracking is disabled. May be empty, as this is obtained from when we join a channel, as there is no other more efficient method to return this info.

func (*Client) GetNick

func (c *Client) GetNick() string

GetNick returns the current nickname of the active connection. Panics if tracking is disabled.

func (*Client) GetServerOption

func (c *Client) GetServerOption(key string) (result string, ok bool)

GetServerOption retrieves a server capability setting that was retrieved during client connection. This is also known as ISUPPORT (or RPL_PROTOCTL). Will panic if used when tracking has been disabled. Examples of usage:

nickLen, success := GetServerOption("MAXNICKLEN")

func (*Client) HasCapability

func (c *Client) HasCapability(name string) (has bool)

HasCapability checks if the client connection has the given capability. If you want the full list of capabilities, listen for the girc.CAP_ACK event. Will panic if used when tracking has been disabled.

func (*Client) IsConnected

func (c *Client) IsConnected() bool

IsConnected returns true if the client is connected to the server.

func (*Client) IsInChannel

func (c *Client) IsInChannel(channel string) (in bool)

IsInChannel returns true if the client is in channel. Panics if tracking is disabled.

func (*Client) Latency

func (c *Client) Latency() (delta time.Duration)

Latency is the latency between the server and the client. This is measured by determining the difference in time between when we ping the server, and when we receive a pong.

func (*Client) Lifetime

func (c *Client) Lifetime() time.Duration

Lifetime returns the amount of time that has passed since the client was created.

func (*Client) LookupChannel

func (c *Client) LookupChannel(name string) (channel *Channel)

LookupChannel looks up a given channel in state. If the channel doesn't exist, nil is returned. Panics if tracking is disabled.

func (*Client) LookupUser

func (c *Client) LookupUser(nick string) (user *User)

LookupUser looks up a given user in state. If the user doesn't exist, nil is returned. Panics if tracking is disabled.

func (*Client) MockConnect

func (c *Client) MockConnect(conn net.Conn) error

MockConnect is used to implement mocking with an IRC server. Supply a net.Conn that will be used to spoof the server. A useful way to do this is to so net.Pipe(), pass one end into MockConnect(), and the other end into bufio.NewReader().

For example:

client := girc.New(girc.Config{
	Server: "dummy.int",
	Port:   6667,
	Nick:   "test",
	User:   "test",
	Name:   "Testing123",
})

in, out := net.Pipe()
defer in.Close()
defer out.Close()
b := bufio.NewReader(in)

go func() {
	if err := client.MockConnect(out); err != nil {
		panic(err)
	}
}()

defer client.Close(false)

for {
	in.SetReadDeadline(time.Now().Add(300 * time.Second))
	line, err := b.ReadString(byte('\n'))
	if err != nil {
		panic(err)
	}

	event := girc.ParseEvent(line)

	if event == nil {
 		continue
 	}

 	// Do stuff with event here.
 }

func (*Client) NetworkName

func (c *Client) NetworkName() (name string)

NetworkName returns the network identifier. E.g. "EsperNet", "ByteIRC". May be empty if the server does not support RPL_ISUPPORT (or RPL_PROTOCTL). Will panic if used when tracking has been disabled.

func (*Client) Quit

func (c *Client) Quit(reason string)

Quit sends a QUIT message to the server with a given reason to close the connection. Underlying this event being sent, Client.Close() is called as well. This is different than just calling Client.Close() in that it provides a reason as to why the connection was closed (for bots to tell users the bot is restarting, or shutting down, etc).

NOTE: servers may delay showing of QUIT reasons, until you've been connected to the server for a certain period of time (e.g. 5 minutes). Keep this in mind.

func (*Client) RunHandlers

func (c *Client) RunHandlers(event *Event)

RunHandlers manually runs handlers for a given event.

func (*Client) Send

func (c *Client) Send(event *Event)

Send sends an event to the server. Use Client.RunHandlers() if you are simply looking to trigger handlers with an event.

func (*Client) Server

func (c *Client) Server() string

Server returns the string representation of host+port pair for the connection.

func (*Client) ServerMOTD

func (c *Client) ServerMOTD() (motd string)

ServerMOTD returns the servers message of the day, if the server has sent it upon connect. Will panic if used when tracking has been disabled.

func (*Client) ServerVersion

func (c *Client) ServerVersion() (version string)

ServerVersion returns the server software version, if the server has supplied this information during connection. May be empty if the server does not support RPL_MYINFO. Will panic if used when tracking has been disabled.

func (*Client) String

func (c *Client) String() string

String returns a brief description of the current client state.

func (*Client) TLSConnectionState

func (c *Client) TLSConnectionState() (*tls.ConnectionState, error)

TLSConnectionState returns the TLS connection state from tls.Conn{}, which is useful to return needed TLS fingerprint info, certificates, verify cert expiration dates, etc. Will only return an error if the underlying connection wasn't established using TLS (see ErrConnNotTLS), or if the client isn't connected.

func (*Client) Uptime

func (c *Client) Uptime() (up time.Time, err error)

Uptime is the time at which the client successfully connected to the server.

func (*Client) UserList

func (c *Client) UserList() []string

UserList returns the (sorted) active list of nicknames that the client is tracking across all channels. Panics if tracking is disabled.

func (*Client) Users

func (c *Client) Users() []*User

Users returns the (sorted) active users that the client is tracking across all channels. Panics if tracking is disabled.

type Commands

type Commands struct {
	// contains filtered or unexported fields
}

Commands holds a large list of useful methods to interact with the server, and wrappers for common events.

func (*Commands) Action

func (cmd *Commands) Action(target, message string)

Action sends a PRIVMSG ACTION (/me) to target (either channel, service, or user).

func (*Commands) Actionf

func (cmd *Commands) Actionf(target, format string, a ...interface{})

Actionf sends a formated PRIVMSG ACTION (/me) to target (either channel, service, or user).

func (*Commands) Away

func (cmd *Commands) Away(reason string)

Away sends a AWAY query to the server, suggesting that the client is no longer active. If reason is blank, Client.Back() is called. Also see Client.Back().

func (*Commands) Back

func (cmd *Commands) Back()

Back sends a AWAY query to the server, however the query is blank, suggesting that the client is active once again. Also see Client.Away().

func (*Commands) Ban

func (cmd *Commands) Ban(channel, mask string)

Ban adds the +b mode on the given mask on a channel.

func (*Commands) Invite

func (cmd *Commands) Invite(channel string, users ...string)

Invite sends a INVITE query to the server, to invite nick to channel.

func (*Commands) Join

func (cmd *Commands) Join(channels ...string)

Join attempts to enter a list of IRC channels, at bulk if possible to prevent sending extensive JOIN commands.

func (*Commands) JoinKey

func (cmd *Commands) JoinKey(channel, password string)

JoinKey attempts to enter an IRC channel with a password.

func (*Commands) Kick

func (cmd *Commands) Kick(channel, user, reason string)

Kick sends a KICK query to the server, attempting to kick nick from channel, with reason. If reason is blank, one will not be sent to the server.

func (*Commands) List

func (cmd *Commands) List(channels ...string)

List sends a LIST query to the server, which will list channels and topics. Supports multiple channels at once, in hopes it will reduce extensive LIST queries to the server. Supply no channels to run a list against the entire server (warning, that may mean LOTS of channels!)

func (*Commands) Message

func (cmd *Commands) Message(target, message string)

Message sends a PRIVMSG to target (either channel, service, or user).

func (*Commands) Messagef

func (cmd *Commands) Messagef(target, format string, a ...interface{})

Messagef sends a formated PRIVMSG to target (either channel, service, or user).

func (*Commands) Mode

func (cmd *Commands) Mode(target, modes string, params ...string)

Mode sends a mode change to the server which should be applied to target (usually a channel or user), along with a set of modes (generally "+m", "+mmmm", or "-m", where "m" is the mode you want to change). Params is only needed if the mode change requires a parameter (ban or invite-only exclude.)

func (*Commands) Monitor

func (cmd *Commands) Monitor(modifier rune, args ...string)

Monitor sends a MONITOR query to the server. The results of the query depends on the given modifier, see https://ircv3.net/specs/core/monitor-3.2.html

func (*Commands) Nick

func (cmd *Commands) Nick(name string)

Nick changes the client nickname.

func (*Commands) Notice

func (cmd *Commands) Notice(target, message string)

Notice sends a NOTICE to target (either channel, service, or user).

func (*Commands) Noticef

func (cmd *Commands) Noticef(target, format string, a ...interface{})

Noticef sends a formated NOTICE to target (either channel, service, or user).

func (*Commands) Oper

func (cmd *Commands) Oper(user, pass string)

Oper sends a OPER authentication query to the server, with a username and password.

func (*Commands) Part

func (cmd *Commands) Part(channels ...string)

Part leaves an IRC channel.

func (*Commands) PartMessage

func (cmd *Commands) PartMessage(channel, message string)

PartMessage leaves an IRC channel with a specified leave message.

func (*Commands) Ping

func (cmd *Commands) Ping(id string)

Ping sends a PING query to the server, with a specific identifier that the server should respond with.

func (*Commands) Pong

func (cmd *Commands) Pong(id string)

Pong sends a PONG query to the server, with an identifier which was received from a previous PING query received by the client.

func (*Commands) Reply

func (cmd *Commands) Reply(event Event, message string)

Reply sends a reply to channel or user, based on where the supplied event originated from. See also ReplyTo(). Panics if the incoming event has no source.

func (*Commands) ReplyBan

func (cmd *Commands) ReplyBan(event Event, reason string)

ReplyBan kicks the source of the event from the channel where the event originated

func (*Commands) ReplyKick

func (cmd *Commands) ReplyKick(event Event, reason string)

ReplyKick kicks the source of the event from the channel where the event originated

func (*Commands) ReplyTo

func (cmd *Commands) ReplyTo(event Event, message string)

ReplyTo sends a reply to a channel or user, based on where the supplied event originated from. ReplyTo(), when originating from a channel will default to replying with "<user>, <message>". See also Reply(). Panics if the incoming event has no source.

func (*Commands) ReplyTof

func (cmd *Commands) ReplyTof(event Event, format string, a ...interface{})

ReplyTof sends a reply to a channel or user with a format string, based on where the supplied event originated from. ReplyTo(), when originating from a channel will default to replying with "<user>, <message>". See also Replyf(). Panics if the incoming event has no source.

func (*Commands) Replyf

func (cmd *Commands) Replyf(event Event, format string, a ...interface{})

Replyf sends a reply to channel or user with a format string, based on where the supplied event originated from. See also ReplyTof(). Panics if the incoming event has no source.

func (*Commands) SendCTCP

func (cmd *Commands) SendCTCP(target, ctcpType, message string)

SendCTCP sends a CTCP request to target. Note that this method uses PRIVMSG specifically. ctcpType is the CTCP command, e.g. "FINGER", "TIME", "VERSION", etc.

func (*Commands) SendCTCPReply

func (cmd *Commands) SendCTCPReply(target, ctcpType, message string)

SendCTCPReply sends a CTCP response to target. Note that this method uses NOTICE specifically.

func (*Commands) SendCTCPReplyf

func (cmd *Commands) SendCTCPReplyf(target, ctcpType, format string, a ...interface{})

SendCTCPReplyf sends a CTCP response to target using a specific format. Note that this method uses NOTICE specifically. ctcpType is the CTCP command, e.g. "FINGER", "TIME", "VERSION", etc.

func (*Commands) SendCTCPf

func (cmd *Commands) SendCTCPf(target, ctcpType, format string, a ...interface{})

SendCTCPf sends a CTCP request to target using a specific format. Note that this method uses PRIVMSG specifically. ctcpType is the CTCP command, e.g. "FINGER", "TIME", "VERSION", etc.

func (*Commands) SendRaw

func (cmd *Commands) SendRaw(raw ...string) error

SendRaw sends a raw string (or multiple) to the server, without carriage returns or newlines. Returns an error if one of the raw strings cannot be properly parsed.

func (*Commands) SendRawf

func (cmd *Commands) SendRawf(format string, a ...interface{}) error

SendRawf sends a formated string back to the server, without carriage returns or newlines.

func (*Commands) Topic

func (cmd *Commands) Topic(channel, message string)

Topic sets the topic of channel to message. Does not verify the length of the topic.

func (*Commands) Unban

func (cmd *Commands) Unban(channel, mask string)

Unban removes the +b mode on the given mask on a channel.

func (*Commands) Who

func (cmd *Commands) Who(users ...string)

Who sends a WHO query to the server, which will attempt WHOX by default. See http://faerion.sourceforge.net/doc/irc/whox.var for more details. This sends "%tcuhnr,2" per default. Do not use "1" as this will conflict with girc's builtin tracking functionality.

func (*Commands) Whois

func (cmd *Commands) Whois(users ...string)

Whois sends a WHOIS query to the server, targeted at a specific user (or set of users). As WHOIS is a bit slower, you may want to use WHO for brief user info.

func (*Commands) Whowas

func (cmd *Commands) Whowas(user string, amount int)

Whowas sends a WHOWAS query to the server. amount is the amount of results you want back.

type Config

type Config struct {
	// Server is a host/ip of the server you want to connect to. This only
	// has an affect during the dial process
	Server string
	// ServerPass is the server password used to authenticate. This only has
	// an affect during the dial process.
	ServerPass string
	// Port is the port that will be used during server connection. This only
	// has an affect during the dial process.
	Port int
	// Nick is an rfc-valid nickname used during connection. This only has an
	// affect during the dial process.
	Nick string
	// User is the username/ident to use on connect. Ignored if an identd
	// server is used. This only has an affect during the dial process.
	User string
	// Name is the "realname" that's used during connection. This only has an
	// affect during the dial process.
	Name string
	// SASL contains the necessary authentication data to authenticate
	// with SASL. See the documentation for SASLMech for what is currently
	// supported. Capability tracking must be enabled for this to work, as
	// this requires IRCv3 CAP handling.
	SASL SASLMech
	// WebIRC allows forwarding source user hostname/ip information to the server
	// (if supported by the server) to ensure the source machine doesn't show as
	// the source. See the WebIRC type for more information.
	WebIRC WebIRC
	// Bind is used to bind to a specific host or ip during the dial process
	// when connecting to the server. This can be a hostname, however it must
	// resolve to an IPv4/IPv6 address bindable on your system. Otherwise,
	// you can simply use a IPv4/IPv6 address directly. This only has an
	// affect during the dial process and will not work with DialerConnect().
	Bind string
	// SSL allows dialing via TLS. See TLSConfig to set your own TLS
	// configuration (e.g. to not force hostname checking). This only has an
	// affect during the dial process.
	SSL bool
	// DisableSTS disables the use of automatic STS connection upgrades
	// when the server supports STS. STS can also be disabled using the environment
	// variable "GIRC_DISABLE_STS=true". As many clients may not propagate options
	// like this back to the user, this allows to directly disable such automatic
	// functionality.
	DisableSTS bool
	// DisableSTSFallback disables the "fallback" to a non-tls connection if the
	// strict transport policy expires and the first attempt to reconnect back to
	// the tls version fails.
	DisableSTSFallback bool
	// TLSConfig is an optional user-supplied tls configuration, used during
	// socket creation to the server. SSL must be enabled for this to be used.
	// This only has an affect during the dial process.
	TLSConfig *tls.Config
	// AllowFlood allows the client to bypass the rate limit of outbound
	// messages.
	AllowFlood bool
	// GlobalFormat enables passing through all events which have trailing
	// text through the color Fmt() function, so you don't have to wrap
	// every response in the Fmt() method.
	//
	// Note that this only actually applies to PRIVMSG, NOTICE and TOPIC
	// events, to ensure it doesn't clobber unwanted events.
	GlobalFormat bool
	// Debug is an optional, user supplied location to log the raw lines
	// sent from the server, or other useful debug logs. Defaults to
	// ioutil.Discard. For quick debugging, this could be set to os.Stdout.
	Debug io.Writer
	// Out is used to write out a prettified version of incoming events. For
	// example, channel JOIN/PART, PRIVMSG/NOTICE, KICk, etc. Useful to get
	// a brief output of the activity of the client. If you are looking to
	// log raw messages, look at a handler and girc.ALLEVENTS and the relevant
	// Event.Bytes() or Event.String() methods.
	Out io.Writer
	// RecoverFunc is called when a handler throws a panic. If RecoverFunc is
	// set, the panic will be considered recovered, otherwise the client will
	// panic. Set this to DefaultRecoverHandler if you don't want the client
	// to panic, however you don't want to handle the panic yourself.
	// DefaultRecoverHandler will log the panic to Debug or os.Stdout if
	// Debug is unset.
	RecoverFunc func(c *Client, e *HandlerError)
	// SupportedCaps are the IRCv3 capabilities you would like the client to
	// support on top of the ones which the client already supports (see
	// cap.go for which ones the client enables by default). Only use this
	// if you have not called DisableTracking(). The keys value gets passed
	// to the server if supported.
	SupportedCaps map[string][]string
	// Version is the application version information that will be used in
	// response to a CTCP VERSION, if default CTCP replies have not been
	// overwritten or a VERSION handler was already supplied.
	Version string
	// PingDelay is the frequency between when the client sends a keep-alive
	// PING to the server, and awaits a response (and times out if the server
	// doesn't respond in time). This should be between 20-600 seconds. See
	// Client.Latency() if you want to determine the delay between the server
	// and the client. If this is set to -1, the client will not attempt to
	// send client -> server PING requests.
	PingDelay time.Duration

	// HandleNickCollide when set, allows the client to handle nick collisions
	// in a custom way. If unset, the client will attempt to append a
	// underscore to the end of the nickname, in order to bypass using
	// an invalid nickname. For example, if "test" is already in use, or is
	// blocked by the network/a service, the client will try and use "test_",
	// then it will attempt "test__", "test___", and so on.
	HandleNickCollide func(oldNick string) (newNick string)
	// contains filtered or unexported fields
}

Config contains configuration options for an IRC client

type Dialer

type Dialer interface {
	// Dial takes two arguments. Network, which should be similar to "tcp",
	// "tdp6", "udp", etc -- as well as address, which is the hostname or ip
	// of the network. Note that network can be ignored if your transport
	// doesn't take advantage of network types.
	Dial(network, address string) (net.Conn, error)
}

Dialer is an interface implementation of net.Dialer. Use this if you would like to implement your own dialer which the client will use when connecting.

type ErrEvent

type ErrEvent struct {
	Event *Event
}

ErrEvent is an error returned when the server (or library) sends an ERROR message response. The string returned contains the trailing text from the message.

func (*ErrEvent) Error

func (e *ErrEvent) Error() string

type ErrInvalidConfig

type ErrInvalidConfig struct {
	Conf Config // Conf is the configuration that was not valid.
	// contains filtered or unexported fields
}

ErrInvalidConfig is returned when the configuration passed to the client is invalid.

func (ErrInvalidConfig) Error

func (e ErrInvalidConfig) Error() string

type ErrParseEvent

type ErrParseEvent struct {
	Line string
}

ErrParseEvent is returned when an event cannot be parsed with ParseEvent().

func (ErrParseEvent) Error

func (e ErrParseEvent) Error() string

type ErrSTSUpgradeFailed

type ErrSTSUpgradeFailed struct {
	Err error
}

ErrSTSUpgradeFailed is an error that occurs when a connection that was attempted to be upgraded via a strict transport policy, failed. This does not necessarily indicate that STS was to blame, but the underlying connection failed for some reason.

func (ErrSTSUpgradeFailed) Error

func (e ErrSTSUpgradeFailed) Error() string

type ErrTimedOut

type ErrTimedOut struct {
	// TimeSinceSuccess is how long ago we received a successful pong.
	TimeSinceSuccess time.Duration
	// LastPong is the time we received our last successful pong.
	LastPong time.Time
	// LastPong is the last time we sent a pong request.
	LastPing time.Time
	// Delay is the configured delay between how often we send a ping request.
	Delay time.Duration
}

ErrTimedOut is returned when we attempt to ping the server, and timed out before receiving a PONG back.

func (ErrTimedOut) Error

func (ErrTimedOut) Error() string

type Event

type Event struct {
	// Source is the origin of the event.
	Source *Source `json:"source"`
	// Tags are the IRCv3 style message tags for the given event. Only use
	// if network supported.
	Tags Tags `json:"tags"`
	// Timestamp is the time the event was received. This could optionally be
	// used for client-stored sent messages too. If the server supports the
	// "server-time" capability, this is synced to the UTC time that the server
	// specifies.
	Timestamp time.Time `json:"timestamp"`
	// Command that represents the event, e.g. JOIN, PRIVMSG, KILL.
	Command string `json:"command"`
	// Params (parameters/args) to the command. Commonly nickname, channel, etc.
	// The last item in the slice could potentially contain spaces (commonly
	// referred to as the "trailing" parameter).
	Params []string `json:"params"`
	// Sensitive should be true if the message is sensitive (e.g. and should
	// not be logged/shown in debugging output).
	Sensitive bool `json:"sensitive"`
	// If the event is an echo-message response.
	Echo bool `json:"echo"`
}

Event represents an IRC protocol message, see RFC1459 section 2.3.1

<message>  :: [':' <prefix> <SPACE>] <command> <params> <crlf>
<prefix>   :: <servername> | <nick> ['!' <user>] ['@' <host>]
<command>  :: <letter>{<letter>} | <number> <number> <number>
<SPACE>    :: ' '{' '}
<params>   :: <SPACE> [':' <trailing> | <middle> <params>]
<middle>   :: <Any *non-empty* sequence of octets not including SPACE or NUL
               or CR or LF, the first of which may not be ':'>
<trailing> :: <Any, possibly empty, sequence of octets not including NUL or
               CR or LF>
<crlf>     :: CR LF

func ParseEvent

func ParseEvent(raw string) (e *Event)

ParseEvent takes a string and attempts to create a Event struct. Returns nil if the Event is invalid.

func (*Event) Bytes

func (e *Event) Bytes() []byte

Bytes returns a []byte representation of event. Strips all newlines and carriage returns.

Per RFC2812 section 2.3, messages should not exceed 512 characters in length. This method forces that limit by discarding any characters exceeding the length limit.

func (*Event) Copy

func (e *Event) Copy() *Event

Copy makes a deep copy of a given event, for use with allowing untrusted functions/handlers edit the event without causing potential issues with other handlers.

func (*Event) Equals

func (e *Event) Equals(ev *Event) bool

Equals compares two Events for equality.

func (*Event) IsAction

func (e *Event) IsAction() bool

IsAction checks to see if the event is an ACTION (/me).

func (*Event) IsCTCP

func (e *Event) IsCTCP() (ok bool, ctcp *CTCPEvent)

IsCTCP checks to see if the event is a CTCP event, and if so, returns the converted CTCP event.

func (*Event) IsFromChannel

func (e *Event) IsFromChannel() bool

IsFromChannel checks to see if a message was from a channel (rather than a private message).

func (*Event) IsFromUser

func (e *Event) IsFromUser() bool

IsFromUser checks to see if a message was from a user (rather than a channel).

func (*Event) Last

func (e *Event) Last() string

Last returns the last parameter in Event.Params if it exists.

func (*Event) Len

func (e *Event) Len() (length int)

Len calculates the length of the string representation of event. Note that this will return the true length (even if longer than what IRC supports), which may be useful if you are trying to check and see if a message is too long, to trim it down yourself.

func (*Event) Pretty

func (e *Event) Pretty() (out string, ok bool)

Pretty returns a prettified string of the event. If the event doesn't support prettification, ok is false. Pretty is not just useful to make an event prettier, but also to filter out events that most don't visually see in normal IRC clients. e.g. most clients don't show WHO queries.

func (*Event) String

func (e *Event) String() string

String returns a string representation of this event. Strips all newlines and carriage returns.

func (*Event) StripAction

func (e *Event) StripAction() string

StripAction returns the stripped version of the action encoding from a PRIVMSG ACTION (/me).

type Handler

type Handler interface {
	Execute(*Client, Event)
}

Handler is lower level implementation of a handler. See Caller.AddHandler()

type HandlerError

type HandlerError struct {
	Event Event       // Event is the event that caused the error.
	ID    string      // ID is the CUID of the handler.
	File  string      // File is the file from where the panic originated.
	Line  int         // Line number where panic originated.
	Func  string      // Function name where panic originated.
	Panic interface{} // Panic is the error that was passed to panic().
	Stack []byte      // Stack is the call stack. Note you may have to skip 1 or 2 due to debug functions.
	// contains filtered or unexported fields
}

HandlerError is the error returned when a panic is intentionally recovered from. It contains useful information like the handler identifier (if applicable), filename, line in file where panic occurred, the call trace, and original event.

func (*HandlerError) Error

func (e *HandlerError) Error() string

Error returns a prettified version of HandlerError, containing ID, file, line, and basic error string.

func (*HandlerError) String

func (e *HandlerError) String() string

String returns the error that panic returned, as well as the entire call trace of where it originated.

type HandlerFunc

type HandlerFunc func(client *Client, event Event)

HandlerFunc is a type that represents the function necessary to implement Handler.

func (HandlerFunc) Execute

func (f HandlerFunc) Execute(client *Client, event Event)

Execute calls the HandlerFunc with the sender and irc message.

type Perms

type Perms struct {
	// Owner (non-rfc) indicates that the user has full permissions to the
	// channel. More than one user can have owner permission.
	Owner bool `json:"owner"`
	// Admin (non-rfc) is commonly given to users that are trusted enough
	// to manage channel permissions, as well as higher level service settings.
	Admin bool `json:"admin"`
	// Op is commonly given to trusted users who can manage a given channel
	// by kicking, and banning users.
	Op bool `json:"op"`
	// HalfOp (non-rfc) is commonly used to give users permissions like the
	// ability to kick, without giving them greater abilities to ban all users.
	HalfOp bool `json:"half_op"`
	// Voice indicates the user has voice permissions, commonly given to known
	// users, with very light trust, or to indicate a user is active.
	Voice bool `json:"voice"`
}

Perms contains all channel-based user permissions. The minimum op, and voice should be supported on all networks. This also supports non-rfc Owner, Admin, and HalfOp, if the network has support for it.

func (Perms) IsAdmin

func (m Perms) IsAdmin() bool

IsAdmin indicates that the user has banning abilities, and are likely a very trustable user (e.g. op+).

func (Perms) IsTrusted

func (m Perms) IsTrusted() bool

IsTrusted indicates that the user at least has modes set upon them, higher than a regular joining user.

type SASLExternal

type SASLExternal struct {
	// Identity is an optional field which allows the client to specify
	// pre-authentication identification. This means that EXTERNAL will
	// supply this in the initial response. This usually isn't needed (e.g.
	// CertFP).
	Identity string `json:"identity"`
}

SASLExternal implements the "EXTERNAL" SASL type.

func (*SASLExternal) Encode

func (sasl *SASLExternal) Encode(params []string) string

Encode for external SALS authentication should really only return a "+", unless the user has specified pre-authentication or identification data. See https://tools.ietf.org/html/rfc4422#appendix-A for more info.

func (*SASLExternal) Method

func (sasl *SASLExternal) Method() string

Method identifies what type of SASL this implements.

type SASLMech

type SASLMech interface {
	// Method returns the uppercase version of the SASL mechanism name.
	Method() string
	// Encode returns the response that the SASL mechanism wants to use. If
	// the returned string is empty (e.g. the mechanism gives up), the handler
	// will attempt to panic, as expectation is that if SASL authentication
	// fails, the client will disconnect.
	Encode(params []string) (output string)
}

SASLMech is an representation of what a SASL mechanism should support. See SASLExternal and SASLPlain for implementations of this.

type SASLPlain

type SASLPlain struct {
	User string `json:"user"` // User is the username for SASL.
	Pass string `json:"pass"` // Pass is the password for SASL.
}

SASLPlain contains the user and password needed for PLAIN SASL authentication.

func (*SASLPlain) Encode

func (sasl *SASLPlain) Encode(params []string) string

Encode encodes the plain user+password into a SASL PLAIN implementation. See https://tools.ietf.org/rfc/rfc4422.txt for more info.

func (*SASLPlain) Method

func (sasl *SASLPlain) Method() string

Method identifies what type of SASL this implements.

type Source

type Source struct {
	// Name is the nickname, server name, or service name, in its original
	// non-rfc1459 form.
	Name string `json:"name"`
	// Ident is commonly known as the "user".
	Ident string `json:"ident"`
	// Host is the hostname or IP address of the user/service. Is not accurate
	// due to how IRC servers can spoof hostnames.
	Host string `json:"host"`
}

Source represents the sender of an IRC event, see RFC1459 section 2.3.1. <servername> | <nick> [ '!' <user> ] [ '@' <host> ]

func ParseSource

func ParseSource(raw string) (src *Source)

ParseSource takes a string and attempts to create a Source struct.

func (*Source) Bytes

func (s *Source) Bytes() []byte

Bytes returns a []byte representation of source.

func (*Source) Copy

func (s *Source) Copy() *Source

Copy returns a deep copy of Source.

func (*Source) Equals

func (s *Source) Equals(ss *Source) bool

Equals compares two Sources for equality.

func (*Source) ID

func (s *Source) ID() string

ID is the nickname, server name, or service name, in it's converted and comparable) form.

func (*Source) IsHostmask

func (s *Source) IsHostmask() bool

IsHostmask returns true if source looks like a user hostmask.

func (*Source) IsServer

func (s *Source) IsServer() bool

IsServer returns true if this source looks like a server name.

func (*Source) Len

func (s *Source) Len() (length int)

Len calculates the length of the string representation of prefix

func (*Source) String

func (s *Source) String() (out string)

String returns a string representation of source.

type Tags

type Tags map[string]string

Tags represents the key-value pairs in IRCv3 message tags. The map contains the encoded message-tag values. If the tag is present, it may still be empty. See Tags.Get() and Tags.Set() for use with getting/setting information within the tags.

Note that retrieving and setting tags are not concurrent safe. If this is necessary, you will need to implement it yourself.

func ParseTags

func ParseTags(raw string) (t Tags)

ParseTags parses out the key-value map of tags. raw should only be the tag data, not a full message. For example:

@aaa=bbb;ccc;example.com/ddd=eee

NOT:

@aaa=bbb;ccc;example.com/ddd=eee :nick!ident@host.com PRIVMSG me :Hello

Technically, there is a length limit of 4096, but the server should reject tag messages longer than this.

func (Tags) Bytes

func (t Tags) Bytes() []byte

Bytes returns a []byte representation of this tag map, including the tag prefix ("@"). Note that this will return the tags sorted, regardless of the order of how they were originally parsed.

func (Tags) Count

func (t Tags) Count() int

Count finds how many total tags that there are.

func (Tags) Equals

func (t Tags) Equals(tt Tags) bool

Equals compares two Tags for equality. With the msgid IRCv3 spec +\ echo-message (amongst others), we may receive events that have msgid's, whereas our local events will not have the msgid. As such, don't compare all tags, only the necessary/important tags.

func (Tags) Get

func (t Tags) Get(key string) (tag string, success bool)

Get returns the unescaped value of given tag key. Note that this is not concurrent safe.

func (Tags) Keys

func (t Tags) Keys() (keys []string)

Keys returns a slice of (unsorted) tag keys.

func (Tags) Len

func (t Tags) Len() (length int)

Len determines the length of the bytes representation of this tag map. This does not include the trailing space required when creating an event, but does include the tag prefix ("@").

func (Tags) Remove

func (t Tags) Remove(key string) (success bool)

Remove deletes the tag frwom the tag map.

func (Tags) Set

func (t Tags) Set(key, value string) error

Set escapes given value and saves it as the value for given key. Note that this is not concurrent safe.

func (Tags) String

func (t Tags) String() string

String returns a string representation of this tag map.

type User

type User struct {
	// Nick is the users current nickname. rfc1459 compliant.
	Nick string `json:"nick"`
	// Ident is the users username/ident. Ident is commonly prefixed with a
	// "~", which indicates that they do not have a identd server setup for
	// authentication.
	Ident string `json:"ident"`
	// Host is the visible host of the users connection that the server has
	// provided to us for their connection. May not always be accurate due to
	// many networks spoofing/hiding parts of the hostname for privacy
	// reasons.
	Host string `json:"host"`

	// ChannelList is a sorted list of all channels that we are currently
	// tracking the user in. Each channel name is rfc1459 compliant. See
	// User.Channels() for a shorthand if you're looking for the *Channel
	// version of the channel list.
	ChannelList []string `json:"channels"`

	// FirstSeen represents the first time that the user was seen by the
	// client for the given channel. Only usable if from state, not in past.
	FirstSeen time.Time `json:"first_seen"`
	// LastActive represents the last time that we saw the user active,
	// which could be during nickname change, message, channel join, etc.
	// Only usable if from state, not in past.
	LastActive time.Time `json:"last_active"`

	// Perms are the user permissions applied to this user that affect the given
	// channel. This supports non-rfc style modes like Admin, Owner, and HalfOp.
	Perms *UserPerms `json:"perms"`

	// Extras are things added on by additional tracking methods, which may
	// or may not work on the IRC server in mention.
	Extras struct {
		// Name is the users "realname" or full name. Commonly contains links
		// to the IRC client being used, or something of non-importance. May
		// also be empty if unsupported by the server/tracking is disabled.
		Name string `json:"name"`
		// Account refers to the account which the user is authenticated as.
		// This differs between each network (e.g. usually Nickserv, but
		// could also be something like Undernet). May also be empty if
		// unsupported by the server/tracking is disabled.
		Account string `json:"account"`
		// Away refers to the away status of the user. An empty string
		// indicates that they are active, otherwise the string is what they
		// set as their away message. May also be empty if unsupported by the
		// server/tracking is disabled.
		Away string `json:"away"`
	} `json:"extras"`
}

User represents an IRC user and the state attached to them.

func (*User) Active

func (u *User) Active() time.Duration

Active represents the the amount of time that has passed since we have last seen the user.

func (User) Channels

func (u User) Channels(c *Client) []*Channel

Channels returns a reference of *Channels that the client knows the user is in. If you're just looking for the namme of the channels, use User.ChannelList.

func (*User) Copy

func (u *User) Copy() *User

Copy returns a deep copy of the user which can be modified without making changes to the actual state.

func (*User) InChannel

func (u *User) InChannel(name string) bool

InChannel checks to see if a user is in the given channel.

func (*User) IsActive

func (u *User) IsActive() bool

IsActive returns true if they were active within the last 30 minutes.

func (*User) Lifetime

func (u *User) Lifetime() time.Duration

Lifetime represents the amount of time that has passed since we have first seen the user.

type UserPerms

type UserPerms struct {
	// contains filtered or unexported fields
}

UserPerms contains all of the permissions for each channel the user is in.

func (*UserPerms) Copy

func (p *UserPerms) Copy() (perms *UserPerms)

Copy returns a deep copy of the channel permissions.

func (*UserPerms) Lookup

func (p *UserPerms) Lookup(channel string) (perms Perms, ok bool)

Lookup looks up the users permissions for a given channel. ok is false if the user is not in the given channel.

func (*UserPerms) MarshalJSON

func (p *UserPerms) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

type WebIRC

type WebIRC struct {
	// Password that authenticates the WEBIRC command from this client.
	Password string
	// Gateway or client type requesting spoof (cgiirc defaults to cgiirc, as an
	// example).
	Gateway string
	// Hostname of user.
	Hostname string
	// Address either in IPv4 dotted quad notation (e.g. 192.0.0.2) or IPv6
	// notation (e.g. 1234:5678:9abc::def). IPv4-in-IPv6 addresses
	// (e.g. ::ffff:192.0.0.2) should not be sent.
	Address string
}

WebIRC is useful when a user connects through an indirect method, such web clients, the indirect client sends its own IP address instead of sending the user's IP address unless WebIRC is implemented by both the client and the server.

Client expectations:

  • Perform any proxy resolution.
  • Check the reverse DNS and forward DNS match.
  • Check the IP against suitable access controls (ipaccess, dnsbl, etc).

More information:

func (WebIRC) Params

func (w WebIRC) Params() []string

Params returns the arguments for the WEBIRC command that can be passed to the server.

Jump to

Keyboard shortcuts

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