Changelogs
Anuncios de Monetag, apagados por defecto y detrás del consentimiento
16 de julio de 2026 a las 11:15adevopg · 67656fa
Se añade la integración del script de Monetag (MultiTag: popunder + push + in-page push + vignette) como alternativa a AdSense para monetizar sin depender de que Google apruebe el sitio. Tres interruptores (ver components/Monetag.tsx): 1. `MONETAG_SRC` + `MONETAG_ZONE` en el .env (no versionadas, documentadas en el README). Cualquiera de las dos vacía = no se carga nada. Se leen en el servidor y se pasan como props, así que encender/apagar es tocar el .env + reiniciar, SIN rebuild. Ahora mismo van vacías: la integración queda instalada pero inerte hasta que se pegue la zona del panel de Monetag. 2. El filtro común de publicidad, extraído a lib/ads.ts (`shouldServeAds`): fuera para admins y para quien sea rango 2+ o haya pagado alguna vez. Antes esta lógica vivía dentro de AdSense.tsx; ahora la comparten la etiqueta de AdSense y el script de Monetag desde un único sitio, para que no se puedan desincronizar. 3. El consentimiento «Marketing» del banner, en components/MonetagScript.tsx (cliente). A diferencia de la etiqueta de AdSense, MultiTag escribe cookies y pide permisos, así que NO puede cargarse sin aceptar la categoría. Mismo patrón que Analytics.tsx: useConsent reacciona en caliente, arranca en false. El push de MultiTag necesitará además un sw.js servido desde la raíz del dominio (public/sw.js, descargado del panel). Sin él, el resto de formatos funcionan igual. Verificado: con las variables vacías la web queda idéntica (ni script de Monetag ni cambios) y la etiqueta de AdSense sigue intacta. Con una zona de prueba, el filtro de servidor deja pasar a anónimos y rango 1 sin pagos, y corta a los admins. Sin consentimiento no se inyecta ningún <script> (la zona solo viaja como prop inerte en el payload de React).
Guía de Mac: CrossOver oficial en vez de una web de software pirateado
16 de julio de 2026 a las 07:11adevopg · 9721592
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.
Etiqueta de verificación de AdSense, con interruptor y sin anuncios para quien paga
16 de julio de 2026 a las 06:57adevopg · 3361f2e
Se añade `<meta name="google-adsense-account">` al <head> de todas las páginas, que es lo que pide Google para verificar la propiedad del sitio. OJO: esto NO muestra anuncios ni carga adsbygoogle.js todavía; solo permite que Google confirme que el dominio es nuestro y arranque la revisión. TRES interruptores (ver components/AdSense.tsx): 1. `ADSENSE_CLIENT_ID` en el .env (no versionado). Vacío o sin poner = no se emite nada. Documentada en el README. NO lleva prefijo NEXT_PUBLIC_ a propósito: la etiqueta se pinta en el servidor, así que no hace falta exponerla al bundle ni rebuildear para activarla/desactivarla, al revés que NEXT_PUBLIC_GA_ID. 2. Admin (ADMIN_EMAILS o gmlevel de AzerothCore): sin etiqueta, para que la navegación del staff no cuente como tráfico con anuncios. 3. Rango de la cuenta (ns-ranks) Y pagos: solo ve anuncios el rango 1 (Newbie, el de por defecto) que ADEMÁS nunca ha pagado. Los dos cortes del punto 3 son distintos a propósito y no basta con mirar el rango: el mínimo de SumUp son 0,20 €, que a 100 PD/unidad son 20 PD, y eso sigue siendo rango 1. Mirando solo el rango, quien pagara el mínimo seguiría viendo anuncios, que es justo lo contrario de lo que queremos. Para no duplicar el SQL, las consultas de saldo y de total donado salen de getAccountDashboard a dos helpers (`getPoints`, `getDonatedPD`) que reutiliza el nuevo `getAccountRankInfo`, con las dos consultas mínimas en vez del panel entero (personajes, baneos, correo…). El criterio de rango es el mismo que ya usaba /my-account: el máximo entre lo donado y el saldo actual. Verificado contra la web real: anónimo y rango 1 sin pagos SÍ reciben la etiqueta; rango 1 con 99 PD también; 100 PD de saldo (rango 2) no; rango 1 tras pagar 0,20 € tampoco; admin tampoco; y con la variable vacía no la recibe nadie. Los dos últimos casos no existían en la BD, así que se probaron con datos temporales en la cuenta 14 (fila en stripelog y en api_points), ya borrados. /my-account sigue pintando el rango correcto tras mover las consultas.
Google Analytics 4, con interruptor y respetando el consentimiento
15 de julio de 2026 a las 19:49adevopg · 94f9731
Se añade GA4 (gtag.js) con el componente oficial `@next/third-parties`, que es lo que recomienda el doc de Next 16 y carga el mismo gtag pero tras la hidratación. DOS interruptores: 1. `NEXT_PUBLIC_GA_ID` en el .env (no versionado). Vacío o sin poner = no se carga nada. Documentada en el README. 2. El consentimiento del visitante. El sitio YA tenía un banner con la categoría «Analíticas» que se puede rechazar: soltar gtag en el <head> lo habría convertido en mentira, y con visitantes en la UE, en un problema legal. Para lo segundo se expone `useConsent(categoría)` desde CookieConsent, que además reacciona en caliente: `writeConsent`/`revokeConsent` ya disparaban el evento `ns:consentchange`, así que la analítica entra en cuanto se acepta y desaparece si se revoca, sin recargar. Arranca en `false` a propósito: hasta confirmar el consentimiento no se carga nada. Verificado en el build: sin consentimiento no hay ni rastro de googletagmanager en el HTML, y la condición compilada es `id && consent ? <GoogleAnalytics/> : null`.
Avisar al correo antiguo cuando el cambio de correo se completa
15 de julio de 2026 a las 19:32adevopg · fbc17f2
`oldEmailNotificationHtml` estaba portada del Django original pero NO la llamaba nadie: `confirmNewEmail` cambiaba el correo de la cuenta y al antiguo no le llegaba nada. Importa porque al entrar se usa el correo: quien secuestrara una sesión podía cambiarlo y el dueño se quedaba sin cuenta en silencio, sin ningún aviso en ninguna parte. Se envía DESPUÉS de que el cambio haya cuajado (si el UPDATE falla, no hay nada que avisar) y sin enlaces: solo informa, y dice a quién contactar. `sendMail` nunca lanza (devuelve false), así que un fallo de correo no puede tumbar un cambio ya hecho. Verificado ejecutando confirmNewEmail() contra la BD con el SMTP interceptado y cuentas de usar y tirar: 1 correo al antiguo (antes 0), la cuenta cambia, y las filas de prueba quedan borradas.


