From 24bd28fccadedb660e16a9e74708b13cbf5bb768 Mon Sep 17 00:00:00 2001 From: adevopg Date: Fri, 17 Jul 2026 07:57:41 +0000 Subject: [PATCH] Foro: autor con personaje aleatorio de la cuenta MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - El nombre del autor muestra un personaje ALEATORIO de la cuenta (no la id). - Nombre con en dorado (oculto si el personaje no tiene guild). - Avatar = imagen de raza del personaje (raza+género). - Cajas nuevas: puntos de logros, nivel y clase (con su color de clase). Co-Authored-By: Claude Opus 4.8 --- .../[locale]/forum/topic/[topicId]/page.tsx | 30 +++++- web-next/app/[locale]/layout.tsx | 5 +- web-next/app/forum.css | 3 + web-next/components/AdSense.tsx | 22 +++-- web-next/components/AdSenseScript.tsx | 32 +++++++ web-next/lib/forum.ts | 94 +++++++++++++++---- web-next/messages/en.json | 3 +- web-next/messages/es.json | 3 +- wmmv-cache/spellicons/12163.txt | 1 + wmmv-cache/spellicons/12281.txt | 1 + wmmv-cache/spellicons/12282.txt | 1 + wmmv-cache/spellicons/12284.txt | 1 + wmmv-cache/spellicons/12285.txt | 1 + wmmv-cache/spellicons/12286.txt | 1 + wmmv-cache/spellicons/12287.txt | 1 + wmmv-cache/spellicons/12289.txt | 1 + wmmv-cache/spellicons/12290.txt | 1 + wmmv-cache/spellicons/12292.txt | 1 + wmmv-cache/spellicons/12294.txt | 1 + wmmv-cache/spellicons/12295.txt | 1 + wmmv-cache/spellicons/12296.txt | 1 + wmmv-cache/spellicons/12297.txt | 1 + wmmv-cache/spellicons/12298.txt | 1 + wmmv-cache/spellicons/12299.txt | 1 + wmmv-cache/spellicons/12300.txt | 1 + wmmv-cache/spellicons/12301.txt | 1 + wmmv-cache/spellicons/12308.txt | 1 + wmmv-cache/spellicons/12311.txt | 1 + wmmv-cache/spellicons/12312.txt | 1 + wmmv-cache/spellicons/12313.txt | 1 + wmmv-cache/spellicons/12317.txt | 1 + wmmv-cache/spellicons/12318.txt | 1 + wmmv-cache/spellicons/12319.txt | 1 + wmmv-cache/spellicons/12320.txt | 1 + wmmv-cache/spellicons/12321.txt | 1 + wmmv-cache/spellicons/12322.txt | 1 + wmmv-cache/spellicons/12323.txt | 1 + wmmv-cache/spellicons/12324.txt | 1 + wmmv-cache/spellicons/12328.txt | 1 + wmmv-cache/spellicons/12329.txt | 1 + wmmv-cache/spellicons/12700.txt | 1 + wmmv-cache/spellicons/12797.txt | 1 + wmmv-cache/spellicons/12809.txt | 1 + wmmv-cache/spellicons/12834.txt | 1 + wmmv-cache/spellicons/12862.txt | 1 + wmmv-cache/spellicons/12975.txt | 1 + wmmv-cache/spellicons/16462.txt | 1 + wmmv-cache/spellicons/16487.txt | 1 + wmmv-cache/spellicons/16493.txt | 1 + wmmv-cache/spellicons/16538.txt | 1 + wmmv-cache/spellicons/20243.txt | 1 + wmmv-cache/spellicons/20500.txt | 1 + wmmv-cache/spellicons/20502.txt | 1 + wmmv-cache/spellicons/20504.txt | 1 + wmmv-cache/spellicons/23584.txt | 1 + wmmv-cache/spellicons/23881.txt | 1 + wmmv-cache/spellicons/29140.txt | 1 + wmmv-cache/spellicons/29590.txt | 1 + wmmv-cache/spellicons/29593.txt | 1 + wmmv-cache/spellicons/29598.txt | 1 + wmmv-cache/spellicons/29623.txt | 1 + wmmv-cache/spellicons/29721.txt | 1 + wmmv-cache/spellicons/29723.txt | 1 + wmmv-cache/spellicons/29759.txt | 1 + wmmv-cache/spellicons/29787.txt | 1 + wmmv-cache/spellicons/29801.txt | 1 + wmmv-cache/spellicons/29834.txt | 1 + wmmv-cache/spellicons/29836.txt | 1 + wmmv-cache/spellicons/29888.txt | 1 + wmmv-cache/spellicons/35446.txt | 1 + wmmv-cache/spellicons/46854.txt | 1 + wmmv-cache/spellicons/46859.txt | 1 + wmmv-cache/spellicons/46865.txt | 1 + wmmv-cache/spellicons/46867.txt | 1 + wmmv-cache/spellicons/46908.txt | 1 + wmmv-cache/spellicons/46910.txt | 1 + wmmv-cache/spellicons/46913.txt | 1 + wmmv-cache/spellicons/46917.txt | 1 + wmmv-cache/spellicons/46924.txt | 1 + wmmv-cache/spellicons/46945.txt | 1 + wmmv-cache/spellicons/46951.txt | 1 + wmmv-cache/spellicons/46968.txt | 1 + wmmv-cache/spellicons/47294.txt | 1 + wmmv-cache/spellicons/50685.txt | 1 + wmmv-cache/spellicons/50720.txt | 1 + wmmv-cache/spellicons/56636.txt | 1 + wmmv-cache/spellicons/56927.txt | 1 + wmmv-cache/spellicons/57499.txt | 1 + wmmv-cache/spellicons/58872.txt | 1 + wmmv-cache/spellicons/59088.txt | 1 + wmmv-cache/spellicons/60970.txt | 1 + wmmv-cache/spellicons/61216.txt | 1 + wmmv-cache/spellicons/64976.txt | 1 + 93 files changed, 249 insertions(+), 28 deletions(-) create mode 100644 web-next/components/AdSenseScript.tsx create mode 100644 wmmv-cache/spellicons/12163.txt create mode 100644 wmmv-cache/spellicons/12281.txt create mode 100644 wmmv-cache/spellicons/12282.txt create mode 100644 wmmv-cache/spellicons/12284.txt create mode 100644 wmmv-cache/spellicons/12285.txt create mode 100644 wmmv-cache/spellicons/12286.txt create mode 100644 wmmv-cache/spellicons/12287.txt create mode 100644 wmmv-cache/spellicons/12289.txt create mode 100644 wmmv-cache/spellicons/12290.txt create mode 100644 wmmv-cache/spellicons/12292.txt create mode 100644 wmmv-cache/spellicons/12294.txt create mode 100644 wmmv-cache/spellicons/12295.txt create mode 100644 wmmv-cache/spellicons/12296.txt create mode 100644 wmmv-cache/spellicons/12297.txt create mode 100644 wmmv-cache/spellicons/12298.txt create mode 100644 wmmv-cache/spellicons/12299.txt create mode 100644 wmmv-cache/spellicons/12300.txt create mode 100644 wmmv-cache/spellicons/12301.txt create mode 100644 wmmv-cache/spellicons/12308.txt create mode 100644 wmmv-cache/spellicons/12311.txt create mode 100644 wmmv-cache/spellicons/12312.txt create mode 100644 wmmv-cache/spellicons/12313.txt create mode 100644 wmmv-cache/spellicons/12317.txt create mode 100644 wmmv-cache/spellicons/12318.txt create mode 100644 wmmv-cache/spellicons/12319.txt create mode 100644 wmmv-cache/spellicons/12320.txt create mode 100644 wmmv-cache/spellicons/12321.txt create mode 100644 wmmv-cache/spellicons/12322.txt create mode 100644 wmmv-cache/spellicons/12323.txt create mode 100644 wmmv-cache/spellicons/12324.txt create mode 100644 wmmv-cache/spellicons/12328.txt create mode 100644 wmmv-cache/spellicons/12329.txt create mode 100644 wmmv-cache/spellicons/12700.txt create mode 100644 wmmv-cache/spellicons/12797.txt create mode 100644 wmmv-cache/spellicons/12809.txt create mode 100644 wmmv-cache/spellicons/12834.txt create mode 100644 wmmv-cache/spellicons/12862.txt create mode 100644 wmmv-cache/spellicons/12975.txt create mode 100644 wmmv-cache/spellicons/16462.txt create mode 100644 wmmv-cache/spellicons/16487.txt create mode 100644 wmmv-cache/spellicons/16493.txt create mode 100644 wmmv-cache/spellicons/16538.txt create mode 100644 wmmv-cache/spellicons/20243.txt create mode 100644 wmmv-cache/spellicons/20500.txt create mode 100644 wmmv-cache/spellicons/20502.txt create mode 100644 wmmv-cache/spellicons/20504.txt create mode 100644 wmmv-cache/spellicons/23584.txt create mode 100644 wmmv-cache/spellicons/23881.txt create mode 100644 wmmv-cache/spellicons/29140.txt create mode 100644 wmmv-cache/spellicons/29590.txt create mode 100644 wmmv-cache/spellicons/29593.txt create mode 100644 wmmv-cache/spellicons/29598.txt create mode 100644 wmmv-cache/spellicons/29623.txt create mode 100644 wmmv-cache/spellicons/29721.txt create mode 100644 wmmv-cache/spellicons/29723.txt create mode 100644 wmmv-cache/spellicons/29759.txt create mode 100644 wmmv-cache/spellicons/29787.txt create mode 100644 wmmv-cache/spellicons/29801.txt create mode 100644 wmmv-cache/spellicons/29834.txt create mode 100644 wmmv-cache/spellicons/29836.txt create mode 100644 wmmv-cache/spellicons/29888.txt create mode 100644 wmmv-cache/spellicons/35446.txt create mode 100644 wmmv-cache/spellicons/46854.txt create mode 100644 wmmv-cache/spellicons/46859.txt create mode 100644 wmmv-cache/spellicons/46865.txt create mode 100644 wmmv-cache/spellicons/46867.txt create mode 100644 wmmv-cache/spellicons/46908.txt create mode 100644 wmmv-cache/spellicons/46910.txt create mode 100644 wmmv-cache/spellicons/46913.txt create mode 100644 wmmv-cache/spellicons/46917.txt create mode 100644 wmmv-cache/spellicons/46924.txt create mode 100644 wmmv-cache/spellicons/46945.txt create mode 100644 wmmv-cache/spellicons/46951.txt create mode 100644 wmmv-cache/spellicons/46968.txt create mode 100644 wmmv-cache/spellicons/47294.txt create mode 100644 wmmv-cache/spellicons/50685.txt create mode 100644 wmmv-cache/spellicons/50720.txt create mode 100644 wmmv-cache/spellicons/56636.txt create mode 100644 wmmv-cache/spellicons/56927.txt create mode 100644 wmmv-cache/spellicons/57499.txt create mode 100644 wmmv-cache/spellicons/58872.txt create mode 100644 wmmv-cache/spellicons/59088.txt create mode 100644 wmmv-cache/spellicons/60970.txt create mode 100644 wmmv-cache/spellicons/61216.txt create mode 100644 wmmv-cache/spellicons/64976.txt diff --git a/web-next/app/[locale]/forum/topic/[topicId]/page.tsx b/web-next/app/[locale]/forum/topic/[topicId]/page.tsx index 39951a7..523f76f 100644 --- a/web-next/app/[locale]/forum/topic/[topicId]/page.tsx +++ b/web-next/app/[locale]/forum/topic/[topicId]/page.tsx @@ -11,6 +11,7 @@ import { import { formatForumDate } from '@/lib/forum-format' import { localizeWowheadLinks } from '@/lib/forum-wowhead' import { getSession } from '@/lib/session' +import { className, classColor } from '@/lib/wow-data' import { forumIsModerator, canEditPost } from '@/lib/forum-perm' import { PageShell } from '@/components/PageShell' import { ForumBreadcrumb } from '@/components/ForumBreadcrumb' @@ -105,7 +106,10 @@ export default async function TopicPage({
- {author?.name ?? `#${post.poster}`} + + {author?.charName ?? author?.name ?? `#${post.poster}`} + {author?.guildName ? <{author.guildName}> : null} +
{formatForumDate(author?.joindate ?? null, locale) || '—'}
+ {author?.charName ? ( + <> +

+
+ +
+
{(author.achPoints ?? 0).toLocaleString(locale)}
+

+

+
+ +
+
+ {t('level')} {author.level} +
+

+

+
+ +
+
{className(author.classId, locale)}
+

+ + ) : null}

diff --git a/web-next/app/[locale]/layout.tsx b/web-next/app/[locale]/layout.tsx index 28105bd..5c9455f 100644 --- a/web-next/app/[locale]/layout.tsx +++ b/web-next/app/[locale]/layout.tsx @@ -54,8 +54,9 @@ export default async function LocaleLayout({ return ( - {/* Verificación de la cuenta de Google AdSense: solo si hay ADSENSE_CLIENT_ID - y el visitante no es admin. Ver components/AdSense.tsx. */} + {/* Google AdSense (meta de verificación + adsbygoogle.js): solo si hay + ADSENSE_CLIENT_ID, el visitante no es admin ni ha pagado, y —para el + script— ha aceptado «Marketing». Ver components/AdSense.tsx. */} {/* Iconos del sitio (idénticos a la web Django) */} diff --git a/web-next/app/forum.css b/web-next/app/forum.css index 852e0ef..5120585 100644 --- a/web-next/app/forum.css +++ b/web-next/app/forum.css @@ -295,3 +295,6 @@ a.nice_button:focus { .topic_post .left_side { flex-basis: 100%; } .topic_post .left_side .user_avatar { width: 56px; height: 56px; } } + +/* Nombre de hermandad junto al personaje en el foro */ +.username_guild { color: #c8a24c; font-weight: 400; font-size: .8em; } diff --git a/web-next/components/AdSense.tsx b/web-next/components/AdSense.tsx index 7bddbaf..4e36512 100644 --- a/web-next/components/AdSense.tsx +++ b/web-next/components/AdSense.tsx @@ -1,7 +1,11 @@ import { shouldServeAds } from '@/lib/ads' +import { AdSenseScript } from './AdSenseScript' /** - * Etiqueta de verificación de Google AdSense, con DOS interruptores: + * Google AdSense: etiqueta de verificación de la cuenta + script de anuncios + * («Auto ads»: se pega en todas las páginas y Google decide dónde colocarlos). + * + * TRES interruptores: * * 1. `ADSENSE_CLIENT_ID` en el .env. Vacío o sin poner = no se emite nada. Es el * interruptor del administrador. No lleva prefijo NEXT_PUBLIC_ a propósito: @@ -10,10 +14,11 @@ import { shouldServeAds } from '@/lib/ads' * rebuildear para activarlo o desactivarlo. * 2. El filtro común de publicidad (`shouldServeAds`, ver lib/ads.ts): fuera para * admins y para quien sea rango 2+ o haya pagado alguna vez. - * - * Ojo: esto es solo la etiqueta de verificación de la cuenta, no carga adsbygoogle.js - * ni escribe cookies, por eso no pasa por el banner de consentimiento (el script de - * anuncios sí lo hace, ver components/Monetag.tsx). + * 3. El consentimiento «Marketing» del visitante, pero SOLO para el script, en + * (cliente). La se queda fuera del banner a propósito: + * es un identificador estático de la cuenta, no carga nada ni escribe cookies, + * y Google la quiere presente para poder verificar el sitio aunque el visitante + * rechace los anuncios. */ export async function AdSense() { const client = process.env.ADSENSE_CLIENT_ID @@ -21,5 +26,10 @@ export async function AdSense() { if (!(await shouldServeAds())) return null - return + return ( + <> + + + + ) } diff --git a/web-next/components/AdSenseScript.tsx b/web-next/components/AdSenseScript.tsx new file mode 100644 index 0000000..23d222c --- /dev/null +++ b/web-next/components/AdSenseScript.tsx @@ -0,0 +1,32 @@ +'use client' + +import Script from 'next/script' +import { useConsent } from './CookieConsent' + +/** + * Parte de cliente de AdSense: el script que de verdad pinta los anuncios + * (adsbygoogle.js, «Auto ads»). Existe separado de solo para mirar el + * consentimiento, que vive en el navegador (cookie `ns_cookie_consent` + evento + * `ns:consentchange`). + * + * A diferencia de la etiqueta de verificación, esto SÍ pasa por el banner: + * adsbygoogle.js escribe cookies de personalización y perfila al visitante, así que + * cargarlo sin mirar la categoría «Marketing» convertiría el banner en mentira y, con + * visitantes en la UE, en un problema legal. Mismo criterio que . + * + * `useConsent` reacciona en caliente: entra en cuanto se acepta y deja de renderizarse + * si se revoca, sin recargar. Arranca en `false`, así que hasta confirmar el + * consentimiento no se carga nada. + */ +export function AdSenseScript({ client }: { client: string }) { + const consent = useConsent('marketing') + if (!consent) return null + + return ( +