OOKNET                             [ /  search the index  ]  
──────────────────────────────────────────────────────────────────────────────────────
══════════════════════════════════════════════════════════════════════════════════════
OOKNET   [ /  search  ]  
────────────────────────────────────────────────
════════════════════════════════════════════════
 
 
master @ 222 LINES
 
[ HISTORY ]  [ UP ]
 

// player profile embed formatter

import type { Embed, MessageComponent } from "../types.js";
import { ComponentType, ButtonStyle } from "../types.js";
import type { PlayerProfileData } from "../../lib/types.js";
import {
  SPEC_EMOJI_IDS,
  API_BASE_URL,
  DUNGEON_EMOJI_IDS,
  CLASS_COLORS,
} from "../constants.js";
import { formatDurationFromMs } from "../../lib/utils.js";

// bracket to percentile mapping
const BRACKET_PERCENTILES: Record<string, string> = {
  artifact: "#1",
  excellent: "Top 1%",
  legendary: "Top 5%",
  epic: "Top 20%",
  rare: "Top 40%",
  uncommon: "Top 60%",
  common: "-",
};

// creates a player profile embed
export function createPlayerProfileEmbed(
  profile: PlayerProfileData,
  season: string = "2",
): Embed {
  const player = profile.player;
  if (!player) {
    throw new Error("Player data not found");
  }

  // get specified season data, fallback to latest season if requested season does
n't exist
  let seasonData = player.seasons?.[season];
  let actualSeason = season;

  if (!seasonData && player.seasons) {
    // find the highest season number available
    const availableSeasons = Object.keys(player.seasons)
      .map(Number)
      .sort((a, b) => b - a);
    if (availableSeasons.length > 0) {
      actualSeason = String(availableSeasons[0]);
      seasonData = player.seasons[actualSeason];
    }
  }

  // determine ranking bracket
  const bracket = seasonData?.global_ranking_bracket || "common";

  // spec emoji (use class|spec format like frontend)
  const specKey = `${player.class_name}|${player.active_spec_name || ""}`;
  const emojiId = SPEC_EMOJI_IDS[specKey];
  const emojiName = (player.active_spec_name || "")
    .toLowerCase()
    .replace(/\s+/g, "_");
  const specEmoji = emojiId ? `<:${emojiName}:${emojiId}> ` : "";

  // build title
  const title = `${specEmoji}${player.name} - ${player.realm_name} (${player.regio
n.toUpperCase()})`;

  // build description
  let description = "";
  if (player.class_name && player.active_spec_name) {
    description = `**${player.class_name}** (${player.active_spec_name})`;
    if (player.guild_name) {
      description += `\n<${player.guild_name}>`;
    }
  }

  // build fields
  const fields = [];

  // rankings field
  if (seasonData) {
    let rankingsText = "";
    const globalPercentile = BRACKET_PERCENTILES[bracket] || "-";
    const regionalBracket = seasonData.regional_ranking_bracket || "";
    const regionalPercentile = BRACKET_PERCENTILES[regionalBracket] || "-";
    const realmBracket = seasonData.realm_ranking_bracket || "";
    const realmPercentile = BRACKET_PERCENTILES[realmBracket] || "-";

    if (seasonData.global_ranking) {
      // only show percentile if not rank 1 (would be redundant)
      const percentileText =
        seasonData.global_ranking === 1 ? "" : ` (${globalPercentile})`;
      rankingsText += `**Global:** #${seasonData.global_ranking}${percentileText}\
n`;
    }
    if (seasonData.regional_ranking) {
      const percentileText =
        seasonData.regional_ranking === 1 ? "" : ` (${regionalPercentile})`;
      rankingsText += `**Regional:** #${seasonData.regional_ranking}${percentileTe
xt}\n`;
    }
    if (seasonData.realm_ranking) {
      const percentileText =
        seasonData.realm_ranking === 1 ? "" : ` (${realmPercentile})`;
      rankingsText += `**Realm:** #${seasonData.realm_ranking}${percentileText}`;
    }

    fields.push({
      name: "? Rankings",
      value: rankingsText,
      inline: false,
    });
  }

  // combined time field
  if (seasonData?.combined_best_time) {
    const combinedTime = formatDurationFromMs(seasonData.combined_best_time);
    const dungeonsCompleted = seasonData.dungeons_completed || 0;
    fields.push({
      name: "Combined Time",
      value: `\`${combinedTime}\` (${dungeonsCompleted}/9 dungeons)`,
      inline: false,
    });
  }

  // best runs field
  if (seasonData?.best_runs) {
    const bestRunsArray = Object.values(seasonData.best_runs);
    if (bestRunsArray.length > 0) {
      const bestRunsText = bestRunsArray
        .slice(0, 9)
        .map((run) => {
          const dungeonSlug = run.dungeon_slug || "";

          // get dungeon emoji
          const emojiId = DUNGEON_EMOJI_IDS[dungeonSlug];
          const emojiName = dungeonSlug.replace(/-/g, "_");
          const dungeonEmoji = emojiId ? `<:${emojiName}:${emojiId}>` : "";

          return `${dungeonEmoji} \`${formatDurationFromMs(run.duration)}\``;
        })
        .join("\n");

      fields.push({
        name: "?? Best Times",
        value: bestRunsText || "No runs recorded",
        inline: false,
      });
    }
  }

  // get class color for embed sidebar
  const classKey = player.class_name
    ?.toLowerCase()
    .replace(/\s+/g, "_") as keyof typeof CLASS_COLORS;
  const color = CLASS_COLORS[classKey] || 0x5865f2; // fallback to discord blurple

  // add footer with season info
  const seasonNote =
    actualSeason !== season
      ? ` - Showing Season ${actualSeason} (Season ${season} data not available)`
      : ` - Season ${actualSeason}`;

  return {
    title,
    description,
    fields,
    color,
    footer: {
      text: `wowsimstats.com${seasonNote}`,
    },
    timestamp: new Date().toISOString(),
  };
}

