From ec618653e6e9adf008403d963ed7ca07904b10bd Mon Sep 17 00:00:00 2001 From: dave Date: Tue, 25 May 2021 21:45:23 -0700 Subject: [PATCH] remote control mode --- cmd/swarm/main.go | 172 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 155 insertions(+), 17 deletions(-) diff --git a/cmd/swarm/main.go b/cmd/swarm/main.go index e729fc4..e0d6649 100644 --- a/cmd/swarm/main.go +++ b/cmd/swarm/main.go @@ -14,6 +14,7 @@ import ( "math/rand" "net/http" + gabs "github.com/Jeffail/gabs/v2" "golang.org/x/net/proxy" irc "gopkg.in/irc.v3" zmq "gopkg.in/zeromq/goczmq.v4" @@ -64,11 +65,6 @@ func NewBotConfigFromEnv() *BotConfig { log.Fatal("Set IRC_CHANNEL!") } - c.Victim = os.Getenv("IRC_VICTIM") - if c.Victim == "" { - log.Fatal("Set IRC_VICTIM!") - } - enable_op_mode := os.Getenv("IRC_OP_MODE") if enable_op_mode != "" { c.OpMode = true @@ -90,6 +86,7 @@ func NewBotConfigFromEnv() *BotConfig { panic(fmt.Errorf("invalid HEALTH_PORT: %d", c.HealthPort)) } + c.Victim = os.Getenv("IRC_VICTIM") c.LogIrc = os.Getenv("LOG_IRC") != "" c.Nick = genNick(c.SuffixLength, c.OpMode) @@ -236,10 +233,13 @@ func (b *Bot) runBackground() { defer sub.Destroy() channel := strings.ToLower(b.Config.Nick) + log.Printf("channel: %s", channel) sub.SetSubscribe(channel) if b.Config.OpMode { sub.SetSubscribe("_ops") + } else { + sub.SetSubscribe("_nops") } b.State.Subscriber = sub @@ -248,22 +248,162 @@ func (b *Bot) runBackground() { for { resp, err := sub.RecvMessage() if err != nil { - log.Fatal(err) + log.Printf("Sub recv failed: %s", err) + continue } msg := bytes.Join(resp, nil) parts := bytes.SplitN(msg, []byte{' '}, 2) - channel := string(parts[0]) - message := string(parts[1]) + // channel := string(parts[0]) + message := parts[1] - log.Printf("channel: '%s'", channel) - log.Printf("message: '%s'", message) - log.Printf("len : %d", len(message)) - log.Printf("") + // log.Printf("channel: '%s'", channel) + // log.Printf("message: '%s'", message) + // log.Printf("len : %d", len(message)) + + b.handleBackgroundMessage(message) + + // log.Printf("") } } +func roll(chance int) bool { + if chance <= 0 { + return false + } + return RNG.Intn(chance) == 0 +} + +func (b *Bot) handleBackgroundMessage(message []byte) { + json, err := gabs.ParseJSON(message) + if err != nil { + log.Printf("invalid message: %s", message) + return + } + + chance, ok := json.S("chance").Data().(float64) + if ok && !roll(int(chance)) { + log.Printf("chanced out") + return + } + + // todo replace this with smarter json struct nonsense + for key, child := range json.ChildrenMap() { + switch key { + case "greet_chance": + loadIntField(&b.Config.GreetChance, child) + log.Printf("setting GreetChance to: %d", b.Config.GreetChance) + case "victim": + loadStrField(&b.Config.Victim, child) + log.Printf("setting Victim to: %s", b.Config.Victim) + case "join": + if !b.Status.Connected { + continue + } + channel, ok := child.Data().(string) + if !ok || channel == "" { + continue + } + b.State.IRCClient.WriteMessage(&irc.Message{ + Command: "JOIN", + Params: []string{ + channel, + }, + }) + case "part": + if !b.Status.Connected { + continue + } + channel, ok := child.Data().(string) + if !ok || channel == "" { + continue + } + b.State.IRCClient.WriteMessage(&irc.Message{ + Command: "PART", + Params: []string{ + channel, + "", + }, + }) + case "say": + if !b.Status.Connected { + continue + } + sayMsg, ok := child.Data().(string) + if !ok || sayMsg == "" { + continue + } + sayTo, ok := json.S("to").Data().(string) + if !ok || sayTo == "" { + sayTo = b.Config.Channel + } + b.State.IRCClient.WriteMessage(&irc.Message{ + Command: "PRIVMSG", + Params: []string{ + sayTo, sayMsg, + }, + }) + case "op": + if !b.Status.Connected { + continue + } + opNick, ok := child.Data().(string) + if !ok || opNick == "" { + continue + } + b.State.IRCClient.WriteMessage(&irc.Message{ + Command: "MODE", + Params: []string{ + b.Config.Channel, + "+o", + opNick, + }, + }) + case "nick": + if !b.Status.Connected { + continue + } + b.DoNewNick() + case "name": + if !b.Status.Connected { + continue + } + b.DoNewNick() + case "die": + panic("by request") + case "chance": + case "to": + default: + log.Printf("unknown var field %s", key) + } + } +} + +func loadIntField(dest *int, ob *gabs.Container) { + value, ok := ob.Data().(float64) + if !ok { + log.Printf("not int: %v", ob) + return + } + *dest = int(value) +} + +func loadStrField(dest *string, ob *gabs.Container) { + value, ok := ob.Data().(string) + if !ok { + log.Printf("not str: %v", ob) + return + } + *dest = value +} + +func (b *Bot) DoNewNick() { + nick := genNick(b.Config.SuffixLength, b.Config.OpMode) + b.UpdateNick(nick) + b.State.IRCClient.Write("NICK " + nick) +} + func (b *Bot) runStatusHandler() { healthAddress := fmt.Sprintf("0.0.0.0:%d", b.Config.HealthPort) @@ -306,14 +446,12 @@ func (b *Bot) handleIRC(c *irc.Client, m *irc.Message) { Command: "PRIVMSG", Params: []string{ m.Params[0], - "I've sent " + strconv.FormatInt(int64(b.Status.Invites), 10) + " invites to " + b.Config.Victim + " :)", + "I've sent " + strconv.FormatInt(int64(b.Status.Invites), 10) + " invites. Current target: " + b.Config.Victim + " :)", }, }) } else if text[len(text)-1] == "name" { - nick := genNick(b.Config.SuffixLength, b.Config.OpMode) - b.UpdateNick(nick) - c.Write("NICK " + nick) - } else if text[len(text)-1] == "invite" { + b.DoNewNick() + } else if text[len(text)-1] == "invite" && b.Config.Victim != "" { c.Write("INVITE " + b.Config.Victim + " " + b.Config.Channel) b.Status.Invites++ } /* else if strings.Contains(m.Trailing(), "greetings") {