Personal Project  /  Hypixel Guild Automation

GUILD BOT

Two bots and one bridge between Minecraft and Discord, so a guild could talk, track itself, and onboard new members without an admin ever being online.

Solo build Node.js Discord.js Mineflayer Hypixel API · Mojang API

01 — The idea

The guild lived in two places that could not talk to each other.

I spend a lot of my free time building small tools that make everyday tasks less tedious, and this is the project I am most proud of. Our Minecraft guild ran on Hypixel, the largest Minecraft server, but the actual community lived on Discord. Those were two completely separate places, and keeping them in sync was all manual work: who was active, who was new, who deserved a promotion, who was even who.

I wanted the two to feel like one thing. So I built a bot, or really two bots working as a pair, that sat between Hypixel and Discord and handled the glue automatically. Members could talk across both platforms, their activity was tracked without anyone watching, and new players could join the guild without waiting around for an admin to be online.

02 — Architecture

Two bots, one shared brain.

A Minecraft bot and a Discord bot running in one process, so one could drive the other directly.

The system had two halves, but they ran from a single JavaScript codebase in one process. A Minecraft bot stayed logged into Hypixel and read the in-game guild chat, and a Discord bot ran the slash commands and roles on the Discord side. Because they shared a process, the Minecraft bot could call the Discord bot directly, so an in-game event could fire a Discord action on the spot without waiting on anything in between. A shared database held the persistent state both sides leaned on, like account links and activity, and two external APIs fed the whole thing: the Hypixel API for guild and player data, and the Mojang API for resolving usernames to account UUIDs.

Hypixel Minecraft server Discord guild server Minecraft bot Mineflayer · regex reads guild chat Discord bot Discord.js · slash commands + roles direct calls Shared database links · activity · state Hypixel API Mojang API

One process, one codebase. The Minecraft bot calls the Discord bot directly, with a shared database holding the state between them.

2
Linked platforms
5 min
Activity poll
24h
XP sync cycle
0
Admins online needed

03 — What it did

Everything the guild needed, running on its own.

  • ActivityTracked guild XP and estimated playtime, then flagged members for promotion or demotion.
  • VerificationLinked each Minecraft account to a Discord account and gated the server behind it.
  • ApplicationsTook applicants from the Hypixel forums or straight from Discord, then handled the invite.

Activity tracking

Activity came down to two things: guild XP and playtime. XP was the easy half, since the Hypixel API returns a daily XP value per member. The bot called the API once a day and wrote each player's number to the database.

Playtime was the interesting problem, because Hypixel does not expose it. My workaround was to run a command every five minutes that listed who was online, and increment a daily counter each time a member showed up. It was an estimate, not a stopwatch, but it was consistent enough to give admins a reliable read on who was actually playing. All of this fed a weekly promotion and demotion check against activity milestones, surfaced in a Discord interface that flagged eligible members so an admin could review and act in seconds.

Account linking and verification

Linking was the piece everything else leaned on, since it told the bot which Discord user matched which in-game player. I used a common Hypixel trick: a player put their Discord username into a designated field on their Hypixel profile, which the API exposes, and the bot verified ownership and tied the two accounts together.

Verification was required before anyone could get into the Discord server. That did two jobs at once. It guaranteed every member was properly linked, and it quietly kept out the spammers and advertisers who could not pass it.

Applications and invites

Players could apply two ways. Through the Hypixel forums, where accepted applicants got a reply pointing them to the Discord, or directly through Discord, where a button spun up a private channel for them to fill out an application that admins then reviewed.

The annoying part of guild invites is that a player and an admin have to be online at the same moment. I solved that with a pending invite queue. An admin dropped a name into the queue, and whenever that player later joined the Discord, the bot greeted them and handed them a button that sent their in-game invite instantly. It cut the waiting out of onboarding almost entirely.

04 — How I built it

Two modular systems, same idea on both sides.

JavaScript throughout, with Discord.js and Mineflayer doing the heavy lifting.

Discord.js: a command per file

On the Discord side I used a file-based command system. Each command was its own file holding its config (name, description, required roles, options) and a run function, so adding a command meant dropping in a new file rather than touching a big switch statement. Slash commands support subcommands too, so I grouped related ones into subfolders. The birthday command, for example, let anyone with the Birthday role recolor it on their day with a hex code.

commands/birthday.js javascript
const { MessageEmbed } = require("discord.js");
const cfg = require("../botconfig/botconfig.json");

module.exports = {
  name: "birthday",
  description: "Change the Birthday role color",
  requiredroles: [cfg.roles.birthday],
  options: [
    { String: { name: "hexcode", description: "Insert a hex color code", required: true } },
  ],

  run: async (client, interaction) => {
    const hexCode = interaction.options.getString("hexcode");
    const role = interaction.guild.roles.cache.get(cfg.roles.birthday);

    role.edit({ color: hexCode })
      .then(() => interaction.reply(`Birthday role color changed to ${hexCode}`));
  },
};

Mineflayer: a regex handler per event

Mineflayer's job was to stay logged into Hypixel and react to the guild chat. I kept it organized the same way as the Discord commands, but keyed on regex instead: each handler lived in its own file and fired when a chat line matched its pattern. When a new member joined the guild, one handler caught the event, welcomed them in guild chat, pulled their UUID from Mojang, checked whether their Minecraft account was linked to a Discord account, and synced their Discord roles and welcome message. No admin had to be online for any of it.

handlers/guildJoin.js javascript
module.exports = {
  name: "guildJoin",
  regex: /(?:\[.{0,20}\] )?(?<username>[A-Za-z0-9_]{0,17}) joined the guild!/,
  description: "Handles new guild member joins.",

  run: async (bot, username) => {
    bot.chat(`/gc Welcome to the guild, ${username}`);
    // fetch UUID from Mojang, sync the Discord account, assign roles, post welcome
  },
};

Both sides ended up following the same shape: small, single-purpose files that the bot loaded automatically. It kept the codebase easy to reason about, and adding a feature rarely meant editing anything that already worked.

05 — Takeaway

This is the project where building tools stopped feeling like a hobby and started feeling like the thing I actually want to do.

The lesson that stuck was how much the modular structure paid off. Once both sides followed the same shape, small single-purpose files loaded automatically, adding a feature almost never meant touching code that already worked. That is usually where my side projects fall apart, and here it was the opposite: the bot stayed easy to extend long after the first version shipped, so I kept adding to it instead of abandoning it.

It also pushed me on the messier problems, the ones with no clean answer in the docs. Estimating playtime when the API never reports it, so I had to approximate it from who showed up online every few minutes. Working around the timing problem where a new player and an admin were almost never online at the same moment, which is what the pending invite queue was for. Keeping one codebase sane while it drove two very different bots at once. Those were the parts I enjoyed most, and they taught me more about tying real systems together than any tutorial had.

Mostly, though, it was satisfying to watch it run without me. Members got welcomed, tracked, and onboarded while every admin, myself included, was offline, and over time the guild came to count on it day to day. Taking something tedious and manual and turning it into something people quietly depend on is the feeling that keeps me building.

Guild Bot · Hypixel × Discord Personal project · Node.js