diff --git a/irc.go b/irc.go new file mode 100644 index 0000000..15054bb --- /dev/null +++ b/irc.go @@ -0,0 +1,136 @@ +// vi:ts=4:sts=4:sw=4:noet:tw=72 +// +// flokatirc +// +// Copyright (c) 2015,2016 Andreas Neue + +package main + +import ( + "flag" + "fmt" + "strings" + "time" + + "code.dnix.de/an/xlog" + + "github.com/nickvanw/ircx" + "github.com/sorcix/irc" + "github.com/sorcix/irc/ctcp" + + "flokatirc/modules" +) + +var ( + nsname = flag.String("nsname", "NickServ", "NickServ name") + nspass = flag.String("nspass", "", "NickServ password") + params = flag.String("params", "", "Module params") + autocmd = flag.String("autocmd", "", "Autosend IRC command") +) + +func Irc() { + //bot := ircx.Classic(*server, *name) + cfg := ircx.Config{User: *name, MaxRetries: 1000} + bot := ircx.New(*server, *name, cfg) + if err := bot.Connect(); err != nil { + xlog.Fatal("Unable to dial IRC Server: %v", err) + } + + modules.ModParams["_nick"] = *name + + go func() { + for { + var targets string + line := strings.Split(<-sayCh, "\n") + if len(line) < 2 { + continue + } + if line[0] != "*" { + targets = line[0] + } else { + targets = *channels + } + for _, tar := range strings.Split(targets, ",") { + bot.Sender.Send(&irc.Message{ + Command: irc.PRIVMSG, + Params: []string{tar}, + Trailing: line[1], + }) + time.Sleep(1 * time.Second) + } + } + }() + + go Ping(bot) + if *autocmd != "" { + println(*autocmd) + bot.Sender.Send(&irc.Message{Command: *autocmd}) + } + RegisterHandlers(bot) + bot.HandleLoop() + xlog.Info("Exiting") +} + +func RegisterHandlers(bot *ircx.Bot) { + xlog.Info("Registering handlers") + bot.HandleFunc(irc.RPL_WELCOME, ConnectHandler) + bot.HandleFunc(irc.PING, PingHandler) + bot.HandleFunc(irc.PRIVMSG, PrivmsgHandler) +} + +func Ping(bot *ircx.Bot) { + for { + time.Sleep(1 * time.Minute) + bot.Sender.Send(&irc.Message{Command: irc.PING}) + } +} + +func ConnectHandler(s ircx.Sender, m *irc.Message) { + if *nspass != "" { + xlog.Info("Authenticating with NickServ: %v, %v", *name, *nspass) + s.Send(&irc.Message{ + Command: irc.PRIVMSG, + Params: []string{*nsname}, + Trailing: "IDENTIFY " + *name + " " + *nspass, + }) + } + xlog.Info("Joining channels: %v", *channels) + for _, ch := range strings.Split(*channels, ",") { + s.Send(&irc.Message{ + Command: irc.JOIN, + Params: []string{ch}, + }) + } + time.Sleep(2 * time.Second) + msg := ctcp.Action(fmt.Sprintf("running on %s", SoftwareInfo())) + sayCh <- fmt.Sprintf("%s\n%s", "*", msg) +} + +func PingHandler(s ircx.Sender, m *irc.Message) { + xlog.Info("PingPong") + s.Send(&irc.Message{ + Command: irc.PONG, + Params: m.Params, + Trailing: m.Trailing, + }) +} + +func PrivmsgHandler(s ircx.Sender, m *irc.Message) { + //TODO: implement message handler table + HandleMessage(m) + modules.HandleMessage(m) +} + +func HandleMessage(m *irc.Message) { + tok := strings.Split(m.Trailing, " ") + if len(tok) < 1 { + return + } + switch tok[0] { + case "!version": + msg := ctcp.Action(fmt.Sprintf("running on %s", SoftwareInfo())) + sayCh <- fmt.Sprintf("%s\n%s", "*", msg) + //sayCh <- fmt.Sprintf("%s\n%s", "*", SoftwareInfo()) + default: + } +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..e16c227 --- /dev/null +++ b/main.go @@ -0,0 +1,55 @@ +// vi:ts=4:sts=4:sw=4:noet:tw=72 +// +// flokatimx +// +// Copyright (c) 2015-2019 Andreas Neue + +package main + +import ( + "flag" + "flokati/modules" + "fmt" + "runtime" + "strings" + + "git.dnix.de/an/xlog" +) + +var ( + protocol = flag.String("protocol", "", "Protocol") + mods = flag.String("mods", "", "Modules to load") + name = flag.String("name", "flokati", "Bot name") + nick = flag.String("nick", "flokati", "Nickname") + server = flag.String("server", "https://matrix.org", "Host to connect to") + channels = flag.String("chan", "", "Channels") + password = flag.String("password", "", "Login password") + token = flag.String("token", "", "Login token") +) + +var ( + sayCh chan string +) + +func init() { + flag.Parse() +} + +func main() { + xlog.Info("%s started", SoftwareInfo()) + modules.Init(sayCh, *mods) + modules.BotNick = strings.ToLower(*nick) + switch *protocol { + case "irc": + Irc() + case "matrix": + Matrix() + default: + xlog.Error("Unsupported protocol: %s", *protocol) + } +} + +func SoftwareInfo() string { + return fmt.Sprintf("flokatimx %s-%s (%s) [%s]", + Version, Build, Builddate, runtime.Version()) +} diff --git a/matrix.go b/matrix.go new file mode 100644 index 0000000..d6da8e2 --- /dev/null +++ b/matrix.go @@ -0,0 +1,65 @@ +// vi:ts=4:sts=4:sw=4:noet:tw=72 +// +// flokatimx +// +// Copyright (c) 2019 Andreas Neue + +package main + +import ( + "flokati/modules" + "fmt" + "strings" + "time" + + "git.dnix.de/an/xlog" + + "github.com/matrix-org/gomatrix" +) + +func Matrix() { + cl, err := gomatrix.NewClient(*server, *name, *token) + fmt.Println(err) + + syncer := cl.Syncer.(*gomatrix.DefaultSyncer) + syncer.OnEventType("m.room.message", func(ev *gomatrix.Event) { + fmt.Println("Message: ", ev) + if msgtype, ok := ev.MessageType(); ok && msgtype == "m.text" { + if body, ok := ev.Body(); ok { + fmt.Println(ev.Sender, ev.RoomID, body) + modules.HandleMessage(&modules.Message{From: ev.Sender, Channel: ev.RoomID, Text: body}) + } + } + }) + + go func() { + for { + if err := cl.Sync(); err != nil { + fmt.Println("Sync() returned ", err) + } + time.Sleep(1 * time.Second) + } + }() + + xlog.Info("%s started", SoftwareInfo()) + sayCh <- fmt.Sprintf("%s\n%s", "*", SoftwareInfo()) + + for { + var targets string + line := strings.Split(<-sayCh, "\n") + if len(line) < 2 { + continue + } + if line[0] != "*" { + targets = line[0] + } else { + targets = *channels + } + xlog.Debug("Say: \"%s\" to [%s]", line[1], targets) + for _, tar := range strings.Split(targets, ",") { + cl.SendText(tar, line[1]) + time.Sleep(1 * time.Second) + } + } + time.Sleep(1 * time.Millisecond) +}