diff options
author | Runxi Yu <me@runxiyu.org> | 2025-08-12 11:01:07 +0800 |
---|---|---|
committer | Runxi Yu <me@runxiyu.org> | 2025-09-13 19:08:22 +0800 |
commit | 5717faed659a9eeb86c528ab56822c42eca1ad3f (patch) | |
tree | 92e6662628a51c03c52300d2fd98173716a82882 /forged/internal/ipc/irc | |
parent | Remove forge-specific functions from misc (diff) | |
download | forge-5717faed659a9eeb86c528ab56822c42eca1ad3f.tar.gz forge-5717faed659a9eeb86c528ab56822c42eca1ad3f.tar.zst forge-5717faed659a9eeb86c528ab56822c42eca1ad3f.zip |
Refactor
Diffstat (limited to '')
-rw-r--r-- | forged/internal/ipc/irc/bot.go (renamed from forged/internal/irc/bot.go) | 38 | ||||
-rw-r--r-- | forged/internal/ipc/irc/config.go | 13 | ||||
-rw-r--r-- | forged/internal/ipc/irc/conn.go (renamed from forged/internal/irc/conn.go) | 15 | ||||
-rw-r--r-- | forged/internal/ipc/irc/doc.go | 2 | ||||
-rw-r--r-- | forged/internal/ipc/irc/errors.go (renamed from forged/internal/irc/errors.go) | 0 | ||||
-rw-r--r-- | forged/internal/ipc/irc/message.go (renamed from forged/internal/irc/message.go) | 20 | ||||
-rw-r--r-- | forged/internal/ipc/irc/source.go (renamed from forged/internal/irc/source.go) | 3 |
7 files changed, 55 insertions, 36 deletions
diff --git a/forged/internal/irc/bot.go b/forged/internal/ipc/irc/bot.go index 1c6d32f..07008ae 100644 --- a/forged/internal/irc/bot.go +++ b/forged/internal/ipc/irc/bot.go @@ -1,31 +1,21 @@ // SPDX-License-Identifier: AGPL-3.0-only // SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org> -// Package irc provides basic IRC bot functionality. package irc import ( + "context" "crypto/tls" + "fmt" "log/slog" "net" - "go.lindenii.runxiyu.org/forge/forged/internal/misc" + "go.lindenii.runxiyu.org/forge/forged/internal/common/misc" ) -// Config contains IRC connection and identity settings for the bot. -// This should usually be a part of the primary config struct. -type Config struct { - Net string `scfg:"net"` - Addr string `scfg:"addr"` - TLS bool `scfg:"tls"` - SendQ uint `scfg:"sendq"` - Nick string `scfg:"nick"` - User string `scfg:"user"` - Gecos string `scfg:"gecos"` -} - // Bot represents an IRC bot client that handles events and allows for sending messages. type Bot struct { + // TODO: Use each config field instead of embedding Config here. config *Config ircSendBuffered chan string ircSendDirectChan chan misc.ErrorBack[string] @@ -35,24 +25,28 @@ type Bot struct { func NewBot(c *Config) (b *Bot) { b = &Bot{ config: c, - } + } //exhaustruct:ignore return } // Connect establishes a new IRC session and starts handling incoming and outgoing messages. // This method blocks until an error occurs or the connection is closed. -func (b *Bot) Connect() error { +func (b *Bot) Connect(ctx context.Context) error { var err error var underlyingConn net.Conn if b.config.TLS { - underlyingConn, err = tls.Dial(b.config.Net, b.config.Addr, nil) + dialer := tls.Dialer{} //exhaustruct:ignore + underlyingConn, err = dialer.DialContext(ctx, b.config.Net, b.config.Addr) } else { - underlyingConn, err = net.Dial(b.config.Net, b.config.Addr) + dialer := net.Dialer{} //exhaustruct:ignore + underlyingConn, err = dialer.DialContext(ctx, b.config.Net, b.config.Addr) } if err != nil { - return err + return fmt.Errorf("dialing irc: %w", err) } - defer underlyingConn.Close() + defer func() { + _ = underlyingConn.Close() + }() conn := NewConn(underlyingConn) @@ -165,12 +159,12 @@ func (b *Bot) Send(line string) { // ConnectLoop continuously attempts to maintain an IRC session. // If the connection drops, it automatically retries with no delay. -func (b *Bot) ConnectLoop() { +func (b *Bot) ConnectLoop(ctx context.Context) { b.ircSendBuffered = make(chan string, b.config.SendQ) b.ircSendDirectChan = make(chan misc.ErrorBack[string]) for { - err := b.Connect() + err := b.Connect(ctx) slog.Error("irc session error", "error", err) } } diff --git a/forged/internal/ipc/irc/config.go b/forged/internal/ipc/irc/config.go new file mode 100644 index 0000000..b1b5703 --- /dev/null +++ b/forged/internal/ipc/irc/config.go @@ -0,0 +1,13 @@ +package irc + +// Config contains IRC connection and identity settings for the bot. +// This should usually be a part of the primary config struct. +type Config struct { + Net string `scfg:"net"` + Addr string `scfg:"addr"` + TLS bool `scfg:"tls"` + SendQ uint `scfg:"sendq"` + Nick string `scfg:"nick"` + User string `scfg:"user"` + Gecos string `scfg:"gecos"` +} diff --git a/forged/internal/irc/conn.go b/forged/internal/ipc/irc/conn.go index b975b72..b9b208c 100644 --- a/forged/internal/irc/conn.go +++ b/forged/internal/ipc/irc/conn.go @@ -2,10 +2,11 @@ package irc import ( "bufio" + "fmt" "net" "slices" - "go.lindenii.runxiyu.org/forge/forged/internal/misc" + "go.lindenii.runxiyu.org/forge/forged/internal/common/misc" ) type Conn struct { @@ -41,9 +42,17 @@ func (c *Conn) ReadMessage() (msg Message, line string, err error) { } func (c *Conn) Write(p []byte) (n int, err error) { - return c.netConn.Write(p) + n, err = c.netConn.Write(p) + if err != nil { + err = fmt.Errorf("write to connection: %w", err) + } + return n, err } func (c *Conn) WriteString(s string) (n int, err error) { - return c.netConn.Write(misc.StringToBytes(s)) + n, err = c.netConn.Write(misc.StringToBytes(s)) + if err != nil { + err = fmt.Errorf("write to connection: %w", err) + } + return n, err } diff --git a/forged/internal/ipc/irc/doc.go b/forged/internal/ipc/irc/doc.go new file mode 100644 index 0000000..dcfca82 --- /dev/null +++ b/forged/internal/ipc/irc/doc.go @@ -0,0 +1,2 @@ +// Package irc provides basic IRC bot functionality. +package irc diff --git a/forged/internal/irc/errors.go b/forged/internal/ipc/irc/errors.go index 3506c70..3506c70 100644 --- a/forged/internal/irc/errors.go +++ b/forged/internal/ipc/irc/errors.go diff --git a/forged/internal/irc/message.go b/forged/internal/ipc/irc/message.go index 84b6867..3387bec 100644 --- a/forged/internal/irc/message.go +++ b/forged/internal/ipc/irc/message.go @@ -7,7 +7,7 @@ package irc import ( "bytes" - "go.lindenii.runxiyu.org/forge/forged/internal/misc" + "go.lindenii.runxiyu.org/forge/forged/internal/common/misc" ) type Message struct { @@ -24,18 +24,18 @@ func Parse(raw []byte) (msg Message, err error) { if bytes.HasPrefix(sp[0], []byte{'@'}) { // TODO: Check size manually if len(sp[0]) < 2 { err = ErrMalformedMsg - return + return msg, err } sp[0] = sp[0][1:] msg.Tags, err = tagsToMap(sp[0]) if err != nil { - return + return msg, err } if len(sp) < 2 { err = ErrMalformedMsg - return + return msg, err } sp = sp[1:] } else { @@ -45,7 +45,7 @@ func Parse(raw []byte) (msg Message, err error) { if bytes.HasPrefix(sp[0], []byte{':'}) { // TODO: Check size manually if len(sp[0]) < 2 { err = ErrMalformedMsg - return + return msg, err } sp[0] = sp[0][1:] @@ -53,14 +53,14 @@ func Parse(raw []byte) (msg Message, err error) { if len(sp) < 2 { err = ErrMalformedMsg - return + return msg, err } sp = sp[1:] } msg.Command = misc.BytesToString(sp[0]) if len(sp) < 2 { - return + return msg, err } sp = sp[1:] @@ -81,7 +81,7 @@ func Parse(raw []byte) (msg Message, err error) { msg.Args = append(msg.Args, misc.BytesToString(sp[i])) } - return + return msg, err } var ircv3TagEscapes = map[byte]byte{ //nolint:gochecknoglobals @@ -97,7 +97,7 @@ func tagsToMap(raw []byte) (tags map[string]string, err error) { key, value, found := bytes.Cut(rawTag, []byte{'='}) if !found { err = ErrInvalidIRCv3Tag - return + return tags, err } if len(value) == 0 { tags[misc.BytesToString(key)] = "" @@ -122,5 +122,5 @@ func tagsToMap(raw []byte) (tags map[string]string, err error) { } } } - return + return tags, err } diff --git a/forged/internal/irc/source.go b/forged/internal/ipc/irc/source.go index d955f45..938751f 100644 --- a/forged/internal/irc/source.go +++ b/forged/internal/ipc/irc/source.go @@ -6,13 +6,14 @@ package irc import ( "bytes" - "go.lindenii.runxiyu.org/forge/forged/internal/misc" + "go.lindenii.runxiyu.org/forge/forged/internal/common/misc" ) type Source interface { AsSourceString() string } +//nolint:ireturn func parseSource(s []byte) Source { nick, userhost, found := bytes.Cut(s, []byte{'!'}) if !found { |