Skip to content

xanning/Liyue

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 

Repository files navigation

hello

Liyue

An example Discord bot (made with py-cord & scraping) that's able to track players' progression on Hypixel Bedwars. Vibe-coded.

How it works?

When you add players to track, it scrapes their stats from Plancke every 60 seconds, and if it finds a stats-difference, sends a message to the configured channel.

Accuracy

It's as accurate as Plancke. It might be delayed, late, or skipping games as 2 games in per message, that's all how Plancke caches/works.

Efficiency

It's vibe coded. Heavily the discord-bot part is made with AI. I didn't improve this much, so I don't know how it would act with adding 10-15+ players to track.

Commands

/track add <username> will add a player to the tracker.

/track remove <username> will remove a player to tracker.

/track fetch <username> will scrape a player's stats from Plancke, return it in JSON.

/track latest <username> will return the specified player's last fetched stats from the loop, in JSON.

/track list will show the currently tracked players.

Installing

  • Download the main.py file

  • Open the file, on the top part, enter your Discord BOT token, and your Channel ID, optionally the loop interval (in seconds).

  • Run the python file.

Improvements

If you want to improve this, please do it for yourself. Any opened pull requests will probably be merged if they make sense, but this really doesn't need that much attention.

Why?

It's an example on how to scrape Plancke. Not a way to actually track down winstreakers. It might help you, who knows.

For the nerds

We first send a request to https://plancke.io/hypixel/player/stats/{username}, and get the page contents. We do it with proper User Agents, so we don't get 403.

After having the page, we use BeautifulSoup to locate the BedWars panel stat_panel_BedWars

Selected the table, we obtain the stats on top (such as Level, Resources collected etc.) with selecting ul.list-unstyled li and going through every label that has this.

Then, we parse the table with

 table = panel.find("table", {"class": "table"})
        rows = table.find_all("tr")

        headers = [th.get_text(strip=True) for th in rows[1].find_all("th")]

to select the Mode Statistics, AFTER Final Kills section and we go through every row th-td

  for row in rows[2:]:
            cols = row.find_all(["th", "td"])
            if not cols:
                continue
            mode_name = cols[0].get_text(strip=True)
            if not mode_name or mode_name in ("", "-"):
                continue

and save the modes stats. Finally we can convert the scraped stats to JSON.

stats = {}
            for idx, col in enumerate(cols[1:], start=1):
                val = col.get_text(strip=True)
                stats[headers[idx]] = val
            modes_data.append({"mode": mode_name, "stats": stats})

        return {
            "base_stats": base_stats,
            "modes": modes_data
        }

Now the JSON we have, includes statistics like

  • Tokens, Winstreak, Resources Collected, Ender Dust etc. on base_stats

  • All BedWars modes (including Dreams) and Overall, Core Modes stats (Final Kills, Final Deaths, FKDR, Wins, Losses, W/L, Beds Broken)

Keep in mind that because we selected only the rows after Final Kills table we don't get Normal kills & deaths & k/d.

The Kills on JSON is Final Kills, same for Deaths and K/D.

We save these stats on a temporary array, and in the next loop, we compare them, if anything different, send that to the channel.

If YOU want to scrape stats for another gamemode, you can change the stat panel name e.g: stat_panel_Duels and change the way you go through and parse the rows according to how the table is styled.

