68cfe7594b
restore_items_view ahora responde JSON cuando la petición es AJAX (X-Requested-With):
GET con character_name -> {items}; POST recover_id -> {success, message}. Se conserva
el flujo legacy (redirect+messages) para no-AJAX. RestoreItemsForm.tsx: paso 1 elegir
personaje y buscar ítems borrados (SOAP), paso 2 elegir ítem y recuperarlo; refresca la
lista tras recuperar. La vista pasa character_names por json_script.
Verificado: check OK, render de la isla, redirige a login sin sesión.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1006 lines
46 KiB
Python
1006 lines
46 KiB
Python
from ._base import *
|
||
|
||
|
||
def rename_character_view(request):
|
||
username = request.session.get('username')
|
||
if not username:
|
||
return redirect('login')
|
||
|
||
# 🔹 Obtener información de la cuenta desde acore_auth
|
||
with connections['acore_auth'].cursor() as cursor:
|
||
cursor.execute("""
|
||
SELECT id, email, last_ip FROM account WHERE username = %s
|
||
""", [username])
|
||
account_info = cursor.fetchone()
|
||
|
||
if not account_info:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Error: Cuenta no encontrada.</span>'})
|
||
|
||
account_id, email, acore_ip = account_info
|
||
client_ip = request.META.get('REMOTE_ADDR', '')
|
||
|
||
# 🔹 Obtener personajes del usuario desde la base de datos `acore_characters`
|
||
with connections['acore_characters'].cursor() as cursor:
|
||
cursor.execute("""
|
||
SELECT name FROM characters WHERE account = %s
|
||
""", [account_id])
|
||
characters = [row[0] for row in cursor.fetchall()]
|
||
|
||
# 🔹 Obtener el precio del renombrado
|
||
price_obj = RenamePrice.objects.first()
|
||
price = price_obj.price if price_obj else 2.00
|
||
|
||
# 🔹 Ejecutar el comando SOAP para verificar el servidor
|
||
command = f".server info"
|
||
response = execute_soap_command(command)
|
||
|
||
if request.method == 'POST':
|
||
character_name = request.POST.get('character')
|
||
|
||
if response is None:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Error de comunicación con el servidor. Intente nuevamente más tarde.</span>'})
|
||
|
||
if not character_name:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Por favor, seleccione un personaje.</span>'})
|
||
|
||
if character_name not in characters:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">No tienes permiso para renombrar este personaje.</span>'})
|
||
|
||
# 🔹 Crear sesión de pago con Stripe
|
||
success_url = request.build_absolute_uri(reverse('rename-success'))
|
||
cancel_url = request.build_absolute_uri(reverse('rename-cancel'))
|
||
stripe_response = create_checkout_session(
|
||
account_id=account_id,
|
||
username=username,
|
||
email=email,
|
||
acore_ip=acore_ip,
|
||
amount=price,
|
||
character_name=character_name,
|
||
success_url=success_url,
|
||
cancel_url=cancel_url,
|
||
product_name=f"Renombrar personaje: {character_name}"
|
||
)
|
||
|
||
if stripe_response["success"]:
|
||
request.session['rename_character'] = character_name
|
||
return JsonResponse({
|
||
'success': True,
|
||
'session_id': stripe_response["session_id"],
|
||
'stripe_public_key': settings.STRIPE_PUBLIC_KEY
|
||
})
|
||
else:
|
||
return JsonResponse({'success': False, 'message': f'<span class="red-form-response">Error al iniciar el pago: {stripe_response["error"]}</span>'})
|
||
|
||
return render(request, 'account/rename_character.html', {'characters': characters, 'price': price})
|
||
@require_paid_stripe()
|
||
def rename_success_view(request):
|
||
# Procesar el comando SOAP tras el pago exitoso
|
||
character_name = request.session.get('rename_character')
|
||
if not character_name:
|
||
return redirect('rename-character')
|
||
|
||
command = f".char rename {character_name}"
|
||
response = execute_soap_command(command)
|
||
|
||
if response is None or response.strip() == "":
|
||
message = f"El personaje {character_name} ha sido marcado para renombrar."
|
||
request.session.pop('rename_character', None) # Limpiar la sesión
|
||
return render(request, 'account/rename_success.html', {'message': message})
|
||
else:
|
||
return render(request, 'account/rename_success.html', {'message': f"Error: {response}"})
|
||
def rename_cancel_view(request):
|
||
username = request.session.get('username')
|
||
if not username:
|
||
return redirect('login')
|
||
return render(request, 'account/rename_cancel.html')
|
||
def restore_character_view(request):
|
||
# Verifica si el usuario está autenticado y obtiene su nombre de usuario
|
||
username = request.session.get('username')
|
||
if not username:
|
||
return redirect('login') # Redirige si no hay sesión
|
||
|
||
# Obtener la ID de cuenta del usuario conectado a partir del sistema de autenticación personalizada
|
||
try:
|
||
with connections['acore_auth'].cursor() as cursor:
|
||
cursor.execute("SELECT id FROM account WHERE username = %s", [username])
|
||
result = cursor.fetchone()
|
||
|
||
if not result:
|
||
# Si no se encuentra la cuenta, mostrar un error
|
||
messages.error(request, "No se encontró la cuenta asociada a ese usuario.")
|
||
return redirect('login') # Redirige al login si no se encuentra la cuenta
|
||
|
||
account_id = result[0] # Obtén el ID de la cuenta
|
||
except Exception as e:
|
||
messages.error(request, f"Ocurrió un error al recuperar la cuenta: {str(e)}")
|
||
return redirect('login')
|
||
|
||
# Verificar si se ha seleccionado un personaje para restaurar
|
||
if request.method == 'POST':
|
||
# Obtener el GUID del personaje seleccionado para restaurar
|
||
guid = request.POST.get('guid')
|
||
|
||
if not guid:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">No se seleccionó un personaje para restaurar.</span>'})
|
||
|
||
# Restaurar vía SOAP y responder en JSON (isla React)
|
||
try:
|
||
command = f".char del restore {guid}" # Comando SOAP para restaurar el personaje
|
||
response = execute_soap_command(command) # Ejecuta el comando SOAP
|
||
|
||
if response == "success":
|
||
return JsonResponse({
|
||
'success': True,
|
||
'message': '<span class="ok-form-response">Personaje restaurado exitosamente.</span>',
|
||
'redirect': reverse('my-account'),
|
||
})
|
||
else:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Hubo un error al restaurar el personaje.</span>'})
|
||
except Exception as e:
|
||
return JsonResponse({'success': False, 'message': f'<span class="red-form-response">Hubo un error al intentar restaurar el personaje: {str(e)}</span>'})
|
||
|
||
# Realizar la consulta para obtener los personajes eliminados de la cuenta
|
||
with connections['acore_characters'].cursor() as cursor:
|
||
cursor.execute("""
|
||
SELECT guid, level, deleteInfos_Name, deleteInfos_Account, deleteDate
|
||
FROM characters
|
||
WHERE deleteInfos_Account = %s AND deleteDate IS NOT NULL
|
||
""", [account_id]) # Filtra por account_id
|
||
|
||
# Obtener los resultados de la consulta
|
||
deleted_characters = cursor.fetchall()
|
||
|
||
# Si no hay personajes eliminados
|
||
if not deleted_characters:
|
||
return render(request, 'account/restore_character.html', {
|
||
'message': 'No hay personajes eliminados que puedas recuperar.'
|
||
})
|
||
|
||
# Crear un listado de personajes eliminados con su nombre y nivel (si lo tienes)
|
||
character_list = []
|
||
for character in deleted_characters:
|
||
guid, level, name, account_id, delete_date = character
|
||
# Agregar la información del personaje al listado
|
||
character_list.append({
|
||
'name': name,
|
||
'guid': guid,
|
||
'level': level,
|
||
'delete_date': delete_date
|
||
})
|
||
|
||
# Renderiza la plantilla con los personajes eliminados
|
||
return render(request, 'account/restore_character.html', {
|
||
'character_list': character_list,
|
||
'character_data': [
|
||
{'guid': c['guid'], 'name': c['name'], 'level': c['level']}
|
||
for c in character_list
|
||
],
|
||
})
|
||
def restore_items_view(request):
|
||
username = request.session.get('username')
|
||
if not username:
|
||
return redirect('login')
|
||
|
||
characters = []
|
||
deleted_items = []
|
||
selected_character = None
|
||
|
||
try:
|
||
# Obtener la ID de cuenta del usuario
|
||
with connections['acore_auth'].cursor() as cursor:
|
||
cursor.execute("SELECT id FROM account WHERE username = %s", [username])
|
||
result = cursor.fetchone()
|
||
if result:
|
||
account_id = result[0]
|
||
else:
|
||
messages.error(request, "No se encontró la cuenta asociada.")
|
||
return redirect('login')
|
||
|
||
# Obtener los personajes del usuario
|
||
with connections['acore_characters'].cursor() as cursor:
|
||
cursor.execute("SELECT name FROM characters WHERE account = %s", [account_id])
|
||
characters = [row[0] for row in cursor.fetchall()]
|
||
|
||
except Exception as e:
|
||
messages.error(request, f"Error al obtener los personajes: {str(e)}")
|
||
|
||
# La isla React usa AJAX (X-Requested-With); en ese caso respondemos JSON.
|
||
is_ajax = request.headers.get('X-Requested-With') == 'XMLHttpRequest'
|
||
|
||
if request.method == "GET" and "character_name" in request.GET:
|
||
selected_character = request.GET.get("character_name")
|
||
|
||
if selected_character:
|
||
try:
|
||
# Ejecutar comando SOAP para obtener ítems eliminados del personaje seleccionado
|
||
command = f".item restore list {selected_character}"
|
||
response = execute_soap_command(command)
|
||
|
||
# Procesar la respuesta del servidor
|
||
for line in response.split("\n"):
|
||
match = re.search(r"Recover id: (\d+) \| Item: (.+) \((\d+)\) \| Count: (\d+)", line)
|
||
if match:
|
||
recover_id = match.group(1)
|
||
item_name = match.group(2)
|
||
item_id = match.group(3)
|
||
count = match.group(4)
|
||
deleted_items.append({
|
||
"recover_id": recover_id,
|
||
"item_name": item_name,
|
||
"item_id": item_id,
|
||
"count": count
|
||
})
|
||
|
||
except Exception as e:
|
||
if is_ajax:
|
||
return JsonResponse({'error': f'Error al obtener los ítems eliminados: {str(e)}'})
|
||
messages.error(request, f"Error al obtener los ítems eliminados: {str(e)}")
|
||
|
||
if is_ajax:
|
||
return JsonResponse({'items': deleted_items})
|
||
|
||
if request.method == "POST":
|
||
recover_id = request.POST.get("recover_id")
|
||
selected_character = request.POST.get("character_name")
|
||
|
||
if not recover_id or not selected_character:
|
||
if is_ajax:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Selecciona un personaje y un ítem para restaurar.</span>'})
|
||
messages.error(request, "Selecciona un personaje y un ítem para restaurar.")
|
||
return redirect('restore-items')
|
||
|
||
try:
|
||
# Ejecutar comando SOAP para restaurar el ítem
|
||
command = f".item restore {recover_id} {selected_character}"
|
||
response = execute_soap_command(command)
|
||
ok = "success" in response.lower()
|
||
except Exception as e:
|
||
if is_ajax:
|
||
return JsonResponse({'success': False, 'message': f'<span class="red-form-response">Error al restaurar el ítem: {str(e)}</span>'})
|
||
messages.error(request, f"Error al restaurar el ítem: {str(e)}")
|
||
return redirect('restore-items')
|
||
|
||
if is_ajax:
|
||
msg = ('<span class="ok-form-response">Ítem restaurado exitosamente.</span>' if ok
|
||
else '<span class="red-form-response">No se pudo restaurar el ítem.</span>')
|
||
return JsonResponse({'success': ok, 'message': msg})
|
||
|
||
messages.success(request, "Ítem restaurado exitosamente.") if ok else messages.error(request, "No se pudo restaurar el ítem.")
|
||
return redirect('restore-items')
|
||
|
||
return render(request, 'account/restore_items.html', {
|
||
'characters': characters,
|
||
'deleted_items': deleted_items,
|
||
'selected_character': selected_character,
|
||
'character_names': characters,
|
||
})
|
||
def quest_character_view(request):
|
||
username = request.session.get('username')
|
||
if not username:
|
||
return redirect('login')
|
||
return render(request, 'account/quest_character.html')
|
||
def send_gift_view(request):
|
||
username = request.session.get('username')
|
||
if not username:
|
||
return redirect('login')
|
||
return render(request, 'account/send_gift.html')
|
||
def customize_character_view(request):
|
||
username = request.session.get('username')
|
||
if not username:
|
||
return redirect('login')
|
||
|
||
# ?? Obtener información de la cuenta desde acore_auth
|
||
with connections['acore_auth'].cursor() as cursor:
|
||
cursor.execute("""
|
||
SELECT id, email, last_ip FROM account WHERE username = %s
|
||
""", [username])
|
||
account_info = cursor.fetchone()
|
||
|
||
if not account_info:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Error: Cuenta no encontrada.</span>'})
|
||
|
||
account_id, email, acore_ip = account_info
|
||
client_ip = request.META.get('REMOTE_ADDR', '')
|
||
|
||
# ?? Obtener personajes del usuario desde la base de datos `acore_characters`
|
||
with connections['acore_characters'].cursor() as cursor:
|
||
cursor.execute("""
|
||
SELECT name FROM characters WHERE account = %s
|
||
""", [account_id])
|
||
|
||
characters = [row[0] for row in cursor.fetchall()]
|
||
|
||
# Obtener el precio de la personalización (si se gestiona desde el admin)
|
||
price_obj = CustomizePrice.objects.first()
|
||
price = price_obj.price if price_obj else 1.00
|
||
|
||
if request.method == 'POST':
|
||
character_name = request.POST.get('character')
|
||
|
||
# Validar si el personaje fue seleccionado
|
||
if not character_name:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Por favor, seleccione un personaje.</span>'})
|
||
|
||
# Verificar si el personaje pertenece al usuario
|
||
if character_name not in characters:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">No tienes permiso para personalizar este personaje.</span>'})
|
||
|
||
# Crear sesión de pago con Stripe
|
||
success_url = request.build_absolute_uri(reverse('customize-success'))
|
||
cancel_url = request.build_absolute_uri(reverse('customize-cancel'))
|
||
stripe_response = create_checkout_session(
|
||
account_id=account_id,
|
||
username=username,
|
||
email=email,
|
||
acore_ip=acore_ip,
|
||
amount=price,
|
||
character_name=character_name,
|
||
success_url=success_url,
|
||
cancel_url=cancel_url,
|
||
product_name=f"Personalizar personaje: {character_name}"
|
||
)
|
||
|
||
|
||
if stripe_response["success"]:
|
||
# Guardar temporalmente el nombre del personaje en la sesión
|
||
request.session['customize_character'] = character_name
|
||
return JsonResponse({
|
||
'success': True,
|
||
'session_id': stripe_response["session_id"],
|
||
'stripe_public_key': settings.STRIPE_PUBLIC_KEY
|
||
})
|
||
else:
|
||
return JsonResponse({'success': False, 'message': f'<span class="red-form-response">Error al iniciar el pago: {stripe_response["error"]}</span>'})
|
||
|
||
return render(request, 'account/customize_character.html', {'characters': characters, 'price': price})
|
||
@require_paid_stripe()
|
||
def customize_success_view(request):
|
||
# Procesar el comando SOAP tras el pago exitoso
|
||
character_name = request.session.get('customize_character')
|
||
if not character_name:
|
||
return redirect('customize-character')
|
||
|
||
command = f".char customi {character_name}"
|
||
response = execute_soap_command(command)
|
||
|
||
if response is None or response.strip() == "":
|
||
message = f"El personaje {character_name} ha sido marcado para personalización."
|
||
request.session.pop('customize_character', None) # Limpiar la sesión
|
||
return render(request, 'account/customize_success.html', {'message': message})
|
||
else:
|
||
return render(request, 'account/customize_success.html', {'message': f"Error: {response}"})
|
||
def customize_cancel_view(request):
|
||
return render(request, 'account/customize_cancel.html')
|
||
def change_race_character_view(request):
|
||
username = request.session.get('username')
|
||
if not username:
|
||
return redirect('login')
|
||
|
||
# Obtener personajes del usuario desde la base de datos `acore_characters`
|
||
with connections['acore_auth'].cursor() as cursor:
|
||
cursor.execute("""
|
||
SELECT id, email, last_ip FROM account WHERE username = %s
|
||
""", [username])
|
||
account_info = cursor.fetchone()
|
||
|
||
if not account_info:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Error: Cuenta no encontrada.</span>'})
|
||
|
||
account_id, email, acore_ip = account_info
|
||
client_ip = request.META.get('REMOTE_ADDR', '')
|
||
|
||
# ?? Obtener personajes del usuario desde la base de datos `acore_characters`
|
||
with connections['acore_characters'].cursor() as cursor:
|
||
cursor.execute("""
|
||
SELECT name FROM characters WHERE account = %s
|
||
""", [account_id])
|
||
characters = [row[0] for row in cursor.fetchall()]
|
||
|
||
# Obtener el precio del cambio de raza
|
||
price_obj = ChangeRacePrice.objects.first()
|
||
price = price_obj.price if price_obj else 10.00 # Precio predeterminado si no hay registro
|
||
|
||
if request.method == 'POST':
|
||
character_name = request.POST.get('character')
|
||
|
||
# Validar si el personaje fue seleccionado
|
||
if not character_name:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Por favor, seleccione un personaje.</span>'})
|
||
|
||
# Verificar si el personaje pertenece al usuario
|
||
if character_name not in characters:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">No tienes permiso para cambiar la raza de este personaje.</span>'})
|
||
|
||
# Crear sesión de pago con Stripe
|
||
success_url = request.build_absolute_uri(reverse('change-race-success'))
|
||
cancel_url = request.build_absolute_uri(reverse('change-race-cancel'))
|
||
stripe_response = create_checkout_session(
|
||
account_id=account_id,
|
||
username=username,
|
||
email=email,
|
||
acore_ip=acore_ip,
|
||
amount=price,
|
||
character_name=character_name,
|
||
success_url=success_url,
|
||
cancel_url=cancel_url,
|
||
product_name=f"Cambio de Raza del personaje: {character_name}"
|
||
)
|
||
|
||
if stripe_response["success"]:
|
||
# Guardar el personaje en la sesión para el cambio
|
||
request.session['change_race_character'] = character_name
|
||
return JsonResponse({
|
||
'success': True,
|
||
'session_id': stripe_response["session_id"],
|
||
'stripe_public_key': settings.STRIPE_PUBLIC_KEY
|
||
})
|
||
else:
|
||
return JsonResponse({'success': False, 'message': f'<span class="red-form-response">Error al iniciar el pago: {stripe_response["error"]}</span>'})
|
||
|
||
return render(request, 'account/change_race.html', {'characters': characters, 'price': price})
|
||
@require_paid_stripe()
|
||
def change_race_success_view(request):
|
||
# Procesar el comando SOAP tras el pago exitoso
|
||
character_name = request.session.get('change_race_character')
|
||
if not character_name:
|
||
return redirect('change-race')
|
||
|
||
command = f".char changerace {character_name}"
|
||
response = execute_soap_command(command)
|
||
|
||
if response is None or response.strip() == "":
|
||
message = f"El personaje {character_name} ha sido marcado para cambio de raza."
|
||
request.session.pop('change_race_character', None) # Limpiar la sesión
|
||
return render(request, 'account/change_race_success.html', {'message': message})
|
||
else:
|
||
return render(request, 'account/change_race_success.html', {'message': f"Error: {response}"})
|
||
def change_race_cancel_view(request):
|
||
return render(request, 'account/change_race_cancel.html')
|
||
def change_faction_character_view(request):
|
||
username = request.session.get('username')
|
||
if not username:
|
||
return redirect('login')
|
||
|
||
# Obtener personajes del usuario desde la base de datos `acore_characters`
|
||
with connections['acore_auth'].cursor() as cursor:
|
||
cursor.execute("""
|
||
SELECT id, email, last_ip FROM account WHERE username = %s
|
||
""", [username])
|
||
account_info = cursor.fetchone()
|
||
|
||
if not account_info:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Error: Cuenta no encontrada.</span>'})
|
||
|
||
account_id, email, acore_ip = account_info
|
||
client_ip = request.META.get('REMOTE_ADDR', '')
|
||
|
||
# ?? Obtener personajes del usuario desde la base de datos `acore_characters`
|
||
with connections['acore_characters'].cursor() as cursor:
|
||
cursor.execute("""
|
||
SELECT name FROM characters WHERE account = %s
|
||
""", [account_id])
|
||
characters = [row[0] for row in cursor.fetchall()]
|
||
|
||
# Obtener el precio del cambio de facción
|
||
price_obj = ChangeFactionPrice.objects.first()
|
||
price = price_obj.price if price_obj else 10.00
|
||
|
||
if request.method == 'POST':
|
||
character_name = request.POST.get('character')
|
||
|
||
# Validar si el personaje fue seleccionado
|
||
if not character_name:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Por favor, seleccione un personaje.</span>'})
|
||
|
||
# Verificar si el personaje pertenece al usuario
|
||
if character_name not in characters:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">No tienes permiso para cambiar la facción de este personaje.</span>'})
|
||
|
||
# Crear sesión de pago con Stripe
|
||
success_url = request.build_absolute_uri(reverse('change-faction-success'))
|
||
cancel_url = request.build_absolute_uri(reverse('change-faction-cancel'))
|
||
stripe_response = create_checkout_session(
|
||
account_id=account_id,
|
||
username=username,
|
||
email=email,
|
||
acore_ip=acore_ip,
|
||
amount=price,
|
||
character_name=character_name,
|
||
success_url=success_url,
|
||
cancel_url=cancel_url,
|
||
product_name=f"Cambiar Faccion del personaje: {character_name}"
|
||
)
|
||
|
||
if stripe_response["success"]:
|
||
# Guardar el personaje seleccionado en la sesión
|
||
request.session['change_faction_character'] = character_name
|
||
return JsonResponse({
|
||
'success': True,
|
||
'session_id': stripe_response["session_id"],
|
||
'stripe_public_key': settings.STRIPE_PUBLIC_KEY
|
||
})
|
||
else:
|
||
return JsonResponse({'success': False, 'message': f'<span class="red-form-response">Error al iniciar el pago: {stripe_response["error"]}</span>'})
|
||
|
||
return render(request, 'account/change_faction.html', {'characters': characters, 'price': price})
|
||
@require_paid_stripe()
|
||
def change_faction_success_view(request):
|
||
# Procesar el comando SOAP tras el pago exitoso
|
||
character_name = request.session.get('change_faction_character')
|
||
if not character_name:
|
||
return redirect('change-faction-character')
|
||
|
||
command = f".char changef {character_name}"
|
||
response = execute_soap_command(command)
|
||
|
||
if response is None or response.strip() == "":
|
||
message = f"El personaje {character_name} ha cambiado de facción con éxito."
|
||
request.session.pop('change_faction_character', None) # Limpiar la sesión
|
||
return render(request, 'account/change_faction_success.html', {'message': message})
|
||
else:
|
||
return render(request, 'account/change_faction_success.html', {'message': f"Error: {response}"})
|
||
def change_faction_cancel_view(request):
|
||
return render(request, 'account/change_faction_cancel.html')
|
||
def level_up_character_view(request):
|
||
username = request.session.get('username')
|
||
if not username:
|
||
return redirect('login')
|
||
|
||
# Obtener personajes del usuario desde la base de datos `acore_characters`
|
||
with connections['acore_auth'].cursor() as cursor:
|
||
cursor.execute("""
|
||
SELECT id, email, last_ip FROM account WHERE username = %s
|
||
""", [username])
|
||
account_info = cursor.fetchone()
|
||
|
||
if not account_info:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Error: Cuenta no encontrada.</span>'})
|
||
|
||
account_id, email, acore_ip = account_info
|
||
client_ip = request.META.get('REMOTE_ADDR', '')
|
||
|
||
# ?? Obtener personajes del usuario desde la base de datos `acore_characters`
|
||
with connections['acore_characters'].cursor() as cursor:
|
||
cursor.execute("""
|
||
SELECT name FROM characters WHERE account = %s
|
||
""", [account_id])
|
||
characters = [row[0] for row in cursor.fetchall()]
|
||
|
||
# Obtener el precio de subir a nivel 80
|
||
price_obj = LevelUpPrice.objects.first()
|
||
price = price_obj.price if price_obj else 10.00
|
||
|
||
if request.method == 'POST':
|
||
character_name = request.POST.get('character')
|
||
|
||
# Validar si el personaje fue seleccionado
|
||
if not character_name:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Por favor, seleccione un personaje.</span>'})
|
||
|
||
# Verificar si el personaje pertenece al usuario
|
||
if character_name not in characters:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">No tienes permiso para subir de nivel a este personaje.</span>'})
|
||
|
||
# Crear sesión de pago con Stripe
|
||
success_url = request.build_absolute_uri(reverse('level-up-success'))
|
||
cancel_url = request.build_absolute_uri(reverse('level-up-cancel'))
|
||
stripe_response = create_checkout_session(
|
||
account_id=account_id,
|
||
username=username,
|
||
email=email,
|
||
acore_ip=acore_ip,
|
||
amount=price,
|
||
character_name=character_name,
|
||
success_url=success_url,
|
||
cancel_url=cancel_url,
|
||
product_name=f"Subir el Nivel 80 del personaje: {character_name}"
|
||
)
|
||
|
||
if stripe_response["success"]:
|
||
# Guardar el personaje en la sesión para usarlo después del pago
|
||
request.session['levelup_character'] = character_name
|
||
return JsonResponse({
|
||
'success': True,
|
||
'session_id': stripe_response["session_id"],
|
||
'stripe_public_key': settings.STRIPE_PUBLIC_KEY
|
||
})
|
||
else:
|
||
return JsonResponse({'success': False, 'message': f'<span class="red-form-response">Error al iniciar el pago: {stripe_response["error"]}</span>'})
|
||
|
||
return render(request, 'account/level_up.html', {'characters': characters, 'price': price})
|
||
@require_paid_stripe()
|
||
def level_up_success_view(request):
|
||
character_name = request.session.get('levelup_character')
|
||
if not character_name:
|
||
return redirect('level-up-character')
|
||
|
||
# Ejecutar el comando SOAP
|
||
command = f".char level {character_name} 80"
|
||
response = execute_soap_command(command)
|
||
|
||
if response is None or response.strip() == "":
|
||
message = f"El personaje {character_name} ha sido subido al nivel 80."
|
||
else:
|
||
message = f"Error: {response}"
|
||
|
||
# Limpiar la sesión
|
||
request.session.pop('levelup_character', None)
|
||
|
||
return render(request, 'account/level_up_success.html', {'message': message})
|
||
def level_up_cancel_view(request):
|
||
return render(request, 'account/level_up_cancel.html')
|
||
def gold_character_view(request):
|
||
username = request.session.get('username')
|
||
if not username:
|
||
return redirect('login')
|
||
|
||
# Obtener personajes y estado de conexión del usuario
|
||
try:
|
||
with connections['acore_auth'].cursor() as cursor:
|
||
cursor.execute("""
|
||
SELECT id, email, last_ip FROM account WHERE username = %s
|
||
""", [username])
|
||
account_info = cursor.fetchone()
|
||
|
||
if not account_info:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Error: Cuenta no encontrada.</span>'})
|
||
|
||
account_id, email, acore_ip = account_info
|
||
client_ip = request.META.get('REMOTE_ADDR', '')
|
||
|
||
# Obtener personajes del usuario desde la base de datos `acore_characters`
|
||
with connections['acore_characters'].cursor() as cursor:
|
||
cursor.execute("""
|
||
SELECT name, online, money FROM characters WHERE account = %s
|
||
""", [account_id])
|
||
characters_data = cursor.fetchall()
|
||
|
||
characters = {row[0]: {'online': row[1], 'money': row[2]} for row in characters_data}
|
||
|
||
except Exception as e:
|
||
return JsonResponse({'success': False, 'message': f'<span class="red-form-response">Error al obtener los personajes: {str(e)}</span>'})
|
||
|
||
# Obtener precios del oro
|
||
gold_prices = GoldPrice.objects.all().order_by('gold_amount')
|
||
|
||
if request.method == 'POST':
|
||
character_name = request.POST.get('character')
|
||
gold_amount = request.POST.get('gold_amount')
|
||
|
||
# Validaciones iniciales
|
||
if not character_name or not gold_amount:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Seleccione un personaje y una cantidad de oro.</span>'})
|
||
|
||
if character_name not in characters:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">No tienes permiso para enviar oro a este personaje.</span>'})
|
||
|
||
if characters[character_name]['online'] == 1:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">El personaje debe estar desconectado para recibir oro.</span>'})
|
||
|
||
try:
|
||
gold_amount = int(gold_amount)
|
||
except ValueError:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Cantidad de oro no válida.</span>'})
|
||
|
||
gold_price = GoldPrice.objects.filter(gold_amount=gold_amount).first()
|
||
if not gold_price:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Cantidad de oro no válida.</span>'})
|
||
|
||
# El precio va en euros (con decimales); el helper lo pasa a céntimos (×100)
|
||
stripe_price = gold_price.price
|
||
|
||
# Crear sesión de pago con Stripe
|
||
success_url = request.build_absolute_uri(reverse('gold-success'))
|
||
cancel_url = request.build_absolute_uri(reverse('gold-cancel'))
|
||
|
||
# Llamada corregida a create_checkout_session con todos los parámetros requeridos
|
||
stripe_response = create_checkout_session(
|
||
account_id=account_id,
|
||
username=username,
|
||
email=email,
|
||
acore_ip=acore_ip,
|
||
amount=stripe_price, # El precio calculado
|
||
character_name=character_name,
|
||
success_url=success_url,
|
||
cancel_url=cancel_url,
|
||
product_name=f"Aumentar el Oro: {gold_amount} al Personaje: {character_name}"
|
||
)
|
||
|
||
if stripe_response["success"]:
|
||
# Guardar en sesión los datos para el callback tras el pago
|
||
request.session['gold_transaction'] = {
|
||
'character_name': character_name,
|
||
'gold_amount': gold_amount
|
||
}
|
||
return JsonResponse({
|
||
'success': True,
|
||
'session_id': stripe_response["session_id"],
|
||
'stripe_public_key': settings.STRIPE_PUBLIC_KEY
|
||
})
|
||
else:
|
||
return JsonResponse({'success': False, 'message': f'<span class="red-form-response">Error al iniciar el pago: {stripe_response["error"]}</span>'})
|
||
|
||
return render(request, 'account/gold_character.html', {
|
||
'characters': characters,
|
||
'gold_prices': gold_prices,
|
||
'character_names': list(characters.keys()),
|
||
'gold_options': [{'gold_amount': p.gold_amount, 'price': str(p.price)} for p in gold_prices],
|
||
})
|
||
@require_paid_stripe()
|
||
def gold_success_view(request):
|
||
# Procesar el pago exitoso
|
||
transaction = request.session.pop('gold_transaction', None)
|
||
if not transaction:
|
||
return redirect('gold-character')
|
||
|
||
character_name = transaction['character_name']
|
||
gold_amount = int(transaction['gold_amount'])
|
||
|
||
# Calcular el oro en formato del juego
|
||
game_gold_amount = gold_amount * 10000
|
||
|
||
# Actualizar la cantidad de oro en la base de datos
|
||
with connections['acore_characters'].cursor() as cursor:
|
||
cursor.execute("""
|
||
UPDATE characters
|
||
SET money = money + %s
|
||
WHERE name = %s
|
||
""", [game_gold_amount, character_name])
|
||
|
||
return render(request, 'account/gold_success.html', {'character_name': character_name, 'gold_amount': gold_amount})
|
||
def gold_cancel_view(request):
|
||
return render(request, 'account/gold_cancel.html')
|
||
def transfer_character_view(request):
|
||
username = request.session.get('username')
|
||
if not username:
|
||
return redirect('login')
|
||
|
||
# Obtener el precio de transferencia
|
||
price_obj = TransferPrice.objects.first()
|
||
price = price_obj.price if price_obj else 10.00
|
||
|
||
# Obtener el ID de usuario desde acore_auth.account
|
||
with connections['acore_auth'].cursor() as cursor:
|
||
cursor.execute("SELECT id, email, last_ip FROM account WHERE username = %s", [username])
|
||
user_data = cursor.fetchone()
|
||
if not user_data:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Cuenta no encontrada. Por favor, inicie sesión nuevamente.</span>'})
|
||
|
||
user_id, email, acore_ip = user_data # ID de la cuenta, email y la última IP
|
||
|
||
# Obtener personajes de la cuenta de origen
|
||
with connections['acore_characters'].cursor() as cursor:
|
||
cursor.execute("""
|
||
SELECT name, class, online
|
||
FROM characters
|
||
WHERE account = %s
|
||
""", [user_id])
|
||
characters = cursor.fetchall()
|
||
|
||
if request.method == 'POST':
|
||
character_name = request.POST.get('character')
|
||
destination_account = request.POST.get('destination_account')
|
||
token = request.POST.get('security_token')
|
||
|
||
# Validaciones
|
||
if not all([character_name, destination_account, token]):
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Por favor, complete todos los campos.</span>'})
|
||
|
||
character = next((char for char in characters if char[0] == character_name), None)
|
||
if not character:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">No tienes permiso para transferir este personaje.</span>'})
|
||
|
||
# Verificar si el personaje está desconectado
|
||
if character[2] == 1: # Si está conectado
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">El personaje debe estar desconectado para ser transferido.</span>'})
|
||
|
||
# Verificar el token de seguridad
|
||
security_token = SecurityToken.objects.filter(user_id=user_id, token=token).first()
|
||
if not security_token:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Token de seguridad incorrecto.</span>'})
|
||
|
||
# Verificar si el token ha expirado
|
||
if security_token.expires_at < timezone.now():
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">El token ha expirado. Solicite uno nuevo.</span>'})
|
||
|
||
# Verificar si la cuenta de destino existe
|
||
with connections['acore_auth'].cursor() as cursor:
|
||
cursor.execute("SELECT id FROM account WHERE username = %s", [destination_account])
|
||
destination_account_data = cursor.fetchone()
|
||
|
||
if not destination_account_data:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">La cuenta de destino no existe.</span>'})
|
||
|
||
# Verificar restricciones en la cuenta de destino
|
||
destination_account_id = destination_account_data[0]
|
||
with connections['acore_characters'].cursor() as cursor:
|
||
cursor.execute("""
|
||
SELECT account, name, class, level, online
|
||
FROM characters
|
||
WHERE account = %s
|
||
""", [destination_account_id])
|
||
destination_characters = cursor.fetchall()
|
||
|
||
if not any(char[3] >= 55 and char[2] != 6 for char in destination_characters):
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">La cuenta destino debe tener al menos un personaje de nivel 55 o superior que no sea Caballero de la Muerte.</span>'})
|
||
|
||
if any(char[2] == 6 for char in destination_characters):
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">La cuenta destino no puede tener un Caballero de la Muerte.</span>'})
|
||
|
||
# Verificar que ninguna cuenta esté online
|
||
for char in destination_characters:
|
||
if char[4] == 1:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Todos los personajes de la cuenta destino deben estar desconectados.</span>'})
|
||
for char in characters:
|
||
if char[2] == 1:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Todos los personajes de la cuenta origen deben estar desconectados.</span>'})
|
||
|
||
# Crear sesión de pago con Stripe
|
||
success_url = request.build_absolute_uri(reverse('transfer-success'))
|
||
cancel_url = request.build_absolute_uri(reverse('transfer-cancel'))
|
||
|
||
# Llamada corregida a create_checkout_session con todos los parámetros requeridos
|
||
stripe_response = create_checkout_session(
|
||
username=username,
|
||
email=email,
|
||
acore_ip=acore_ip,
|
||
account_id=user_id, # Pasar el account_id
|
||
amount=price, # El precio de la transferencia
|
||
character_name=character_name,
|
||
success_url=success_url,
|
||
cancel_url=cancel_url,
|
||
product_name=f"Transferir el personaje: {character_name} a la cuenta de destino: {destination_account}"
|
||
)
|
||
|
||
if stripe_response["success"]:
|
||
# Guardar los datos de la transferencia en la sesión para usarlos después del pago
|
||
request.session['transfer_data'] = {
|
||
'character_name': character_name,
|
||
'destination_account': destination_account
|
||
}
|
||
return JsonResponse({
|
||
'success': True,
|
||
'session_id': stripe_response["session_id"],
|
||
'stripe_public_key': settings.STRIPE_PUBLIC_KEY
|
||
})
|
||
else:
|
||
return JsonResponse({'success': False, 'message': f'<span class="red-form-response">Error al iniciar el pago: {stripe_response["error"]}</span>'})
|
||
|
||
return render(request, 'account/transfer_character.html', {
|
||
'characters': characters,
|
||
'price': price,
|
||
'character_names': [c[0] for c in characters],
|
||
})
|
||
@require_paid_stripe()
|
||
def transfer_success_view(request):
|
||
transfer_data = request.session.get('transfer_data')
|
||
if not transfer_data:
|
||
return redirect('transfer-character')
|
||
|
||
character_name = transfer_data['character_name']
|
||
destination_account = transfer_data['destination_account']
|
||
|
||
# Ejecutar comando SOAP
|
||
command = f".char changeaccount {destination_account} {character_name}"
|
||
response = execute_soap_command(command)
|
||
|
||
if response is None or response.strip() == "":
|
||
message = f"El personaje {character_name} ha sido transferido a la cuenta {destination_account}."
|
||
request.session.pop('transfer_data', None) # Limpiar sesión
|
||
return render(request, 'account/transfer_success.html', {'message': message})
|
||
else:
|
||
return render(request, 'account/transfer_success.html', {'message': f"Error: {response}"})
|
||
def transfer_cancel_view(request):
|
||
return render(request, 'account/transfer_cancel.html')
|
||
def revive_character_view(request):
|
||
username = request.session.get('username')
|
||
if not username:
|
||
return redirect('login')
|
||
|
||
# Obtener personajes del usuario desde la base de datos `acore_characters`
|
||
with connections['acore_characters'].cursor() as cursor:
|
||
cursor.execute("""
|
||
SELECT name, online
|
||
FROM characters
|
||
WHERE account = (
|
||
SELECT id
|
||
FROM acore_auth.account
|
||
WHERE username = %s
|
||
)
|
||
""", [username])
|
||
characters_data = cursor.fetchall()
|
||
characters = {row[0]: row[1] for row in characters_data} # Diccionario con nombre y estado de conexión
|
||
|
||
if request.method == 'POST':
|
||
character_name = request.POST.get('character')
|
||
|
||
# Validar si el personaje fue seleccionado
|
||
if not character_name:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Por favor, seleccione un personaje.</span>'})
|
||
|
||
# Verificar si el personaje pertenece al usuario
|
||
if character_name not in characters:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">No tienes permiso para revivir este personaje.</span>'})
|
||
|
||
# Verificar si el personaje está desconectado
|
||
if characters[character_name] == 1: # Si está conectado
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">El personaje debe estar desconectado para ser revivido.</span>'})
|
||
|
||
# Verificar el historial de uso del comando `revive`
|
||
last_revive = ReviveHistory.objects.filter(character_name=character_name).order_by('-used_at').first()
|
||
if last_revive and last_revive.used_at > now() - timedelta(hours=12):
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">El personaje solo puede revivirse una vez cada 12 horas.</span>'})
|
||
|
||
# Ejecutar el comando SOAP
|
||
command = f".revive {character_name}"
|
||
response = execute_soap_command(command)
|
||
|
||
# None = fallo de comunicación con el servidor
|
||
if response is None:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Error de comunicación con el servidor. Intente nuevamente más tarde.</span>'})
|
||
|
||
# Respuesta vacía = éxito (el comando .revive no devuelve texto si va bien)
|
||
if response.strip() == "":
|
||
ReviveHistory.objects.create(character_name=character_name, used_at=now())
|
||
return JsonResponse({'success': True, 'message': f'<span class="ok-form-response">El personaje {character_name} ha sido revivido con éxito.</span>'})
|
||
|
||
# Respuesta no vacía = el servidor devolvió un mensaje/error
|
||
return JsonResponse({'success': False, 'message': f'<span class="red-form-response">{response}</span>'})
|
||
|
||
return render(request, 'account/revive_character.html', {'characters': characters.keys()})
|
||
def unstuck_character_view(request):
|
||
username = request.session.get('username')
|
||
if not username:
|
||
return redirect('login')
|
||
|
||
# Obtener personajes del usuario desde la base de datos `acore_characters`
|
||
with connections['acore_characters'].cursor() as cursor:
|
||
cursor.execute("""
|
||
SELECT name, online
|
||
FROM characters
|
||
WHERE account = (
|
||
SELECT id
|
||
FROM acore_auth.account
|
||
WHERE username = %s
|
||
)
|
||
""", [username])
|
||
characters_data = cursor.fetchall()
|
||
characters = {row[0]: row[1] for row in characters_data} # Diccionario con nombre y estado de conexión
|
||
|
||
if request.method == 'POST':
|
||
character_name = request.POST.get('character')
|
||
|
||
# Validar si el personaje fue seleccionado
|
||
if not character_name:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Por favor, seleccione un personaje.</span>'})
|
||
|
||
# Verificar si el personaje pertenece al usuario
|
||
if character_name not in characters:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">No tienes permiso para desbloquear este personaje.</span>'})
|
||
|
||
# Verificar si el personaje está desconectado
|
||
if characters[character_name] == 1: # Si está conectado
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">El personaje debe estar desconectado para ser desbloqueado.</span>'})
|
||
|
||
# Verificar el historial de uso del comando
|
||
last_unstuck = UnstuckHistory.objects.filter(character_name=character_name).order_by('-used_at').first()
|
||
if last_unstuck and last_unstuck.used_at > now() - timedelta(hours=12):
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">El personaje solo puede desbloquearse una vez cada 12 horas.</span>'})
|
||
|
||
# Ejecutar el comando SOAP
|
||
command = f".unstuck {character_name} startzone"
|
||
response = execute_soap_command(command)
|
||
|
||
if response is None:
|
||
return JsonResponse({'success': False, 'message': '<span class="red-form-response">Error de comunicación con el servidor. Intente nuevamente más tarde.</span>'})
|
||
|
||
# Analizar la respuesta
|
||
if f"You are summoning {character_name} (offline)" in response:
|
||
# Registrar el uso del comando
|
||
UnstuckHistory.objects.create(character_name=character_name, used_at=now())
|
||
return JsonResponse({'success': True, 'message': f'<span class="ok-form-response">El personaje {character_name} ha sido desbloqueado con éxito.</span>'})
|
||
else:
|
||
return JsonResponse({'success': False, 'message': f'<span class="red-form-response">Error: {response}</span>'})
|
||
|
||
return render(request, 'account/unstuck_character.html', {'characters': characters.keys()})
|