Documentation
¶
Overview ¶
Package ircbridge wraps the external irc.Connection with multi-subscriber fan-out for the bouncer's per-network event stream.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CleanInput ¶
CleanInput preserves the IRC library's wire-safety normalization used by its convenience send methods. IRC values placed on one wire line must not contain embedded line terminators: LF becomes a visible separator and CR is removed.
func SendRaw ¶
func SendRaw(c *irc.Connection, format string, args ...any)
SendRaw sends an IRC line with a unique labeled-response label when the server negotiated both capabilities required by the specification. The label is generated inside Relay rather than exposed to the browser protocol: Relay has one upstream IRC connection per network and already broadcasts resulting IRC events to all attached sessions.
Commands sent before capability negotiation, or to servers without labeled-response support, retain the existing untagged wire format.
func SendRawTags ¶
SendRawTags sends an IRC line with caller-supplied tags and adds a unique labeled-response label when the negotiated capabilities allow it. The caller's map is never mutated, so shared message-tag maps remain safe to reuse across chunked sends and local self-echo events.
Types ¶
type Bridge ¶
type Bridge struct {
Conn *irc.Connection
// contains filtered or unexported fields
}
Bridge wraps a single *irc.Connection, becoming the sole holder of each of its per-type callbacks and re-publishing every event to any number of subscribers. irc.Connection supports exactly one callback per event type; a bouncer needs "one IRC event -> N attached browser sessions", which is what Bridge adds on top without changing the underlying library's contract (see the migration plan's rationale for keeping this fan-out app-side rather than pushing pub/sub upstream into the library itself).
A Bridge intentionally runs no goroutine of its own beyond the one the caller starts via Run: irc.Connection.Run's read loop already invokes every callback synchronously, one message at a time, so simply becoming that loop's sole callback holder and dispatching to subscribers inline preserves the same single-threaded ordering guarantee Node's event loop gives for free - no extra channel/goroutine layer is needed to get it.
func NewBridge ¶
func NewBridge(conn *irc.Connection) *Bridge
NewBridge wraps conn, installing itself as the sole holder of every callback conn exposes. conn must not have any of its callbacks set already - Bridge overwrites all of them.
func (*Bridge) Connected ¶
Connected reports whether Run's read loop is still active. False before Run is ever called would be indistinguishable from false after it ends; callers only call this once they know Run has started (e.g. after launching `go bridge.Run()`).
func (*Bridge) Publish ¶
Publish fans out a synthetic Event to every subscriber, exactly as if the underlying connection had produced it. This is the Go analogue of Node's `irc.emit("privmsg", {...})` self-echo simulation (msg.ts, notice.ts, action.ts all fabricate a local echo when the server hasn't ACKed echo-message) - routing the fabricated event through the same dispatch path real events take, rather than duplicating irchandlers' message- building logic in internal/incommands.
func (*Bridge) Run ¶
func (b *Bridge) Run()
Run blocks, reading from the underlying connection and dispatching events to subscribers, until the connection closes or errors. Callers should invoke this in its own goroutine (one per Bridge, per the package's ordering guarantee) and use Connected to check liveness afterward.
func (*Bridge) Subscribe ¶
Subscribe registers l to receive every subsequent Event and returns an id for Unsubscribe. Safe to call concurrently with Run.
func (*Bridge) SubscriberCount ¶
SubscriberCount reports how many listeners are currently registered.
func (*Bridge) Unsubscribe ¶
Unsubscribe removes a listener previously returned by Subscribe. A no-op if id is unknown (e.g. already unsubscribed).
type Event ¶
type Event struct {
Type EventType
Privmsg *irc.PrivmsgEvent
Message *irc.MessageEvent
Direct *irc.DirectEvent
Join *irc.JoinEvent
Part *irc.PartEvent
Quit *irc.QuitEvent
Nick *irc.NickEvent
Account *irc.AccountEvent
Kick *irc.KickEvent
Notice *irc.NoticeEvent
Numeric *irc.NumericEvent
Topic *irc.TopicEvent
Mode *irc.ModeEvent
Chghost *irc.ChghostEvent
SetName *irc.SetNameEvent
TagMsg *irc.TagMsgEvent
CTCP *irc.CTCPEvent
Whois *irc.WhoisReply
Error *irc.ErrorEvent
}
Event is the single fan-out envelope for every callback the irc library exposes on *irc.Connection. Exactly one field matching Type is non-nil; callers switch on Type rather than nil-checking every field.
type Listener ¶
type Listener func(Event)
Listener receives every Event a Bridge dispatches, in the order the underlying connection produced them. It is invoked synchronously from the Bridge's single dispatching goroutine (see Run) and must not block for long - a slow listener delays delivery to every other listener on the same bridge, and (since irc.Connection's Run loop is itself synchronous) delays the bridge from reading its next line off the wire.