From fbe0411756e5a9b9d6dccb6b8472500924899b2e Mon Sep 17 00:00:00 2001 From: Runxi Yu <me@runxiyu.org> Date: Sat, 22 Mar 2025 10:38:18 +0800 Subject: [PATCH] IRC sending queues --- config.go | 10 +++++++--- forge.scfg | 10 ++++++++++ irc.go | 111 +++++++++++++++++++++++++++++++++++++++++++++-------- diff --git a/config.go b/config.go index 9a5647f8d2328dd94510d598fad388f5fa74f990..5382bbed67ac077b1bbf7d3a8cf009541642a38d 100644 --- a/config.go +++ b/config.go @@ -36,9 +36,13 @@ Key string `scfg:"key"` Root string `scfg:"root"` } `scfg:"ssh"` IRC struct { - Net string `scfg:"net"` - Addr string `scfg:"addr"` - TLS bool `scfg:"tls"` + 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"` } `scfg:"irc"` General struct { Title string `scfg:"title"` diff --git a/forge.scfg b/forge.scfg index cf77a4b9cbf457a3b10025d58ad00657b621d711..42a4b57264e44499c55e378946db7eacc40098f0 100644 --- a/forge.scfg +++ b/forge.scfg @@ -15,6 +15,16 @@ # What is the canonical URL of the web root? root https://forge.example.org } +irc { + tls true + net tcp + addr irc.runxiyu.org:6697 + sendq 6000 + nick forge-test + user forge + gecos "Lindenii Forge Test" +} + git { repo_dir /var/lib/lindenii/forge/repos } diff --git a/irc.go b/irc.go index fc9e0af39e22cd41875d2e25b4c321cee53d3223..afc9f965b6d99a0641ce6a209f836b49b0c3e159 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 @@ } else { 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") + 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: + } + } + }() + for { - msg, err := conn.ReadMessage() - if err != nil { - return (err) + 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 + } } - 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: - } + } +} + +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()) } } -- 2.48.1