aboutsummaryrefslogtreecommitdiff
path: root/irc.go
diff options
context:
space:
mode:
authorRunxi Yu <me@runxiyu.org>2025-03-22 10:38:18 +0800
committerRunxi Yu <me@runxiyu.org>2025-03-22 10:38:18 +0800
commitfbe0411756e5a9b9d6dccb6b8472500924899b2e (patch)
treed12b99283357c2cc5c52167cd091ba1b9cd7be81 /irc.go
parentAdd rudimentary IRC logic (diff)
downloadforge-fbe0411756e5a9b9d6dccb6b8472500924899b2e.tar.gz
forge-fbe0411756e5a9b9d6dccb6b8472500924899b2e.tar.zst
forge-fbe0411756e5a9b9d6dccb6b8472500924899b2e.zip
IRC sending queues
Diffstat (limited to 'irc.go')
-rw-r--r--irc.go111
1 files changed, 94 insertions, 17 deletions
diff --git a/irc.go b/irc.go
index fc9e0af..afc9f96 100644
--- a/irc.go
+++ b/irc.go
@@ -4,9 +4,20 @@ import (
"crypto/tls"
"net"
+ "go.lindenii.runxiyu.org/lindenii-common/clog"
"go.lindenii.runxiyu.org/lindenii-irc"
)
+var (
+ ircSendBuffered chan string
+ ircSendDirectChan chan errorBack[string]
+)
+
+type errorBack[T any] struct {
+ content T
+ errorBack chan error
+}
+
func ircBotSession() error {
var err error
var underlyingConn net.Conn
@@ -16,31 +27,97 @@ func ircBotSession() error {
underlyingConn, err = net.Dial(config.IRC.Net, config.IRC.Addr)
}
if err != nil {
- return (err)
+ return err
}
+ defer underlyingConn.Close()
+
conn := irc.NewConn(underlyingConn)
- conn.WriteString("NICK forge\r\nUSER forge 0 * :Forge\r\n")
- for {
- msg, err := conn.ReadMessage()
- if err != nil {
- return (err)
+ conn.WriteString(
+ "NICK " + config.IRC.Nick + "\r\n" +
+ "USER " + config.IRC.User + " 0 * :" + config.IRC.Gecos + "\r\n",
+ )
+
+ readLoopError := make(chan error)
+ writeLoopAbort := make(chan struct{})
+ go func() {
+ for {
+ select {
+ case <-writeLoopAbort:
+ return
+ default:
+ }
+ msg, err := conn.ReadMessage()
+ if err != nil {
+ readLoopError <- err
+ return
+ }
+ switch msg.Command {
+ case "001":
+ _, err = conn.WriteString("JOIN #chat\r\n")
+ if err != nil {
+ readLoopError <- err
+ return
+ }
+ case "PING":
+ _, err = conn.WriteString("PONG :" + msg.Args[0] + "\r\n")
+ if err != nil {
+ readLoopError <- err
+ return
+ }
+ case "JOIN":
+ _, err = conn.WriteString("PRIVMSG #chat :test\r\n")
+ if err != nil {
+ readLoopError <- err
+ return
+ }
+ default:
+ }
}
- switch msg.Command {
- case "001":
- conn.WriteString("JOIN #chat\r\n")
- case "PING":
- conn.WriteString("PONG :")
- conn.WriteString(msg.Args[0])
- conn.WriteString("\r\n")
- case "JOIN":
- conn.WriteString("PRIVMSG #chat :test\r\n")
- default:
+ }()
+
+ for {
+ select {
+ case err = <-readLoopError:
+ return err
+ case s := <-ircSendBuffered:
+ _, err = conn.WriteString(s)
+ if err != nil {
+ select {
+ case ircSendBuffered <- s:
+ default:
+ clog.Error("unable to requeue IRC message: " + s)
+ }
+ writeLoopAbort <- struct{}{}
+ return err
+ }
+ case se := <-ircSendDirectChan:
+ _, err = conn.WriteString(se.content)
+ se.errorBack <- err
+ if err != nil {
+ writeLoopAbort <- struct{}{}
+ return err
+ }
}
}
}
+func ircSendDirect(s string) error {
+ ech := make(chan error, 1)
+
+ ircSendDirectChan <- errorBack[string]{
+ content: s,
+ errorBack: ech,
+ }
+
+ return <-ech
+}
+
func ircBotLoop() {
+ ircSendBuffered = make(chan string, config.IRC.SendQ)
+ ircSendDirectChan = make(chan errorBack[string])
+
for {
- _ = ircBotSession()
+ err := ircBotSession()
+ clog.Error("IRC error: " + err.Error())
}
}