From 63da75ada09e3f75465ecc0a061c2cb8cd9f48c9 Mon Sep 17 00:00:00 2001 From: jolheiser Date: Thu, 20 Jan 2022 11:42:15 -0600 Subject: [PATCH] Discord implementation and client abstraction Signed-off-by: jolheiser --- client.go | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++--- main.go | 83 ++--------------------------------- 2 files changed, 127 insertions(+), 85 deletions(-) diff --git a/client.go b/client.go index 7815c89..9a4bbb0 100644 --- a/client.go +++ b/client.go @@ -1,30 +1,149 @@ package main import ( + "bufio" + "errors" "github.com/Tnze/go-mc/bot" + "github.com/Tnze/go-mc/bot/basic" "github.com/Tnze/go-mc/chat" + "github.com/Tnze/go-mc/data/packetid" + "github.com/Tnze/go-mc/net/packet" + "github.com/Tnze/go-mc/yggdrasil" "github.com/bwmarrin/discordgo" "github.com/google/uuid" "github.com/rs/zerolog/log" + "io" + "os" + "strings" + "time" ) type Client struct { - discord *discordgo.Session - channel string + discord *discordgo.Session + channelID string minecraft *bot.Client + serverIP string } -func (c *Client) Run() error { +func NewClient(email, password, serverIP, discordToken string) (*Client, error) { + c := &Client{ + serverIP: serverIP, + } + if err := c.setupMinecraft(email, password); err != nil { + return nil, err + } + if discordToken != "" { + if err := c.setupDiscord(discordToken); err != nil { + return nil, err + } + } + return c, nil +} +func (c *Client) Run() { + go c.onChatSend() + c.handleGame() +} + +func (c *Client) handleGame() { + for { + err := c.minecraft.JoinServer(c.serverIP) + if err != nil { + log.Err(err).Msg("") + <-time.After(time.Minute * 5) + return + } + log.Info().Msg("Login success") + + for { + err := c.minecraft.HandleGame() + if err != nil { + log.Err(err).Msg("") + if errors.Is(err, io.EOF) { + <-time.After(time.Minute * 5) + break + } + } + } + } +} + +func (c *Client) sendChat(msg string) { + if err := c.minecraft.Conn.WritePacket(packet.Marshal( + packetid.ServerboundChat, + packet.String(msg), + )); err != nil { + log.Err(err).Msg("") + } } func (c *Client) onChatMsg(msg chat.Message, _ byte, _ uuid.UUID) error { if c.discord != nil { - _, err := c.discord.ChannelMessageSend(c.channel, msg.Text) + _, err := c.discord.ChannelMessageSend(c.channelID, msg.ClearString()) return err } - log.Info().Msg(msg.String()) return nil } + +func (c *Client) setupDiscord(token string) error { + var err error + c.discord, err = discordgo.New("Bot " + token) + if err != nil { + return err + } + info, err := c.discord.Application("@me") + if err != nil { + return err + } + ch, err := c.discord.UserChannelCreate(info.Owner.ID) + if err != nil { + return err + } + c.channelID = ch.ID + + c.discord.AddHandler(func(s *discordgo.Session, m *discordgo.MessageCreate) { + if m.Author.Bot || m.ChannelID != c.channelID { + return + } + c.sendChat(m.Content) + }) + + return c.discord.Open() +} + +func (c *Client) setupMinecraft(email, password string) error { + c.minecraft = bot.NewClient() + basic.NewPlayer(c.minecraft, basic.DefaultSettings) + + auth, err := yggdrasil.Authenticate(email, password) + if err != nil { + return err + } + + c.minecraft.Auth.UUID, c.minecraft.Auth.Name = auth.SelectedProfile() + c.minecraft.Auth.AsTk = auth.AccessToken() + + basic.EventsListener{ + GameStart: func() error { + <-time.After(time.Second * 5) + c.sendChat("/afk") + return nil + }, + ChatMsg: c.onChatMsg, + }.Attach(c.minecraft) + + return nil +} + +func (c *Client) onChatSend() { + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() { + msg := scanner.Text() + if strings.TrimSpace(msg) == "" { + continue + } + c.sendChat(msg) + } +} diff --git a/main.go b/main.go index cf1c77b..6847ce2 100644 --- a/main.go +++ b/main.go @@ -1,23 +1,13 @@ package main import ( - "bufio" "flag" - "github.com/bwmarrin/discordgo" - "os" - "os/signal" - "strings" - - "github.com/Tnze/go-mc/bot" - "github.com/Tnze/go-mc/bot/basic" _ "github.com/Tnze/go-mc/data/lang/en-us" - "github.com/Tnze/go-mc/data/packetid" - "github.com/Tnze/go-mc/net/packet" - "github.com/Tnze/go-mc/yggdrasil" "github.com/peterbourgon/ff/v3" "github.com/peterbourgon/ff/v3/fftoml" "github.com/rs/zerolog" "github.com/rs/zerolog/log" + "os" ) func main() { @@ -43,77 +33,10 @@ func main() { zerolog.SetGlobalLevel(zerolog.DebugLevel) } - minecraft := bot.NewClient() - basic.NewPlayer(minecraft, basic.DefaultSettings) - - auth, err := yggdrasil.Authenticate(*emailFlag, *passwordFlag) + client, err := NewClient(*emailFlag, *passwordFlag, *ipFlag, *discordFlag) if err != nil { log.Fatal().Err(err).Msg("") } - minecraft.Auth.UUID, minecraft.Auth.Name = auth.SelectedProfile() - minecraft.Auth.AsTk = auth.AccessToken() - - var discord *discordgo.Session - if *discordFlag != "" { - discord, err = discordgo.New("Bot " + *discordFlag) - if err != nil { - log.Fatal().Err(err).Msg("") - } - // TODO discord.Application("@me") - } - - client := &Client{ - minecraft: minecraft, - discord: discord, - } - - basic.EventsListener{ - GameStart: func() error { - sendChat(minecraft, "/afk") - return nil - }, - ChatMsg: client.onChatMsg, - }.Attach(minecraft) - - err = minecraft.JoinServer(*ipFlag) - if err != nil { - log.Fatal().Err(err).Msg("") - } - log.Info().Msg("Login success") - - go onChatSend(minecraft) - - go func() { - for { - err := minecraft.HandleGame() - if err != nil { - log.Err(err).Msg("") - } - } - }() - - ch := make(chan os.Signal, 1) - signal.Notify(ch, os.Interrupt, os.Kill) - <-ch -} - -func onChatSend(c *bot.Client) { - scanner := bufio.NewScanner(os.Stdin) - for scanner.Scan() { - msg := scanner.Text() - if strings.TrimSpace(msg) == "" { - continue - } - sendChat(c, msg) - } -} - -func sendChat(c *bot.Client, msg string) { - if err := c.Conn.WritePacket(packet.Marshal( - packetid.ServerboundChat, - packet.String(msg), - )); err != nil { - log.Err(err).Msg("") - } + client.Run() }