diff --git a/README.md b/README.md index 24f76d9..84d1196 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,14 @@ Go AFK +## Getting your token + +Login to `minecraft.net`, then paste the following into your console: + +```js +console.log(`; ${document.cookie}`.split(`; bearer_token=`).pop().split(';').shift()) +``` + ## License [MIT](LICENSE) \ No newline at end of file diff --git a/client.go b/client.go index d769e8e..286e2ca 100644 --- a/client.go +++ b/client.go @@ -2,20 +2,22 @@ package main import ( "bufio" + "encoding/json" "errors" + "io" + "net/http" + "os" + "strings" + "time" + "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" ) var discordFmt = strings.NewReplacer( @@ -32,11 +34,11 @@ type Client struct { serverIP string } -func NewClient(email, password, serverIP, discordToken string) (*Client, error) { +func NewClient(token, serverIP, discordToken string) (*Client, error) { c := &Client{ serverIP: serverIP, } - if err := c.setupMinecraft(email, password); err != nil { + if err := c.setupMinecraft(token); err != nil { return nil, err } if discordToken != "" { @@ -48,7 +50,7 @@ func NewClient(email, password, serverIP, discordToken string) (*Client, error) } func (c *Client) Run() { - go c.onChatSend() + go c.onStdin() c.handleGame() } @@ -75,6 +77,15 @@ func (c *Client) handleGame() { } } +func (c *Client) handleInput(input string) { + switch strings.ToLower(input) { + case ".cook": + go c.cook() + default: + c.sendChat(input) + } +} + func (c *Client) sendChat(msg string) { if err := c.minecraft.Conn.WritePacket(packet.Marshal( packetid.ServerboundChat, @@ -113,27 +124,44 @@ func (c *Client) setupDiscord(token string) error { if m.Author.Bot || m.ChannelID != c.channelID { return } - c.sendChat(m.Content) + c.handleInput(m.Content) }) return c.discord.Open() } -func (c *Client) setupMinecraft(email, password string) error { +func (c *Client) setupMinecraft(token string) error { c.minecraft = bot.NewClient() basic.NewPlayer(c.minecraft, basic.DefaultSettings) - auth, err := yggdrasil.Authenticate(email, password) + req, err := http.NewRequest(http.MethodGet, "https://api.minecraftservices.com/minecraft/profile", nil) if err != nil { return err } + req.Header.Set("Authorization", "Bearer "+token) - c.minecraft.Auth.UUID, c.minecraft.Auth.Name = auth.SelectedProfile() - c.minecraft.Auth.AsTk = auth.AccessToken() + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + profile := struct { + ID string `json:"id"` + Name string `json:"name"` + }{} + if err := json.NewDecoder(resp.Body).Decode(&profile); err != nil { + return err + } + + c.minecraft.Auth = bot.Auth{ + Name: profile.Name, + UUID: profile.ID, + AsTk: token, + } basic.EventsListener{ GameStart: func() error { - <-time.After(time.Second * 5) c.sendChat("/afk") return nil }, @@ -143,13 +171,13 @@ func (c *Client) setupMinecraft(email, password string) error { return nil } -func (c *Client) onChatSend() { +func (c *Client) onStdin() { scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { msg := scanner.Text() if strings.TrimSpace(msg) == "" { continue } - c.sendChat(msg) + c.handleInput(msg) } } diff --git a/cook.go b/cook.go new file mode 100644 index 0000000..864948e --- /dev/null +++ b/cook.go @@ -0,0 +1,64 @@ +package main + +import ( + "time" + + "github.com/Tnze/go-mc/data/block" + "github.com/Tnze/go-mc/data/packetid" + "github.com/Tnze/go-mc/net/packet" + "github.com/rs/zerolog/log" +) + +func (c *Client) cook() { + has := false + + // Set selected slot to last + if err := c.minecraft.Conn.WritePacket(packet.Marshal( + packetid.ServerboundSetCarriedItem, + packet.Short(8), + )); err != nil { + log.Err(err).Msg("") + } + <-time.After(time.Millisecond * 500) + + // For slot 9-44 (inventory) + for slot := 9; slot <= 44; slot++ { + // For an entire stack + for count := 1; count <= 64; count += 4 { + // Four on the campfire at a time + for idx := 0; idx < 4; idx++ { + if err := c.minecraft.Conn.WritePacket(packet.Marshal( + packetid.ServerboundInteract, + packet.VarInt(block.Campfire.ID), + packet.VarInt(0), + packet.Opt{Has: &has}, + packet.Opt{Has: &has}, + packet.Opt{Has: &has}, + packet.VarInt(0), + packet.Boolean(false), + )); err != nil { + log.Err(err).Msg("") + } + //if err := c.minecraft.Conn.WritePacket(packet.Marshal( + // packetid.ServerboundUseItem, + // packet.VarInt(0), + //)); err != nil { + // log.Err(err).Msg("") + //} + <-time.After(time.Millisecond * 500) + } + log.Info().Msg("waiting for cook") + // Campfire takes 30 seconds to cook, give short buffer + <-time.After(time.Second * 35) + } + + // Pick the next slot + if err := c.minecraft.Conn.WritePacket(packet.Marshal( + packetid.ServerboundPickItem, + packet.VarInt(slot), + )); err != nil { + log.Err(err).Msg("") + } + <-time.After(time.Millisecond * 500) + } +} diff --git a/go.mod b/go.mod index 6c1d214..00864b5 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.16 require ( github.com/Tnze/go-mc v1.17.2-0.20220104152428-c724909cd711 - github.com/bwmarrin/discordgo v0.23.2 // indirect + github.com/bwmarrin/discordgo v0.23.2 github.com/google/uuid v1.3.0 github.com/pelletier/go-toml v1.9.4 // indirect github.com/peterbourgon/ff/v3 v3.1.2 diff --git a/go.sum b/go.sum index dde8e9e..a0646a4 100644 --- a/go.sum +++ b/go.sum @@ -11,6 +11,7 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/iancoleman/strcase v0.1.3 h1:dJBk1m2/qjL1twPLf68JND55vvivMupZ4wIzE8CTdBw= github.com/iancoleman/strcase v0.1.3/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= diff --git a/main.go b/main.go index 6847ce2..b892001 100644 --- a/main.go +++ b/main.go @@ -2,12 +2,13 @@ package main import ( "flag" + "os" + _ "github.com/Tnze/go-mc/data/lang/en-us" "github.com/peterbourgon/ff/v3" "github.com/peterbourgon/ff/v3/fftoml" "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "os" ) func main() { @@ -15,8 +16,7 @@ func main() { zerolog.SetGlobalLevel(zerolog.InfoLevel) fs := flag.NewFlagSet("afk", flag.ExitOnError) - emailFlag := fs.String("email", "", "Login Email") - passwordFlag := fs.String("password", "", "Login Password") + tokenFlag := fs.String("token", "", "Minecraft bearer token") ipFlag := fs.String("ip", "", "Server IP") discordFlag := fs.String("discord", "", "Discord bot token") debugFlag := fs.Bool("debug", false, "Debug Logging") @@ -33,7 +33,7 @@ func main() { zerolog.SetGlobalLevel(zerolog.DebugLevel) } - client, err := NewClient(*emailFlag, *passwordFlag, *ipFlag, *discordFlag) + client, err := NewClient(*tokenFlag, *ipFlag, *discordFlag) if err != nil { log.Fatal().Err(err).Msg("") }