Files
NightSpire/web-next/lib/characters.ts
T
Inna eaae16e33a web-next: change-race/faction/level-up/gold por SumUp + rastreador de misiones
- /change-race-character (3€), /change-faction-character (5€, valida condiciones:
  sin hermandad/correo/subastas/capitán-arena y oro <= cap por nivel),
  /level-up-character (10€), /gold-character (oro por correo SOAP). Cada uno borra
  su ruta antigua y actualiza el link del panel.
- SumUp: hook precheck en PaidServiceConfig (condiciones cambio de facción);
  columna home_stripelog.metadata para campos extra (gold_amount).
- /quest-character: rastreador de estado de misiones/cadenas (clase, Hijos de
  Hodir, misión por ID) en personaje offline; cooldowns por categoría, Turnstile,
  IDs de misión verificados en wotlkdb 3.3.5a. Tabla home_questsearchhistory.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 12:39:28 +00:00

46 lines
1.6 KiB
TypeScript

import type { RowDataPacket } from 'mysql2'
import { db, DB } from './db'
import { getClassCss } from './character-info'
export interface GameCharacter {
name: string
online: boolean
level: number
classCss: string // clase CSS de color por clase (priest, warrior…), para el <select>
}
/** Personajes de una cuenta de juego (acore_characters). Vacío si no está poblada. */
export async function getGameCharacters(accountId: number): Promise<GameCharacter[]> {
try {
const [rows] = await db(DB.characters).query<RowDataPacket[]>(
'SELECT name, online, class, level FROM characters WHERE account = ?',
[accountId],
)
return rows.map((r) => ({ name: r.name, online: r.online === 1, level: Number(r.level), classCss: getClassCss(r.class) }))
} catch {
return []
}
}
/** Id de la cuenta dueña de un personaje por su nombre (único), o null. */
export async function getAccountIdByCharacterName(name: string): Promise<number | null> {
const trimmed = name.trim()
if (!trimmed) return null
try {
const [rows] = await db(DB.characters).query<RowDataPacket[]>(
'SELECT account FROM characters WHERE name = ? LIMIT 1',
[trimmed],
)
return rows[0] ? Number(rows[0].account) : null
} catch {
return null
}
}
/** True si el personaje pertenece a la cuenta y está desconectado. */
export async function characterIsOfflineAndOwned(accountId: number, name: string): Promise<boolean> {
const chars = await getGameCharacters(accountId)
const c = chars.find((ch) => ch.name === name)
return Boolean(c && !c.online)
}