Example JSON response
   {
    "base_stats": {
        "Tokens": "2,434,224",
        "Winstreak": "0",
        "Prestige": "Rainbow",
        "Level": "1,320",
        "Diamonds Collected": "176,915",
        "Emeralds Collected": "84,160",
        "Gold Collected": "719,753",
        "Iron Collected": "4,589,513",
        "Bed Sheets": "500",
        "Ender Dust": "500",
        "Iron Nugget": "500",
        "Silver Coins": "500",
        "Soul": "500",
        "Token of Ferocity": "500",
        "Cable": "500",
        "Gold Bar": "500",
        "Proof of Success": "500",
        "Timeworn Mystery Box": "500",
        "Diamond Fragment": "500",
        "Comfy Pillow": "286"
    },
    "modes": [
        {
            "mode": "Solo",
            "stats": {
                "Kills": "29,062",
                "Deaths": "8,644",
                "K/D": "3.36",
                "Wins": "6,025",
                "Losses": "9,031",
                "W/L": "0.67",
                "Beds Broken": "29,778"
            }
        },
        {
            "mode": "Doubles",
            "stats": {
                "Kills": "3,075",
                "Deaths": "1,039",
                "K/D": "2.96",
                "Wins": "530",
                "Losses": "1,031",
                "W/L": "0.51",
                "Beds Broken": "1,609"
            }
        },
        {
            "mode": "3v3v3v3",
            "stats": {
                "Kills": "1,170",
                "Deaths": "813",
                "K/D": "1.44",
                "Wins": "416",
                "Losses": "767",
                "W/L": "0.54",
                "Beds Broken": "612"
            }
        },
        {
            "mode": "4v4v4v4",
            "stats": {
                "Kills": "3,766",
                "Deaths": "1,735",
                "K/D": "2.17",
                "Wins": "1,158",
                "Losses": "1,688",
                "W/L": "0.69",
                "Beds Broken": "1,611"
            }
        },
        {
            "mode": "Core Modes",
            "stats": {
                "Kills": "37,073",
                "Deaths": "12,231",
                "K/D": "3.03",
                "Wins": "8,129",
                "Losses": "12,517",
                "W/L": "0.65",
                "Beds Broken": "33,610"
            }
        },
        {
            "mode": "4v4",
            "stats": {
                "Kills": "16",
                "Deaths": "2",
                "K/D": "8",
                "Wins": "8",
                "Losses": "3",
                "W/L": "2.67",
                "Beds Broken": "2"
            }
        },
        {
            "mode": "Rush Solo",
            "stats": {
                "Kills": "0",
                "Deaths": "0",
                "K/D": "-",
                "Wins": "0",
                "Losses": "0",
                "W/L": "-",
                "Beds Broken": "0"
            }
        },
        {
            "mode": "Rush Doubles",
            "stats": {
                "Kills": "24",
                "Deaths": "11",
                "K/D": "2.18",
                "Wins": "5",
                "Losses": "11",
                "W/L": "0.45",
                "Beds Broken": "14"
            }
        },
        {
            "mode": "Rush 4v4v4v4",
            "stats": {
                "Kills": "23",
                "Deaths": "4",
                "K/D": "5.75",
                "Wins": "6",
                "Losses": "4",
                "W/L": "1.5",
                "Beds Broken": "17"
            }
        },
        {
            "mode": "Ultimate Solo",
            "stats": {
                "Kills": "0",
                "Deaths": "0",
                "K/D": "-",
                "Wins": "0",
                "Losses": "0",
                "W/L": "-",
                "Beds Broken": "0"
            }
        },
        {
            "mode": "Ultimate Doubles",
            "stats": {
                "Kills": "30",
                "Deaths": "11",
                "K/D": "2.73",
                "Wins": "6",
                "Losses": "11",
                "W/L": "0.55",
                "Beds Broken": "15"
            }
        },
        {
            "mode": "Ultimate 4v4v4v4",
            "stats": {
                "Kills": "35",
                "Deaths": "12",
                "K/D": "2.92",
                "Wins": "10",
                "Losses": "10",
                "W/L": "1",
                "Beds Broken": "24"
            }
        },
        {
            "mode": "Lucky Doubles",
            "stats": {
                "Kills": "1,962",
                "Deaths": "548",
                "K/D": "3.58",
                "Wins": "218",
                "Losses": "585",
                "W/L": "0.37",
                "Beds Broken": "1,137"
            }
        },
        {
            "mode": "Lucky 4v4v4v4",
            "stats": {
                "Kills": "35",
                "Deaths": "7",
                "K/D": "5",
                "Wins": "13",
                "Losses": "5",
                "W/L": "2.6",
                "Beds Broken": "14"
            }
        },
        {
            "mode": "Castle",
            "stats": {
                "Kills": "29",
                "Deaths": "7",
                "K/D": "4.14",
                "Wins": "19",
                "Losses": "11",
                "W/L": "1.73",
                "Beds Broken": "5"
            }
        },
        {
            "mode": "Capture",
            "stats": {
                "Kills": "0",
                "Deaths": "0",
                "K/D": "-",
                "Wins": "0",
                "Losses": "0",
                "W/L": "-",
                "Beds Broken": "0"
            }
        },
        {
            "mode": "Swap Doubles",
            "stats": {
                "Kills": "70",
                "Deaths": "13",
                "K/D": "5.38",
                "Wins": "11",
                "Losses": "13",
                "W/L": "0.85",
                "Beds Broken": "41"
            }
        },
        {
            "mode": "Swap 4v4v4v4",
            "stats": {
                "Kills": "0",
                "Deaths": "0",
                "K/D": "-",
                "Wins": "0",
                "Losses": "0",
                "W/L": "-",
                "Beds Broken": "0"
            }
        },
        {
            "mode": "Voidless 4v4v4v4",
            "stats": {
                "Kills": "7",
                "Deaths": "2",
                "K/D": "3.5",
                "Wins": "1",
                "Losses": "2",
                "W/L": "0.5",
                "Beds Broken": "3"
            }
        },
        {
            "mode": "Overall",
            "stats": {
                "Kills": "37,089",
                "Deaths": "12,233",
                "K/D": "3.03",
                "Wins": "8,137",
                "Losses": "12,520",
                "W/L": "0.65",
                "Beds Broken": "33,612"
            }
        }
    ]
}

About

An example Discord bot (made with py-cord & scraping) that's able to track players' progression on Hypixel Bedwars

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages