Event-based stateful IRC client framework for Go.

Build Status

GoIRC Client Framework

Acquiring and Building

Pretty simple, really:

go get github.com/fluffle/goirc/client

There is some example code that demonstrates usage of the library in client.go. This will connect to freenode and join #go-nuts by default, so be careful ;-)

See fix/goirc.go and the README there for a quick way to migrate from the old go1 API.

Using the framework

Synopsis:

package main

import (
	"crypto/tls"
	"fmt"

	irc "github.com/fluffle/goirc/client"
)

func main() {
	// Creating a simple IRC client is simple.
	c := irc.SimpleClient("nick")

	// Or, create a config and fiddle with it first:
	cfg := irc.NewConfig("nick")
	cfg.SSL = true
	cfg.SSLConfig = &tls.Config{ServerName: "irc.freenode.net"}
	cfg.Server = "irc.freenode.net:7000"
	cfg.NewNick = func(n string) string { return n + "^" }
	c = irc.Client(cfg)

	// Add handlers to do things here!
	// e.g. join a channel on connect.
	c.HandleFunc(irc.CONNECTED,
		func(conn *irc.Conn, line *irc.Line) { conn.Join("#channel") })
	// And a signal on disconnect
	quit := make(chan bool)
	c.HandleFunc(irc.DISCONNECTED,
		func(conn *irc.Conn, line *irc.Line) { quit <- true })

	// Tell client to connect.
	if err := c.Connect(); err != nil {
		fmt.Printf("Connection error: %s\n", err.Error())
	}

	// With a "simple" client, set Server before calling Connect...
	c.Config().Server = "irc.freenode.net"

	// ... or, use ConnectTo instead.
	if err := c.ConnectTo("irc.freenode.net"); err != nil {
		fmt.Printf("Connection error: %s\n", err.Error())
	}

	// Wait for disconnect
	<-quit
}

The test client provides a good (if basic) example of how to use the framework. Reading client/handlers.go gives a more in-depth look at how handlers can be written. Commands to be sent to the server (e.g. PRIVMSG) are methods of the main *Conn struct, and can be found in client/commands.go (not all of the possible IRC commands are implemented yet). Events are produced directly from the messages from the IRC server, so you have to handle e.g. "332" for RPL_TOPIC to get the topic for a channel.

The vast majority of handlers implemented within the framework deal with state tracking of all nicks in any channels that the client is also present in. These handlers are in client/state_handlers.go. State tracking is optional, disabled by default, and can be enabled and disabled by calling EnableStateTracking() and DisableStateTracking() respectively. Doing this while connected to an IRC server will probably result in an inconsistent state and a lot of warnings to STDERR ;-)

Misc.

Sorry the documentation is crap. Use the source, Luke.

Feedback on design decisions is welcome. I am indebted to Matt Gruen for his work on go-bot which inspired the re-organisation and channel-based communication structure of *Conn.send() and *Conn.recv(). I'm sure things could be more asynchronous, still.

This code is (c) 2009-15 Alex Bramley, and released under the same licence terms as Go itself.

Contributions gratefully received from:

And thanks to the following for minor doc/fix PRs:

