UNPKG

maplestorysea-mcp-server

Version:

NEXON MapleStory SEA API MCP Server for Claude Desktop - Complete character info, union details, guild data, rankings optimized for SEA servers

380 lines 12.3 kB
"use strict"; /** * Server status and game information utilities * Optimized for MapleStory SEA region with proper timezone and date formatting */ Object.defineProperty(exports, "__esModule", { value: true }); exports.ServerCacheKeys = exports.SEA_SCHEDULES = exports.SEA_TIMEZONE = exports.SEA_TIMEZONE_OFFSET = exports.ServerStatus = void 0; exports.convertToSEATime = convertToSEATime; exports.getCurrentSEATime = getCurrentSEATime; exports.formatSEADate = formatSEADate; exports.formatSEATime = formatSEATime; exports.getCurrentSEADate = getCurrentSEADate; exports.getCurrentSEATimeString = getCurrentSEATimeString; exports.formatDateForAPI = formatDateForAPI; exports.parseSEADate = parseSEADate; exports.isTodayInSEA = isTodayInSEA; exports.getYesterdaySEA = getYesterdaySEA; exports.getTomorrowSEA = getTomorrowSEA; exports.extractMaintenanceTime = extractMaintenanceTime; exports.isMaintenanceTime = isMaintenanceTime; exports.getNextDailyReset = getNextDailyReset; exports.getTimeUntilDailyReset = getTimeUntilDailyReset; exports.getNextWeeklyReset = getNextWeeklyReset; exports.determineServerStatus = determineServerStatus; exports.isDuringDataUpdate = isDuringDataUpdate; exports.getNextDataUpdate = getNextDataUpdate; exports.estimateWorldPopulation = estimateWorldPopulation; exports.formatSEANumber = formatSEANumber; exports.formatSEAMesos = formatSEAMesos; exports.formatSEAPercentage = formatSEAPercentage; exports.formatNoticeContent = formatNoticeContent; // import { DATE_FORMATS } from '../api/constants'; /** * Server status types */ var ServerStatus; (function (ServerStatus) { ServerStatus["ONLINE"] = "online"; ServerStatus["OFFLINE"] = "offline"; ServerStatus["MAINTENANCE"] = "maintenance"; ServerStatus["UNSTABLE"] = "unstable"; ServerStatus["UNKNOWN"] = "unknown"; })(ServerStatus || (exports.ServerStatus = ServerStatus = {})); /** * SEA timezone offset (UTC+8) */ exports.SEA_TIMEZONE_OFFSET = 8 * 60 * 60 * 1000; // 8 hours in milliseconds /** * SEA timezone identifier */ exports.SEA_TIMEZONE = 'Asia/Singapore'; /** * Convert UTC date to SEA timezone using proper timezone handling */ function convertToSEATime(date) { const inputDate = typeof date === 'string' ? new Date(date) : date; // Use Intl.DateTimeFormat for proper timezone conversion const seaTime = new Intl.DateTimeFormat('en-SG', { timeZone: exports.SEA_TIMEZONE, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false, }).formatToParts(inputDate); const year = parseInt(seaTime.find((p) => p.type === 'year')?.value ?? '2024'); const month = parseInt(seaTime.find((p) => p.type === 'month')?.value ?? '1') - 1; const day = parseInt(seaTime.find((p) => p.type === 'day')?.value ?? '1'); const hour = parseInt(seaTime.find((p) => p.type === 'hour')?.value ?? '0'); const minute = parseInt(seaTime.find((p) => p.type === 'minute')?.value ?? '0'); const second = parseInt(seaTime.find((p) => p.type === 'second')?.value ?? '0'); return new Date(year, month, day, hour, minute, second); } /** * Get current time in SEA timezone */ function getCurrentSEATime() { return convertToSEATime(new Date()); } /** * Format date for SEA region display in DD/MM/YYYY format */ function formatSEADate(date, includeTime = false) { const seaDate = convertToSEATime(date); if (includeTime) { return seaDate.toLocaleString('en-SG', { timeZone: 'Asia/Singapore', day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false, // 24-hour format for SEA }); } // Date only in DD/MM/YYYY format return seaDate.toLocaleDateString('en-SG', { timeZone: 'Asia/Singapore', day: '2-digit', month: '2-digit', year: 'numeric', }); } /** * Format time for SEA region display in 24-hour format */ function formatSEATime(date) { const seaDate = convertToSEATime(date); return seaDate.toLocaleTimeString('en-SG', { timeZone: 'Asia/Singapore', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false, }); } /** * Get current SEA date in DD/MM/YYYY format */ function getCurrentSEADate() { return formatSEADate(new Date()); } /** * Get current SEA time string in HH:MM:SS format */ function getCurrentSEATimeString() { return formatSEATime(new Date()); } /** * Convert date to API format (YYYY-MM-DD) */ function formatDateForAPI(date) { const seaDate = convertToSEATime(date); return seaDate.toISOString().split('T')[0] ?? ''; } /** * Parse SEA date string (DD/MM/YYYY) to Date object */ function parseSEADate(dateString) { const [day, month, year] = dateString.split('/'); return new Date(parseInt(year ?? '2024'), parseInt(month ?? '1') - 1, parseInt(day ?? '1')); } /** * Check if date is today in SEA timezone */ function isTodayInSEA(date) { const inputDate = formatSEADate(date); const today = getCurrentSEADate(); return inputDate === today; } /** * Get yesterday's date in SEA timezone */ function getYesterdaySEA() { const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000); return formatSEADate(yesterday); } /** * Get tomorrow's date in SEA timezone */ function getTomorrowSEA() { const tomorrow = new Date(Date.now() + 24 * 60 * 60 * 1000); return formatSEADate(tomorrow); } /** * Extract maintenance time from content (SEA API does not support notices) * This function is kept for backward compatibility but always returns null */ function extractMaintenanceTime(_content) { // SEA API does not support maintenance notices // Always return null for SEA compatibility return null; } /** * Check if server is likely in maintenance based on time patterns * Updated for SEA server maintenance schedules */ function isMaintenanceTime() { const now = convertToSEATime(new Date()); const hour = now.getHours(); const dayOfWeek = now.getDay(); // MapleStory SEA maintenance schedules: // 1. Weekly maintenance: Wednesday 08:00-12:00 SGT if (dayOfWeek === 3 && hour >= 8 && hour <= 12) { return true; } // 2. Emergency maintenance: Usually early morning 01:00-06:00 SGT if (hour >= 1 && hour <= 6) { return true; } // 3. Patch maintenance: Usually Tuesday night 23:00-03:00 SGT if ((dayOfWeek === 2 && hour >= 23) || (dayOfWeek === 3 && hour <= 3)) { return true; } return false; } /** * Get next daily reset time in SEA timezone (00:00 SGT) */ function getNextDailyReset() { const now = convertToSEATime(new Date()); const nextReset = new Date(now); nextReset.setDate(nextReset.getDate() + 1); nextReset.setHours(0, 0, 0, 0); return nextReset; } /** * Get time until next daily reset in SEA timezone */ function getTimeUntilDailyReset() { const now = convertToSEATime(new Date()); const nextReset = getNextDailyReset(); const diffMs = nextReset.getTime() - now.getTime(); const hours = Math.floor(diffMs / (1000 * 60 * 60)); const minutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60)); const seconds = Math.floor((diffMs % (1000 * 60)) / 1000); return { hours, minutes, seconds, totalMs: diffMs, }; } /** * Get next weekly reset time (Wednesday 00:00 SGT) */ function getNextWeeklyReset() { const now = convertToSEATime(new Date()); const nextWednesday = new Date(now); const dayOfWeek = now.getDay(); const daysUntilWednesday = (3 - dayOfWeek + 7) % 7; if (daysUntilWednesday === 0 && now.getHours() >= 0) { // It's Wednesday, next reset is next week nextWednesday.setDate(nextWednesday.getDate() + 7); } else { nextWednesday.setDate(nextWednesday.getDate() + daysUntilWednesday); } nextWednesday.setHours(0, 0, 0, 0); return nextWednesday; } /** * Determine server status based on various factors */ function determineServerStatus(apiAvailable, maintenanceNotices, errorRate = 0) { // SEA API does not support maintenance notices // Skip notice checking for SEA compatibility // Check if it's typical maintenance time if (isMaintenanceTime()) { return ServerStatus.MAINTENANCE; } // Check API availability and error rates if (!apiAvailable) { return ServerStatus.OFFLINE; } if (errorRate > 0.5) { return ServerStatus.UNSTABLE; } if (errorRate > 0.1) { return ServerStatus.UNSTABLE; } return ServerStatus.ONLINE; } /** * Parse world population level from ranking data */ /** * Check if it's currently during data update time (08:00-09:30 SGT) */ function isDuringDataUpdate() { const now = getCurrentSEATime(); const hour = now.getHours(); const minute = now.getMinutes(); // Data updates happen between 08:00 and 09:30 SGT return hour === 8 || (hour === 9 && minute <= 30); } /** * Get next data update time */ function getNextDataUpdate() { const now = getCurrentSEATime(); const nextUpdate = new Date(now); // If it's before 08:00 today, next update is today at 08:00 if (now.getHours() < 8) { nextUpdate.setHours(8, 0, 0, 0); } else { // Otherwise, next update is tomorrow at 08:00 nextUpdate.setDate(nextUpdate.getDate() + 1); nextUpdate.setHours(8, 0, 0, 0); } return nextUpdate; } function estimateWorldPopulation(rankingData) { if (!rankingData?.ranking?.length) { return 'unknown'; } const totalPlayers = rankingData.ranking.length; if (totalPlayers > 1000) { return 'high'; } else if (totalPlayers > 500) { return 'medium'; } else if (totalPlayers > 100) { return 'low'; } return 'unknown'; } /** * Format content for display (SEA API does not support notices) * This function is kept for backward compatibility */ /** * Format number for SEA region display (using English locale) */ function formatSEANumber(num) { return num.toLocaleString('en-SG'); } /** * Format currency for SEA region (Mesos) */ function formatSEAMesos(amount) { return `${formatSEANumber(amount)} mesos`; } /** * Format percentage for SEA region */ function formatSEAPercentage(value, decimals = 1) { return `${value.toFixed(decimals)}%`; } function formatNoticeContent(content, maxLength = 200) { if (!content) return ''; // Remove HTML tags const cleanContent = content.replace(/<[^>]*>/g, ''); // Normalize whitespace const normalized = cleanContent.replace(/\s+/g, ' ').trim(); // Truncate if too long if (normalized.length <= maxLength) { return normalized; } return normalized.substring(0, maxLength - 3) + '...'; } /** * SEA-specific event and reset schedules */ exports.SEA_SCHEDULES = { // Daily resets at 00:00 SGT DAILY_RESET: { hour: 0, minute: 0 }, // Weekly resets on Wednesday 00:00 SGT WEEKLY_RESET: { day: 3, hour: 0, minute: 0 }, // Maintenance windows MAINTENANCE_WINDOWS: { WEEKLY: { day: 3, startHour: 8, endHour: 12 }, // Wednesday 08:00-12:00 EMERGENCY: { startHour: 1, endHour: 6 }, // 01:00-06:00 any day PATCH: { day: 2, startHour: 23, endHour: 3 }, // Tuesday 23:00 - Wednesday 03:00 }, // Data update times DATA_UPDATES: { CHARACTER: { hour: 8, minute: 0 }, // 08:00 SGT RANKINGS: { hour: 8, minute: 30 }, // 08:30 SGT UNION: { hour: 9, minute: 0 }, // 09:00 SGT }, }; /** * Generate cache keys for server-related data */ exports.ServerCacheKeys = { serverStatus: (worldName) => `server_status:${worldName || 'all'}`, // notices: (noticeType?: string): string => `notices:${noticeType || 'all'}`, // Disabled for SEA API events: () => 'current_events', maintenance: () => 'maintenance_schedule', dailyReset: () => 'daily_reset_time', weeklyReset: () => 'weekly_reset_time', }; //# sourceMappingURL=server-utils.js.map