// creates buttons to view profile on website and armory
export function createViewProfileButton(
  name: string,
  realm: string,
  region: string,
  season: string = "2",
): MessageComponent[] {
  const profileUrl = `${API_BASE_URL}/player/${region}/${realm}/${name}?season=${s
eason}`;
  const armoryUrl = `https://classic-armory.org/character/${region}/mop/${realm}/$
{name}`;

  return [
    {
      type: ComponentType.ACTION_ROW,
      components: [
        {
          type: ComponentType.BUTTON,
          style: ButtonStyle.PRIMARY,
          label: "? Refresh",
          custom_id: `refresh_player:${region}:${realm}:${name}:${season}`,
        },
        {
          type: ComponentType.BUTTON,
          style: ButtonStyle.LINK,
          label: "View Full Profile",
          url: profileUrl,
        },
        {
          type: ComponentType.BUTTON,
          style: ButtonStyle.LINK,
          label: "View Armory",
          url: armoryUrl,
        },
      ],
    },
  ];
}

// helper to get dungeon short name from slug
function getDungeonShortName(slug: string): string {
  const shortNames: Record<string, string> = {
    "gate-of-the-setting-sun": "GSS",
    "mogu-shan-palace": "MSP",
    "scarlet-halls": "SH",
    "scarlet-monastery": "SM",
    scholomance: "SCHOLO",
    "shado-pan-monastery": "SPM",
    "siege-of-niuzao-temple": "SNT",
    "stormstout-brewery": "SB",
    "temple-of-the-jade-serpent": "TJS",
  };
  return shortNames[slug] || slug;
}

// player profile embed formatter

import type { Embed, MessageComponent } from
 "../types.js";
import { ComponentType, ButtonStyle } from "
../types.js";
import type { PlayerProfileData } from "../.
./lib/types.js";
import {
  SPEC_EMOJI_IDS,
  API_BASE_URL,
  DUNGEON_EMOJI_IDS,
  CLASS_COLORS,
} from "../constants.js";
import { formatDurationFromMs } from "../../
lib/utils.js";

// bracket to percentile mapping
const BRACKET_PERCENTILES: Record<string, st
ring> = {
  artifact: "#1",
  excellent: "Top 1%",
  legendary: "Top 5%",
  epic: "Top 20%",
  rare: "Top 40%",
  uncommon: "Top 60%",
  common: "-",
};

