Skip to content

Instantly share code, notes, and snippets.

@CraigglesO
Created January 23, 2026 15:44
Show Gist options
  • Select an option

  • Save CraigglesO/faca1f5efab711bac01c578622cc2916 to your computer and use it in GitHub Desktop.

Select an option

Save CraigglesO/faca1f5efab711bac01c578622cc2916 to your computer and use it in GitHub Desktop.
Get Information about a user in Mousehunt using Typescript
export interface UserHorn {
horns: number;
trapChecks: number;
friendHunts: number;
total: number;
}
export interface UserSetup {
trap: string;
base: string;
skin: string;
cheese: string;
cheeseQuantity: number;
charm: string;
charmQuantity: number;
}
export interface User {
id: string;
name: string;
rank: string;
rankProgress: number;
miceCaught: number;
miceTotal: number;
rareMiceCaught: number;
rareMiceTotal: number;
gold: number;
points: number;
location: string;
setup: UserSetup;
horn: UserHorn;
}
// TODO:
// - Treasure Maps: <div class="hunterInfoView-treasureMaps-left-currentMap-content"><div class="hunterInfoView-treasureMaps-left-currentMap-content-title">Fort Rox Treasure Map</div>
export async function get_user(id = "4850475") {
const html = await (
await fetch(`https://www.mousehuntgame.com/p.php?id=${id}`)
).text();
// Extract the core description block
const desc = parse(html, 'property="og:description" content="', '"');
const nameLine = parse(
html,
'property="og:title" content="MouseHunt - ',
'"',
);
if (!desc) return console.error("Could not parse profile");
const lines = desc.split("\n");
const mice = lines[1]?.split(": ")[1]?.split("/") ?? [];
const rare = lines[2]?.split(": ")[1]?.split("/") ?? [];
// Extract Trap Setup names using data-name="..."
// Match 0: Trap, 1: Base, 2: Cheese, 3: Charm, 4: Skin
const names = [...html.matchAll(/data-name="([^"]+)"/g)].map((m) => m[1]);
// Extract Quantities using the slot-quantity class
// Match 0: Cheese Qty, 1: Charm Qty
const qtys = [...html.matchAll(/slot-quantity">([^<]+)</g)].map((m) => m[1]);
const rankProgressSection =
html.split("friendsPage-friendRow-titleBar-titleDetail")[1] ?? "";
const user: User = {
id,
name: nameLine ?? "",
rank: lines[0]?.split(" is a ")[1]?.split(" in ")[0] ?? "",
rankProgress: toFloat(getAttr(rankProgressSection, "data-text")),
miceCaught: toNumber(mice[0] ?? "0"),
miceTotal: toNumber(mice[1] ?? "0"),
rareMiceCaught: toNumber(rare[0] ?? "0"),
rareMiceTotal: toNumber(rare[1] ?? "0"),
gold: toNumber(lines[3]?.split(": ")[1] ?? "0"),
points: toNumber(lines[4]?.split(": ")[1] ?? "0"),
location: lines[5]?.split(": ")[1] ?? "",
setup: {
trap: names[0] || "None",
base: names[1] || "None",
skin: names[4] || "None",
cheese: names[2] || "None",
cheeseQuantity: toNumber(qtys[0] || "0"),
charm: names[3] || "None",
charmQuantity: toNumber(qtys[1] || "0"),
},
horn: {
horns: toNumber(getAttr(html, "data-num-active-turns")),
trapChecks: toNumber(getAttr(html, "data-num-passive-turns")),
friendHunts: toNumber(getAttr(html, "data-num-linked-turns")),
total: toNumber(getAttr(html, "data-num-total-turns")),
},
};
console.log("user", user);
}
function parse(html: string, start: string, end: string) {
return html.split(start)[1]?.split(end)[0]?.trim();
}
function getAttr(html: string, key: string) {
return (
html.split(`${key}='`)[1]?.split("'")[0] ??
html.split(`${key}="`)[1]?.split('"')[0] ??
""
);
}
function toNumber(str: string) {
return parseInt(str.replace(/,/g, ""));
}
function toFloat(str: string) {
return parseFloat(str.replace(/,/g, "").replace("%", ""));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment