From 14023d09d018ab5ef80b27c4609107eeab1b7589 Mon Sep 17 00:00:00 2001 From: A_D Date: Sat, 17 Nov 2018 20:39:54 +0200 Subject: [PATCH] added IRC bot frontend --- src/bot.go | 79 ++++++++++++++++++++++++++++++++++++++++++ src/botLineHandlers.go | 38 ++++++++++++++++++++ src/config.go | 12 +++++-- src/ircUtil.go | 7 ++++ src/main.go | 13 ++++++- src/server.go | 44 +++++++++++++++++++++++ 6 files changed, 189 insertions(+), 4 deletions(-) create mode 100644 src/bot.go create mode 100644 src/botLineHandlers.go create mode 100644 src/ircUtil.go create mode 100644 src/server.go diff --git a/src/bot.go b/src/bot.go new file mode 100644 index 0000000..6061cb3 --- /dev/null +++ b/src/bot.go @@ -0,0 +1,79 @@ +package main + +import ( + "bufio" + "github.com/goshuirc/irc-go/ircmsg" + "log" + "os" +) + +type Bot struct { + Nick string + Ident string + Realname string + Server Server + ChansToJoin []string + NSPasswd string + NSNick string + Logger log.Logger +} + +type BotConfig struct { + Nick string + Ident string + Realname string + ChansToJoin []string + NSNick string + NSPasswd string +} + +func newBot(config BotConfig, host, port, connectionName string, ssl bool) *Bot { + logger := *log.New(os.Stdout, "", log.LstdFlags) + + return &Bot{ + Nick: config.Nick, + Ident: config.Ident, + Realname: config.Realname, + NSPasswd: config.NSPasswd, + NSNick: config.NSNick, + ChansToJoin: config.ChansToJoin, + Server: *NewServer(host, port, connectionName, ssl, logger), + Logger: logger, + } +} + +func (b *Bot) run() { + err := b.Server.Connect() + if err != nil { + b.Logger.Fatal(err) + } + + b.sendRaw(MakeMessage("NICK", b.Nick)) + b.sendRaw(MakeMessage("USER", b.Ident, "0", "0", b.Realname)) + b.readLoop() +} + +func (b *Bot) sendRaw(message ircmsg.IrcMessage) { + line, err := message.LineBytes() + if err != nil { + b.Logger.Printf("could not convert IrcMessage to string: %v", err) + return + } + b.Logger.Printf(">> %s", line) + b.Server.Conn.Write(line) +} + +func (b *Bot) readLoop() { + scanner := bufio.NewScanner(b.Server.Conn) + for scanner.Scan() { + b.HandleLine(scanner.Text()) + } +} + +func (b *Bot) joinChannel(channelName string) { + b.sendRaw(MakeMessage("JOIN", channelName)) +} + +func (b *Bot) sendPrivMessage(target, message string) { + b.sendRaw(MakeMessage("PRIVMSG", message)) +} diff --git a/src/botLineHandlers.go b/src/botLineHandlers.go new file mode 100644 index 0000000..1193787 --- /dev/null +++ b/src/botLineHandlers.go @@ -0,0 +1,38 @@ +package main + +import ( + "fmt" + "github.com/goshuirc/irc-go/ircmsg" +) + +func createPong(ping ircmsg.IrcMessage) ircmsg.IrcMessage { + return ircmsg.MakeMessage(nil, "", "PONG", ping.Params[0]) +} + +func (b *Bot) HandleLine(lineIn string) { + line, err := ircmsg.ParseLine(lineIn) + if err != nil { + b.Logger.Printf("could not parse IRC line: %v", err) + return + } + + b.Logger.Printf("<< %s", line.SourceLine) + + switch line.Command { + case "PING": + b.sendRaw(createPong(line)) + + case "001": + b.OnWelcome() + } +} + +func (b *Bot) OnWelcome() { + if b.NSNick != "" && b.NSPasswd != "" { + b.sendPrivMessage("NickServ", fmt.Sprintf("IDENTIFY %s %s", b.NSNick, b.NSPasswd)) + } + + for _, channel := range b.ChansToJoin { + b.joinChannel(channel) + } +} diff --git a/src/config.go b/src/config.go index 176ac6a..771b4ba 100644 --- a/src/config.go +++ b/src/config.go @@ -7,9 +7,15 @@ import ( ) type Config struct { - Secret string - BindHost string `json:"bind_host"` - BindPort string `json:"bind_port"` + Secret string `json:"secret"` + BindHost string `json:"bind_host"` + BindPort string `json:"bind_port"` + Nick string `json:"nick"` + Ident string `json:"ident"` + Realname string `json:"realname"` + NsNick string `json:"ns_nick"` + NsPasswd string `json:"ns_passwd"` + ChansToJoin []string `json:"chans_to_join"` } func getConfig() Config { diff --git a/src/ircUtil.go b/src/ircUtil.go new file mode 100644 index 0000000..e1bfa7d --- /dev/null +++ b/src/ircUtil.go @@ -0,0 +1,7 @@ +package main + +import "github.com/goshuirc/irc-go/ircmsg" + +func MakeMessage(command string, params... string) ircmsg.IrcMessage{ + return ircmsg.MakeMessage(nil, "", command, params...) +} diff --git a/src/main.go b/src/main.go index 5fe279a..89374ce 100644 --- a/src/main.go +++ b/src/main.go @@ -1,15 +1,26 @@ package main import "fmt" + const configPrint = ` CONFIG: Secret: %q BindHost: %q BindPort: %q ` - func main() { + +func main() { config := getConfig() fmt.Printf(configPrint, config.Secret, config.BindHost, config.BindPort) + bc := BotConfig{ + Nick: config.Nick, + Ident: config.Ident, + Realname: config.Realname, + ChansToJoin: config.ChansToJoin, + } + bot := newBot(bc, "chimera.snoonet.org", "6697", "snoonet", true) + + go bot.run() ListenForWebHook(config) } diff --git a/src/server.go b/src/server.go new file mode 100644 index 0000000..506cfe0 --- /dev/null +++ b/src/server.go @@ -0,0 +1,44 @@ +package main + +import ( + "crypto/tls" + "fmt" + "log" + "net" +) + +type Server struct { + Host string + Port string + Name string + SSL bool + Conn net.Conn + Logger log.Logger +} + +func NewServer(host, port, name string, ssl bool, logger log.Logger) *Server { + return &Server{ + host, + port, + name, + ssl, + nil, + logger, + } +} + +func (s *Server) Connect() error { + var conn net.Conn + var err error + + if s.SSL { + conn, err = tls.Dial("tcp", fmt.Sprintf("%s:%s", s.Host, s.Port), nil) + } else { + conn, err = net.Dial("tcp", fmt.Sprintf("%s:%s", s.Host, s.Port)) + } + if err != nil { + return err + } + s.Conn = conn + return nil +}