Comments
  • client/connection: keep information in disconnected event, revert #43

    client/connection: keep information in disconnected event, revert #43

    Revert of https://github.com/fluffle/goirc/commit/3fdd17a2b88b167b0a9ae6d219375bc47cc91f04 of #43. Context: https://github.com/StalkR/goircbot/issues/9

    It's important to keep information on the current connection before dispatching the disconnected event, so that event receivers can make informed decisions about the disconnection, such as saving the current list of channels.

    The original problem encountered by @sztanpet is how to reconnect the bot from the event handler. As replied by @fluffle, don't reconnect at this point, instead send the information back to the main loop with a channel. For examples, see sp0rkle (https://github.com/fluffle/sp0rkle/blob/master/bot/serverset.go#L35) and goircbot (https://github.com/StalkR/goircbot/blob/master/bot/bot.go#L104).

  • data race in state tracking

    data race in state tracking

    Nick isn't safe for concurrent access https://github.com/fluffle/goirc/blob/master/state%2Fnick.go#L15

    An example of this issue was reported in https://github.com/StalkR/goircbot/issues/8 where there is a goroutine that checks bot Channels() (a read on Nick), meanwhile the state handling using addChannel (a write on Nick).

    I was thinking we could add a mutex in that struct, then protect access to the members (lock/defer unlock). Thoughts?

  • Soft protection against IRC command injection

    Soft protection against IRC command injection

    Hi,

    Command injection on IRC is when a string being sent to the IRC server (nick, privmsg, topic, etc.) contains a "\r" or "\n" followed by another command. This can happen on an IRC client if a user-controlled, not sanitized input is passed to the IRC library. Example: a bot reading URLs, getting page, parsing <title> and displaying it on IRC using Privmsg. A malicious user could forge a web page with <title>test\rNICK owned</title> to send Privmsg with "test" followed by the arbitrary IRC command "NICK owned" so the bot changes nick.

    It would be nice if the library protects against IRC command injection by default. Two solutions: either fail hard (do not send anything) or fail soft (by stripping bad characters \r or \n). I prefer soft in this case and added it in every command except Raw() where we don't want to restrict anything.

    Going further, we could add more checks for instance require channel/nicks to have no space, but not more otherwise we fall into IRC servers implementation differences and it's not the place. This change doesn't do that but let me know if you would be interested.

    Cheers, StalkR

  • Support IRCv3 capability negotiation during registration.

    Support IRCv3 capability negotiation during registration.

    http://ircv3.net/specs/core/capability-negotiation-3.1.html http://ircv3.net/specs/core/capability-negotiation-3.2.html

    TL;DR: We need to send a CAP LS before USER and NICK. Not too sure of a final design yet, but one easy way to do it could be to add a []string of capabilities to try and request if the server supports them to the Config struct.

    CAP tls and STARTTLS would require different handling, I'll file a different issue for that.

  • Add logic for verifying PONGS from server

    Add logic for verifying PONGS from server

    This will (optionally) check that the PONGs that we get back contain the message that we sent.

    Most (all?) IRCd servers will return the text of your PING back to you in the PONG. This helps in establishing that you have two-way communication with the IRC server.

    Example of successful pings:

    I0530 17:50:58.204800   13341 connection.go:458] Current outstanding pings: 0/3
    I0530 17:50:58.205028   13341 connection.go:537] -> PING :1496166658204835562
    I0530 17:50:58.350480   13341 connection.go:438] <- :rajaniemi.freenode.net PONG rajaniemi.freenode.net :1496166658204835562
    I0530 17:50:58.350625   13341 connection.go:477] Processing Pong: 1496166658204835562
    I0530 17:52:58.204800   13341 connection.go:458] Current outstanding pings: 0/3
    I0530 17:52:58.205012   13341 connection.go:537] -> PING :1496166778204837692
    I0530 17:52:58.350588   13341 connection.go:438] <- :rajaniemi.freenode.net PONG rajaniemi.freenode.net :1496166778204837692
    I0530 17:52:58.350736   13341 connection.go:477] Processing Pong: 1496166778204837692
    I0530 17:54:58.204839   13341 connection.go:458] Current outstanding pings: 0/3
    I0530 17:54:58.205076   13341 connection.go:537] -> PING :1496166898204887198
    I0530 17:54:58.350742   13341 connection.go:438] <- :rajaniemi.freenode.net PONG rajaniemi.freenode.net :1496166898204887198
    I0530 17:54:58.350833   13341 connection.go:477] Processing Pong: 1496166898204887198
    

    Example of failed pings:

    I0530 18:32:58.204795   13341 connection.go:458] Current outstanding pings: 0/3
    I0530 18:32:58.204939   13341 connection.go:537] -> PING :1496169178204836420
    I0530 18:34:58.204774   13341 connection.go:458] Current outstanding pings: 1/3
    I0530 18:34:58.204893   13341 connection.go:537] -> PING :1496169298204803849
    I0530 18:36:58.204881   13341 connection.go:458] Current outstanding pings: 2/3
    I0530 18:36:58.205016   13341 connection.go:537] -> PING :1496169418204910266
    I0530 18:38:58.204813   13341 connection.go:458] Current outstanding pings: 3/3
    I0530 18:38:58.204855   13341 connection.go:571] irc.Close(): Disconnected from server.
    E0530 18:38:58.205027   13341 connection.go:430] irc.recv(): read tcp [2600:3c00::f03c:91ff:fe6e:3a69]:56410->[2001:708:40:2001::f5ee:d0de]:6697: use of closed network connection
    

    This change isโ€‚Reviewable

  • TestPing is unstable...

    TestPing is unstable...

    ...for the reason you expected yourself according to your comments, the 49-51ms window to check for your ping is too tight.

    go test github.com/fluffle/...
    ok      github.com/fluffle/goevent/event        0.578s
    ?       github.com/fluffle/goirc        [no test files]
    --- FAIL: TestPing (0.21s)
            connection_test.go:426: Line not output after another 2ms.
            connection_test.go:440: Line output after ping stopped.
    FAIL
    FAIL    github.com/fluffle/goirc/client 0.313s
    ?       github.com/fluffle/goirc/logging        [no test files]
    ?       github.com/fluffle/goirc/logging/glog   [no test files]
    ok      github.com/fluffle/goirc/state  0.025s
    

    So I'm creating the issue as detailed in the comments (connection_test.go l.422)

  • Invalid/expired certificate

    Invalid/expired certificate

    When trying to connect to an IRC server with SSL, I get the following error:

    Connection error x509: certificate has expired or is not yet valid: current time 2022-02-02T23:01:43-05:00 is after 2022-02-01T07:44:35Z

    I suspect the issue might be with the library? I compiled my program, which uses goirc, on two, different operating systems, and I still get the error.

    Any guidance would be appreciated.

  • NewNick handler needs a max length check

    NewNick handler needs a max length check

    If you use the NewNick handler and return a nick with a length that's longer than 16 chars, the whole lib breaks, in particular the NAMES/353 responses no longer work and you get ghosts in your code.

    Ask me how I know...

    There should be a doc patch to mention this, and probably some sort of error propagation in here.

    It's possible that 16 is a server specific limit-- I just found this empirically when using Freenode.

    HTH's someone else.

  • Handler timeout

    Handler timeout

    This will (optionally) set an upper limit on fgHandlers and intHandlers so that if something breaks in one of them the IRC client won't hang indefinitely waiting for the DISCONNECTED event.


    This change isโ€‚Reviewable

  • Add IRCv3 tag parsing and CAP command

    Add IRCv3 tag parsing and CAP command

    I needed this for a Twitch bot I'm working on. This adds the CAP command (needed to enable tags), as well as the tag parsing into a map[string]string.

    If a line doesn't have the tag section, then the map is nil as to not have to change other struct initializers in other parts of the code. I didn't add any functions to access the map, as I'm assuming any user would do this themselves, though it would be nice to have some GetTag() function that can check if the map is nil, but anything that uses the library could probably implement that themselves.

    The Cap function takes a subcommand, and an optional list of capabilities. I haven't added any extra constants for things like REQ or LS or similar (should they be added?).

    I also added a few tests for the tagging, and it works in my own tests (connecting to a twitch channel and detecting if someone's a sub or not, etc).

    Let me know if you have any suggestions. This is all I personally need, anyway.

    http://ircv3.net/specs/core/capability-negotiation-3.1.html http://ircv3.net/specs/core/message-tags-3.2.html

  • Fix TestSTRaces panics

    Fix TestSTRaces panics

    since GetNick returns nil, calling methods on it will generate runtime panics (same with GetChannel vs. NewChannel). This might defeat the purpose of the test, in which case it should be changed in a more fundamental way.

  • disconnect event delay too much

    disconnect event delay too much

    when i reconnect my wifi, after about 260 seconds, another irc client see goirc deamon timeout. but the goirc daemon emit disconnect event after about 15 minutes. want to known is this normal?

  • Allow rate limiting code to be changed.

    Allow rate limiting code to be changed.

    The rate limit code is hard-coded for hybrid's algorithm currently. Other servers probably use different algorithms. Twitch's "IRC" server won't let you send more than 20 messages in 30 seconds, for example, amusingly this is less conservative than hybrid!

  • Support STARTTLS (and CAP tls requesting).

    Support STARTTLS (and CAP tls requesting).

    Many servers support upgrading a plaintext connection to be encrypted by using the STARTTLS command before registration. This client ought to support that.

  • Allow registering a global handler

    Allow registering a global handler

    I'm working on a bot plugin framework and it would be useful to register a handler which gets all events so I can dispatch the events with a different handler type (so my own Bot object is available).

ircflu is an IRC bot written in Go

ircflu ircflu is an IRC bot written in Go with a flexible message- & command-handler. Among its advanced features are a cat-server which allows you to

Apr 26, 2021
Golang Framework for writing Slack bots

hanu - Go for Slack Bots! The Go framework hanu is your best friend to create Slack bots! hanu uses allot for easy command and request parsing (e.g. w

Oct 24, 2022
An XMPP client with OTR support

xmpp-client setup go get github.com/agl/xmpp-client (If you don't have Go already installed then see below.) xmpp-client use xmpp-client is a simple

Sep 3, 2022
Simple TCP-based chat server

hub-server Simple TCP-based chat server. Client can be found: https://github.com/alankritjoshi/hub-client Setup go run server.go 1234 How it works Use

Oct 25, 2021
๐Ÿ›… Backup your Kubernetes Stateful Applications

Stash Stash by AppsCode is a cloud-native data backup and recovery solution for Kubernetes workloads. If you are running production workloads in Kuber

Jan 7, 2023
K8s local storage sync for stateful set's using microk8s-hostpath storage classe

Local Storage Sync for microk8s-hostpath The goal is to be able to sync stateful sets between the different nodes of a cluster to allow the data to be

Nov 1, 2022
Govent is an event bus framework for DDD event source implement

Govent is an event bus framework for DDD event source implement. Govent can also solve the package circular dependency problem.

Jan 28, 2022
KEDA is a Kubernetes-based Event Driven Autoscaling component. It provides event driven scale for any container running in Kubernetes
 KEDA is a Kubernetes-based Event Driven Autoscaling component. It provides event driven scale for any container running in Kubernetes

Kubernetes-based Event Driven Autoscaling KEDA allows for fine-grained autoscaling (including to/from zero) for event driven Kubernetes workloads. KED

Jan 7, 2023
go irc client for twitch.tv

go-twitch-irc This is an irc client for connecting to twitch. It handles the annoying stuff like irc tag parsing. I highly recommend reading the docum

Dec 27, 2022
Build event-driven and event streaming applications with ease

Commander ?? Commander is Go library for writing event-driven applications. Enabling event sourcing, RPC over messages, SAGA's, bidirectional streamin

Dec 19, 2022
gevent imply go-event which tries to make event handling easier.

gevent imply go-event which tries to make event handling easier. What does gevent want to do Async execute jobs safely without too many go routines. S

Nov 10, 2021
Go-serverless-eth-event-listener - Go serverless, ethereum contract event listener with a sample contract

go-serverless-eth-event-listener This repository is for showing how to listen sm

May 19, 2022
Event-planning-go - GRAPHQL Project for Event Planning

About The Project GRAPHQL Project for Event Planning Building the project with l

Mar 13, 2022
IRC, Slack, Telegram and RocketChat bot written in go
IRC, Slack, Telegram and RocketChat bot written in go

go-bot IRC, Slack & Telegram bot written in Go using go-ircevent for IRC connectivity, nlopes/slack for Slack and Syfaro/telegram-bot-api for Telegram

Dec 20, 2022
The Tenyks IRC bot.

Tenyks is a computer program designed to relay messages between connections to IRC networks and custom built services written in any number of languages.

Sep 26, 2022
IRC bot written in Go

GoRobot Yet Another IRC robot. Features: Multiple servers, multiple channels, conversations, flood control Administration via a specific set of IRC ch

Sep 26, 2019
ircflu is an IRC bot written in Go

ircflu ircflu is an IRC bot written in Go with a flexible message- & command-handler. Among its advanced features are a cat-server which allows you to

Apr 26, 2021
A modern IRC server (daemon/ircd) written in Go.
A modern IRC server (daemon/ircd) written in Go.

Oragono is a modern IRC server written in Go. Its core design principles are: Being simple to set up and use Combining the features of an ircd, a serv

Dec 31, 2022
A reverse proxy implementing IRC-over-WebSockets

webircproxy webircproxy is a reverse proxy that accepts IRCv3-over-WebSocket connections, then forwards them to a conventional ircd that speaks the no

Dec 22, 2021
This is my first IRC bot for launch ddos attack, Write on Go language.
This is my first IRC bot for launch ddos attack, Write on Go language.

This is my first IRC bot for launch ddos attack, Write on Go language. For education purpose only. Please test it on your lab, And i create this for join university in the future not for attack anyone server with out any permission!!!

Sep 23, 2022