// creates a player profile embed
export function createPlayerProfileEmbed(
  profile: PlayerProfileData,
  season: string = "2",
): Embed {
  const player = profile.player;
  if (!player) {
    throw new Error("Player data not found")
;
  }

  // get specified season data, fallback to 
latest season if requested season doesn't ex
ist
  let seasonData = player.seasons?.[season];
  let actualSeason = season;

  if (!seasonData && player.seasons) {
    // find the highest season number availa
ble
    const availableSeasons = Object.keys(pla
yer.seasons)
      .map(Number)
      .sort((a, b) => b - a);
    if (availableSeasons.length > 0) {
      actualSeason = String(availableSeasons
[0]);
      seasonData = player.seasons[actualSeas
on];
    }
  }

  // determine ranking bracket
  const bracket = seasonData?.global_ranking
_bracket || "common";

  // spec emoji (use class|spec format like 
frontend)
  const specKey = `${player.class_name}|${pl
ayer.active_spec_name || ""}`;
  const emojiId = SPEC_EMOJI_IDS[specKey];
  const emojiName = (player.active_spec_name
 || "")
    .toLowerCase()
    .replace(/\s+/g, "_");
  const specEmoji = emojiId ? `<:${emojiName
}:${emojiId}> ` : "";

  // build title
  const title = `${specEmoji}${player.name} 
- ${player.realm_name} (${player.region.toUp
perCase()})`;

  // build description
  let description = "";
  if (player.class_name && player.active_spe
c_name) {
    description = `**${player.class_name}** 
(${player.active_spec_name})`;
    if (player.guild_name) {
      description += `\n<${player.guild_name
}>`;
    }
  }

  // build fields
  const fields = [];

  // rankings field
  if (seasonData) {
    let rankingsText = "";
    const globalPercentile = BRACKET_PERCENT
ILES[bracket] || "-";
    const regionalBracket = seasonData.regio
nal_ranking_bracket || "";
    const regionalPercentile = BRACKET_PERCE
NTILES[regionalBracket] || "-";
    const realmBracket = seasonData.realm_ra
nking_bracket || "";
    const realmPercentile = BRACKET_PERCENTI
LES[realmBracket] || "-";

    if (seasonData.global_ranking) {
      // only show percentile if not rank 1 
(would be redundant)
      const percentileText =
        seasonData.global_ranking === 1 ? ""
 : ` (${globalPercentile})`;
      rankingsText += `**Global:** #${season
Data.global_ranking}${percentileText}\n`;
    }
    if (seasonData.regional_ranking) {
      const percentileText =
        seasonData.regional_ranking === 1 ? 
"" : ` (${regionalPercentile})`;
      rankingsText += `**Regional:** #${seas
onData.regional_ranking}${percentileText}\n`
;
    }
    if (seasonData.realm_ranking) {
      const percentileText =
        seasonData.realm_ranking === 1 ? "" 
: ` (${realmPercentile})`;
      rankingsText += `**Realm:** #${seasonD
ata.realm_ranking}${percentileText}`;
    }

    fields.push({
      name: "? Rankings",
      value: rankingsText,
      inline: false,
    });
  }

  // combined time field
  if (seasonData?.combined_best_time) {
    const combinedTime = formatDurationFromM
s(seasonData.combined_best_time);
    const dungeonsCompleted = seasonData.dun
geons_completed || 0;
    fields.push({
      name: "Combined Time",
      value: `\`${combinedTime}\` (${dungeon
sCompleted}/9 dungeons)`,
      inline: false,
    });
  }

  // best runs field
  if (seasonData?.best_runs) {
    const bestRunsArray = Object.values(seas
onData.best_runs);
    if (bestRunsArray.length > 0) {
      const bestRunsText = bestRunsArray
        .slice(0, 9)
        .map((run) => {
          const dungeonSlug = run.dungeon_sl
ug || "";

          // get dungeon emoji
          const emojiId = DUNGEON_EMOJI_IDS[
dungeonSlug];
          const emojiName = dungeonSlug.repl
ace(/-/g, "_");
          const dungeonEmoji = emojiId ? `<:
${emojiName}:${emojiId}>` : "";

          return `${dungeonEmoji} \`${format
DurationFromMs(run.duration)}\``;
        })
        .join("\n");

      fields.push({
        name: "?? Best Times",
        value: bestRunsText || "No runs reco
rded",
        inline: false,
      });
    }
  }

  // get class color for embed sidebar
  const classKey = player.class_name
    ?.toLowerCase()
    .replace(/\s+/g, "_") as keyof typeof CL
ASS_COLORS;
  const color = CLASS_COLORS[classKey] || 0x
5865f2; // fallback to discord blurple

  // add footer with season info
  const seasonNote =
    actualSeason !== season
      ? ` - Showing Season ${actualSeason} (
Season ${season} data not available)`
      : ` - Season ${actualSeason}`;

  return {
    title,
    description,
    fields,
    color,
    footer: {
      text: `wowsimstats.com${seasonNote}`,
    },
    timestamp: new Date().toISOString(),
  };
}

// creates buttons to view profile on websit
e and armory
export function createViewProfileButton(
  name: string,
  realm: string,
  region: string,
  season: string = "2",
): MessageComponent[] {
  const profileUrl = `${API_BASE_URL}/player
/${region}/${realm}/${name}?season=${season}
`;
  const armoryUrl = `https://classic-armory.
org/character/${region}/mop/${realm}/${name}
`;

  return [
    {
      type: ComponentType.ACTION_ROW,
      components: [
        {
          type: ComponentType.BUTTON,
          style: ButtonStyle.PRIMARY,
          label: "? Refresh",
          custom_id: `refresh_player:${regio
n}:${realm}:${name}:${season}`,
        },
        {
          type: ComponentType.BUTTON,
          style: ButtonStyle.LINK,
          label: "View Full Profile",
          url: profileUrl,
        },
        {
          type: ComponentType.BUTTON,
          style: ButtonStyle.LINK,
          label: "View Armory",
          url: armoryUrl,
        },
      ],
    },
  ];
}

// helper to get dungeon short name from slu
g
function getDungeonShortName(slug: string): 
string {
  const shortNames: Record<string, string> =
 {
    "gate-of-the-setting-sun": "GSS",
    "mogu-shan-palace": "MSP",
    "scarlet-halls": "SH",
    "scarlet-monastery": "SM",
    scholomance: "SCHOLO",
    "shado-pan-monastery": "SPM",
    "siege-of-niuzao-temple": "SNT",
    "stormstout-brewery": "SB",
    "temple-of-the-jade-serpent": "TJS",
  };
  return shortNames[slug] || slug;
}
 
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET