Files
NightSpire/web-next/components/ClientDownload.tsx
T
Inna 972159229a Guía de Mac: CrossOver oficial en vez de una web de software pirateado
El paso 1 de la guía de macOS enlazaba a insmac.org, un repositorio de software de
pago pirateado. Ahora apunta a la web oficial de CodeWeavers, que además tiene
prueba gratuita.

Se cambia solo el destino del enlace: el texto de macStep1 ya era neutro («Descarga
e instala CrossOver»), así que no hay que tocar es.json ni en.json.

Motivo, por orden de importancia: metíamos a nuestros propios jugadores en un sitio
de warez con el riesgo de malware que eso supone, y de paso era una infracción de
copyright en una web que quiere servir anuncios de AdSense.

Verificado en producción: el chunk servido contiene codeweavers.com/crossover y no
queda ninguna referencia a insmac en el repo ni en el bundle.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 07:11:52 +00:00

168 lines
7.7 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client'
import { useRef, useState } from 'react'
import { useTranslations } from 'next-intl'
// Lista de trackers común a todos los magnet (idéntica en el original).
const TRACKERS =
'&tr=http%3A%2F%2F184.105.151.164%3A6969%2Fannounce&tr=http%3A%2F%2F184.105.151.164%3A6969%2Fannounce&tr=http%3A%2F%2F182.150.53.61%3A8080%2Fannounce&tr=http%3A%2F%2F62.210.202.61%3A80%2Fannounce&tr=http%3A%2F%2F78.30.254.12%3A2710%2Fannounce&tr=http%3A%2F%2F91.207.136.85%3A80%2Fannounce&tr=http%3A%2F%2F176.113.71.19%3A6961%2Fannounce&tr=http%3A%2F%2F34.92.10.197%3A6789%2Fannounce&tr=http%3A%2F%2F80.209.252.132%3A1337%2Fannounce&tr=udp%3A%2F%2F62.138.0.158%3A6969%2Fannounce&tr=udp%3A%2F%2F188.241.58.209%3A6969%2Fannounce&tr=udp%3A%2F%2F93.158.213.92%3A1337%2Fannounce&tr=udp%3A%2F%2F62.210.97.59%3A1337%2Fannounce&tr=udp%3A%2F%2F151.80.120.112%3A2710%2Fannounce&tr=udp%3A%2F%2F80.209.252.132%3A1337%2Fannounce'
// Hash btih por idioma (Windows y Mac OS Catalina comparten el mismo torrent).
const BTIH: Record<string, string> = {
wotlkeses: 'AIV765TUMAIZSGLSVGN7MRYASNJW6UPD',
wotlkesmx: 'EL64Q3QUXM42PBGJC4TUHNAH2UUTAJXB',
wotlkenus: 'XAJ4DBISLXFEV2N74IIUZLA5XXVGVRG7',
wotlkengb: '7U3ATWR7YN2IR63L53EFPPHZ4SI4RZKX',
}
function magnetFor(lang: string): string {
return `magnet:?xt=urn:btih:${BTIH[lang]}${TRACKERS}`
}
const LANG_INFO_KEY: Record<string, string> = {
wotlkeses: 'clientDownload.langEses',
wotlkesmx: 'clientDownload.langEsmx',
wotlkenus: 'clientDownload.langEnus',
wotlkengb: 'clientDownload.langEngb',
}
export function ClientDownload() {
const t = useTranslations('UI')
const [lang, setLang] = useState('')
const [os, setOs] = useState('')
const [error, setError] = useState(false)
const timer = useRef<ReturnType<typeof setTimeout> | null>(null)
function handleSubmit(e: React.FormEvent) {
e.preventDefault()
if (!lang || !os) {
setError(true)
if (timer.current) clearTimeout(timer.current)
timer.current = setTimeout(() => setError(false), 5000)
return
}
window.location.href = magnetFor(lang)
}
return (
<>
<div className="box-content">
<div className="title-box-content" id="torrent">
<h2>{t('clientDownload.torrentTitle')}</h2>
</div>
<div className="body-box-content justified">
<p><span>{t('clientDownload.infoLabel')}</span></p>
<p>{t('clientDownload.info1')}</p>
<p>{t('clientDownload.info2')}</p>
<p>{t('clientDownload.info3')}</p>
<br />
<p><span>{t('clientDownload.requirementsLabel')}</span></p>
<p>{t('clientDownload.requirementsText')}</p>
<ul>
<li><a href="https://www.qbittorrent.org/download.php" target="_blank" rel="noopener noreferrer">qBittorrent</a></li>
<li><a href="https://www.winrar.es/descargas" target="_blank" rel="noopener noreferrer">WinRAR</a></li>
</ul>
<p>{t('clientDownload.popupNote')}</p>
<br />
<p><span>{t('clientDownload.stepByStep')}</span></p>
<p>{t.rich('clientDownload.stepOptional', { winrar: (c) => <a href="https://www.winrar.es/descargas" target="_blank" rel="noopener noreferrer">{c}</a> })}</p>
<p>{t.rich('clientDownload.step1', { qbit: (c) => <a href="https://www.qbittorrent.org/download.php" target="_blank" rel="noopener noreferrer">{c}</a> })}</p>
<p>{t('clientDownload.step2')}</p>
<p>{t('clientDownload.step3')}</p>
<p>{t('clientDownload.step4')}</p>
<p>{t('clientDownload.step5')}</p>
<p>{t('clientDownload.step6')}</p>
<p>{t('clientDownload.step7')}</p>
<p>{t('clientDownload.step8')}</p>
<p>{t('clientDownload.step9')}</p>
<p>{t('clientDownload.step10')}</p>
<p>{t('clientDownload.step11')}</p>
<p>{t('clientDownload.step12')}</p>
<p>{t('clientDownload.step13')}</p>
<p>{t('clientDownload.step14')}</p>
<p>{t('clientDownload.step15')}</p>
<br />
<hr />
<br />
<div className="centered">
<form name="ns-client-dowload" id="ns-client-download" autoComplete="off" onSubmit={handleSubmit}>
<p><span>{t('clientDownload.languageLabel')}</span></p>
<br />
<select
name="game-language"
id="game-language"
className="game-download-select"
value={lang}
onChange={(e) => { setLang(e.target.value); setOs(''); }}
>
<option value="" disabled>{t('clientDownload.chooseLanguage')}</option>
<option value="wotlkeses">{t('clientDownload.clientEses')}</option>
<option value="wotlkesmx">{t('clientDownload.clientEsmx')}</option>
<option value="wotlkenus">{t('clientDownload.clientEnus')}</option>
<option value="wotlkengb">{t('clientDownload.clientEngb')}</option>
</select>
{lang && (
<div id="select-op">
<br />
<p id="game-info">{lang ? t(LANG_INFO_KEY[lang]) :' '}</p>
<br />
<p><span>{t('clientDownload.osLabel')}</span></p>
<br />
<select
name="operating-system"
id="operating-system"
className="game-download-select"
value={os}
onChange={(e) => setOs(e.target.value)}
>
<option value="" disabled>{t('clientDownload.chooseOs')}</option>
<option value="windows">{t('clientDownload.windows')}</option>
<option value="macosc">{t('clientDownload.macCatalina')}</option>
</select>
<br />
<button type="submit" className="g-download-button" id="download-c-button">{t('clientDownload.downloadBtn')}</button>
</div>
)}
</form>
<br />
<hr />
<div id="error-message" className="red-form-response">
{error ? t('clientDownload.errorChoose') : ''}
</div>
<br />
</div>
</div>
{os === 'macosc' && (
<div id="op-info" className="box-content">
<div className="title-box-content">
<h2>{t('clientDownload.macGuideTitle')}</h2>
</div>
<div className="body-box-content">
<p>{t('clientDownload.mac1')}</p>
<p>{t('clientDownload.mac2')}</p>
<br />
<span>{t('clientDownload.macInstructions')}</span>
{/* CrossOver oficial de CodeWeavers (tiene prueba gratuita). Antes esto
apuntaba a insmac.org, un repositorio de software de pago pirateado:
riesgo de malware para el jugador y, de paso, infracción de copyright
en una web que quiere servir anuncios. */}
<p>{t.rich('clientDownload.macStep1', { crossover: (c) => <a href="https://www.codeweavers.com/crossover" target="_blank" rel="noopener noreferrer">{c}</a> })}</p>
<p>{t('clientDownload.macStep2')}</p>
<p>{t('clientDownload.macStep3')}</p>
<p>{t('clientDownload.macStep4')}</p>
<p>{t('clientDownload.macStep5')}</p>
<p>{t('clientDownload.macStep6')}</p>
<p>{t('clientDownload.macStep7')}</p>
<p>{t('clientDownload.macStep8')}</p>
<p>{t('clientDownload.macStep9')}</p>
<p>{t('clientDownload.macStep10')}</p>
<p>{t('clientDownload.macStep11')}</p>
</div>
</div>
)}
</div>
</>
)
}