67faa1a266b3ad2117b753874a278f42bd06f759
El original lo dice en su propio texto ("los objetos disponibles son los mismos
de la tienda") y lo confirma su JS, que usa #store-list y .store-add-button: el
regalo NO tiene catálogo propio, es la tienda con el correo a otro personaje.
Nosotros teníamos una tabla aparte (home_item) con 8 objetos y precios en euros.
Ahora send-gift monta StoreBrowser en modo `gift`: mismo catálogo (3068 ítems,
PD/PV), mismo carrito con cantidades y las cuatro formas de pago. Antes NO tenía
Stripe: solo SumUp, PD y PV.
Dos pasos, como el original: primero #char-select-div (personaje de origen,
destino, confirmación y token) y solo al pulsar "Mostrar Regalos" aparece el
catálogo. Se borran SendGiftForm, /api/gift/checkout y lib/gift (ya no los usa
nadie); la tabla home_item se queda en la BD, sin usar.
Tres cosas que el usuario pidió y que estaban mal:
- El formulario va con `noValidate`: los avisos los damos nosotros en rojo
(#show-gif-response), no el navegador.
- "Mostrar Regalos" ahora valida contra el SERVIDOR (que el personaje de origen
sea tuyo, que el destino exista y que el token sea correcto). Antes elegías
objetos para descubrir al final que el destino no existía.
- BUG REAL: el nombre del destino distinguía mayúsculas. `characters.name` es
`utf8mb4_bin`, así que "innakh" NO encontraba a "Innakh" (comprobado: 0
resultados; con COLLATE, 1). `findCharacterByName` busca sin distinguir y
devuelve el nombre CANÓNICO, que es el que va al comando SOAP.
La validación vive en lib/gift-check y la usan las dos rutas: /api/gift/check (el
botón) y /api/gift/send, que revalida porque el cliente puede saltarse el paso 1.
También se quita del texto "El pago se realiza mediante SumUp": el original no lo
dice y además ya era falso con cuatro formas de pago.
Verificado: innakh / INNAKH / InNaKh resuelven a "Innakh"; token malo y destino
inexistente salen en rojo sin pasar al catálogo. Con 500 PD de saldo de prueba,
2 copias de un ítem de 200 pasan el cobro (deliveryFailed por el worldserver
caído, con su reembolso) y 3 dan insufficientPd: el servidor cobra por copias.
Datos de prueba borrados.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Nova WoW
Portal web (Django) para un servidor de World of Warcraft basado en AzerothCore.
- Python: 3.14
- Framework: Django 6.0
- Base de datos: MySQL (4 bases: la del portal
django_wow+ las de AzerothCoreacore_auth,acore_characters,acore_world)
1. Requisitos
- Python 3.14 y
venv - MySQL/MariaDB accesible
- Librerías de sistema para compilar algunas dependencias:
sudo apt install python3.14-venv python3.14-dev build-essential pkg-config \
default-libmysqlclient-dev libgmp-dev libmpfr-dev libmpc-dev libjpeg-dev zlib1g-dev
2. Puesta en marcha (desarrollo)
git clone https://git.nightspire.gg/Inna/NovaWoW.git
cd NovaWoW
# Entorno virtual
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
# Variables de entorno
cp .env.example .env
# edita .env con tus credenciales reales (ver sección 3)
# Migraciones y arranque
python manage.py migrate
python manage.py createsuperuser # opcional
python manage.py runserver
La app queda en http://127.0.0.1:8000
3. Configuración (.env)
Toda la configuración sensible se lee de variables de entorno mediante
python-dotenv. Copia .env.example
a .env y rellena los valores. El .env no se versiona.
| Variable | Descripción |
|---|---|
DJANGO_SECRET_KEY |
Clave secreta de Django. Genera una nueva (ver abajo). |
DJANGO_DEBUG |
True en desarrollo, False en producción. |
DB_USER / DB_PASSWORD |
Credenciales MySQL (compartidas por las 4 BBDD). |
DB_HOST / DB_PORT |
Host y puerto de MySQL. |
DB_NAME_DEFAULT |
BD del portal (por defecto django_wow). |
DB_NAME_AUTH / DB_NAME_CHARACTERS / DB_NAME_WORLD |
BBDD de AzerothCore. |
AC_SOAP_* |
Conexión SOAP a AzerothCore (crear cuentas, etc.). |
SUMUP_* / STRIPE_* |
Pasarelas de pago. |
EMAIL_HOST_USER / EMAIL_HOST_PASSWORD |
SMTP de Gmail (App Password). |
Generar una SECRET_KEY nueva:
python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
4. Producción
# Recopilar estáticos
python manage.py collectstatic --noinput
# Servir con gunicorn (4 workers)
gunicorn novawow.wsgi:application --bind 0.0.0.0:8000 --workers 4
Recomendaciones:
DJANGO_DEBUG=Falsey unaDJANGO_SECRET_KEYpropia y secreta.- Poner Nginx delante como proxy inverso y para servir
staticfiles/. - Revisar
ALLOWED_HOSTSyCSRF_TRUSTED_ORIGINSennovawow/settings.py.
5. Docker
Alternativamente, se puede levantar todo con Docker (web + MySQL):
cp .env.example .env # ajusta los secretos (no las variables DB_*, las fija compose)
docker compose up --build
- La web queda en http://127.0.0.1:8000
- El servicio
dbcrea automáticamente las 4 bases de datos. - El
entrypointespera a MySQL, aplica migraciones y recopila estáticos antes de arrancar gunicorn.
Ver docker-compose.yml y Dockerfile para los detalles.
6. Notas de seguridad
- Los secretos que estuvieron hardcodeados en el historial de git deben rotarse (contraseña MySQL/SOAP, App Password de Gmail, claves de Stripe/SumUp).
- Nunca subas el archivo
.enval repositorio.
Description
Languages
Macaulay2
97.3%
TypeScript
2.3%
CSS
0.3%