diff --git a/home/models.py b/home/models.py
index e3666f3..a4a6400 100644
--- a/home/models.py
+++ b/home/models.py
@@ -282,6 +282,7 @@ class LoginAttempt(models.Model):
return f"{self.username} - {self.status} - {self.timestamp}"
+
class StripeLog(models.Model):
account_id = models.IntegerField() # ID de la cuenta en acore_auth
username = models.CharField(max_length=100) # Nombre de la cuenta
diff --git a/home/templates/partials/ban_history.html b/home/templates/partials/ban_history.html
index 2aa5006..7fc56e2 100644
--- a/home/templates/partials/ban_history.html
+++ b/home/templates/partials/ban_history.html
@@ -1,45 +1,95 @@
Aquí podrás ver todas las sanciones que ha tenido la cuenta.
-
Si tienes una sanción vigente, verás que su estado indica Activo.
-
Para evitar que tu cuenta sea sancionada, recuerda respetar las normas de nuestro servidor.
-
-
-
Importante:
-
Si tu cuenta aparece como sancionada o cerrada al intentar ingresar al reino, pero tu historial no tiene ninguna sanción activa, significa que has tenido un bloqueo automático temporal por demasiados intentos de inicio de sesión fallidos.
-
Espera al menos 10 minutos para volver a intentar y asegúrate de usar nombre de cuenta y contraseña correctas.
-
-
-
Para realizar un reclamo de sanción, por favor ingresa en nuestro foro y visita la sección Reclamaciones.
\ No newline at end of file
diff --git a/home/templates/partials/restore_character.html b/home/templates/partials/restore_character.html
index 5affd51..3344305 100644
--- a/home/templates/partials/restore_character.html
+++ b/home/templates/partials/restore_character.html
@@ -1,36 +1,53 @@
No hay ítems eliminados disponibles para restaurar.
+ {% endif %}
-
\ No newline at end of file
+
+
+
diff --git a/home/views.py b/home/views.py
index d8d088d..0f46786 100644
--- a/home/views.py
+++ b/home/views.py
@@ -199,19 +199,19 @@ def login_view(request):
password = form.cleaned_data['password']
ip_address = request.META.get('REMOTE_ADDR') # Obtener la IP del cliente
- # Llamar a la funcin de autenticacin
+ # Llamar a la función de autenticación
if authenticate(username, password):
# Guardar el intento exitoso
log_login_attempt(username, "Exito", ip_address)
- # Guardar el nombre de usuario en maysculas en la sesin
+ # Guardar el nombre de usuario en mayúsculas en la sesión
request.session['username'] = username.upper()
return JsonResponse({'success': True})
else:
# Guardar el intento fallido
log_login_attempt(username, "Fracaso", ip_address)
- return JsonResponse({'success': False, 'error': "Usuario o contrase?a incorrectos"})
+ return JsonResponse({'success': False, 'error': "Usuario o contraseña incorrectos"})
else:
return JsonResponse({'success': False, 'error': "Formulario no valido"})
@@ -675,7 +675,6 @@ def my_account(request):
})
-
def get_account_status(account_id):
with connections['acore_auth'].cursor() as cursor:
# Obtener información de la tabla 'account'
@@ -737,7 +736,7 @@ def get_account_status(account_id):
unban_timestamp, current_timestamp = ban_data
remaining_time = unban_timestamp - current_timestamp
user_info['is_banned'] = True
- user_info['unban_date'] = datetime.datetime.fromtimestamp(unban_timestamp).strftime("%A %d de %B del %Y a las %H:%M:%S Horas")
+ user_info['unban_date'] = datetime.fromtimestamp(unban_timestamp).strftime("%A %d de %B del %Y a las %H:%M:%S Horas")
user_info['remaining_time'] = remaining_time
else:
user_info['is_banned'] = False
@@ -1259,17 +1258,173 @@ def rename_cancel_view(request):
return redirect('login')
return render(request, 'account/rename_cancel.html')
+@csrf_exempt
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')
- return render(request, 'account/restore_character.html')
+ 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:
+ messages.error(request, "No se seleccionó un personaje para restaurar.")
+ return redirect('restore-character')
+
+ # Aquí es donde usamos SOAP en lugar de la actualización directa
+ try:
+ command = f".char del restore {guid}" # Comando SOAP para restaurar el personaje
+ response = execute_soap_command(command) # Ejecuta el comando SOAP
+
+ # Si la respuesta es exitosa, informamos al usuario
+ if response == "success":
+ messages.success(request, "Personaje restaurado exitosamente.")
+ return redirect('my-account') # Redirigir a la cuenta del usuario
+ else:
+ messages.error(request, "Hubo un error al restaurar el personaje.")
+ return redirect('restore-character')
+
+ except Exception as e:
+ messages.error(request, f"Hubo un error al intentar restaurar el personaje: {str(e)}")
+ return redirect('restore-character')
+
+ # 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
+ })
+
+@csrf_exempt
def restore_items_view(request):
username = request.session.get('username')
if not username:
return redirect('login')
- return render(request, 'account/restore_items.html')
+
+ 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)}")
+
+ 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:
+ messages.error(request, f"Error al obtener los ítems eliminados: {str(e)}")
+
+ 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:
+ 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)
+
+ if "success" in response.lower():
+ messages.success(request, "Ítem restaurado exitosamente.")
+ else:
+ messages.error(request, "No se pudo restaurar el ítem.")
+ except Exception as e:
+ messages.error(request, f"Error al restaurar el ítem: {str(e)}")
+
+ return redirect('restore-items')
+
+ return render(request, 'account/restore_items.html', {
+ 'characters': characters,
+ 'deleted_items': deleted_items,
+ 'selected_character': selected_character
+ })
+
def quest_character_view(request):
username = request.session.get('username')
@@ -1288,7 +1443,7 @@ def customize_character_view(request):
if not username:
return redirect('login')
- # ?? Obtener informaci��n de la cuenta desde acore_auth
+ # ?? 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
@@ -2318,13 +2473,20 @@ def d_points_view(request):
def points_history_view(request):
return render(request, 'account/points_history.html')
-
+
+
+
+def format_datetime(timestamp):
+ if timestamp:
+ return datetime.utcfromtimestamp(timestamp).strftime('%d-%m-%Y %H:%M:%S')
+ return "No disponible"
+
def trans_history_view(request):
"""
Vista para mostrar el historial de transacciones de la cuenta y sus personajes.
"""
- username = request.session.get('username') # Obtener el nombre de usuario de la sesin
+ username = request.session.get('username') # Obtener el nombre de usuario de la sesión
if username:
# Filtramos las transacciones que corresponden al usuario y a los personajes asociados
@@ -2335,22 +2497,90 @@ def trans_history_view(request):
# Renderizamos la vista con el historial de transacciones
return render(request, 'account/trans_history.html', {'transactions': transactions})
-
-def ban_history_view(request):
- return render(request, 'account/ban_history.html')
+def get_account_id(username):
+ # Consulta para obtener el account_id a partir del username
+ with connections['acore_auth'].cursor() as cursor:
+ cursor.execute("""
+ SELECT id
+ FROM account
+ WHERE username = %s
+ """, [username])
+ result = cursor.fetchone()
+ return result[0] if result else None
+
+
+def get_ban_history(account_id):
+ # Consulta de baneos de la cuenta
+ with connections['acore_auth'].cursor() as cursor:
+ cursor.execute("""
+ SELECT bandate, unbandate, banreason, active, account.username
+ FROM account_banned
+ JOIN account ON account_banned.id = account.id
+ WHERE account_banned.id = %s
+ """, [account_id])
+ account_bans = cursor.fetchall()
+
+ # Formatear las fechas
+ account_bans = [(format_datetime(ban[0]), format_datetime(ban[1]), ban[2], ban[3], ban[4]) for ban in account_bans]
+
+ # Consulta de baneos de los personajes asociados a la cuenta
+ with connections['acore_characters'].cursor() as cursor:
+ cursor.execute("""
+ SELECT bandate, unbandate, banreason, active, characters.name
+ FROM character_banned
+ JOIN characters ON character_banned.guid = characters.guid
+ WHERE characters.account = %s
+ """, [account_id])
+ character_bans = cursor.fetchall()
+
+ # Formatear las fechas
+ character_bans = [(format_datetime(ban[0]), format_datetime(ban[1]), ban[2], ban[3], ban[4]) for ban in character_bans]
+
+ return account_bans, character_bans
+
+
+def calculate_unmute_date(mute_date, mute_duration):
+ if isinstance(mute_date, int):
+ mute_date = datetime.fromtimestamp(mute_date)
+ return mute_date + timedelta(seconds=mute_duration)
+
+
+
+def ban_history_view(request):
+ # Verificar si el usuario tiene un `username` en la sesión
+ username = request.session.get('username')
+ if not username:
+ return redirect('login')
+
+ # Obtener el account_id a partir del username
+ account_id = get_account_id(username)
+ if not account_id:
+ return redirect('login') # O redirigir a otra página si no se encuentra el account_id
+
+ print(f"Account ID: {account_id}") # Depurar el account_id
+
+ account_bans, character_bans = get_ban_history(account_id)
+
+ return render(request, 'account/ban_history.html', {
+ 'account_bans': account_bans,
+ 'character_bans': character_bans,
+ 'now': datetime.now(),
+ })
+
+
def security_history_view(request):
username = request.session.get('username')
if not username:
- return redirect('login') # Si no est autenticado, redirigir al login
+ return redirect('login') # Si no está autenticado, redirigir al login
- # Obtener los ltimos 20 intentos de inicio de sesin
+ # Obtener los últimos 20 intentos de inicio de sesión
login_attempts = LoginAttempt.objects.filter(username=username).order_by('-timestamp')[:20]
return render(request, 'account/security_history.html', {'login_attempts': login_attempts})
def log_login_attempt(username, status, ip_address):
- # Registrar intento de inicio de sesin en el historial
+ # Registrar intento de inicio de sesión en el historial
LoginAttempt.objects.create(
username=username,
status=status,