import json
import base64
import binascii
import os
import hmac
import hashlib
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad

from translator.utils import *
from translator.commands_from_c2 import *
from translator.commands_from_implant import *

from mythic_container.TranslationBase import (
    TranslationContainer,
    TrGenerateEncryptionKeysMessage,
    TrGenerateEncryptionKeysMessageResponse,
    TrMythicC2ToCustomMessageFormatMessage,
    TrMythicC2ToCustomMessageFormatMessageResponse,
    TrCustomMessageToMythicC2FormatMessage,
    TrCustomMessageToMythicC2FormatMessageResponse
)

# ✅ Añade esta definición manual para compatibilidad
from enum import Enum

class TranslationContainerEncryptionType(Enum):
    NoneType = 0
    MythicEncrypts = 1



class angerona_translator(TranslationContainer):
    name = "angerona_translator"
    description = "Python translation service for the C agent Angerona"
    author = "OFSTeam"
    
    # Variables de clase para configuración de cifrado
    _crypto_type = "none"
    _enc_key = None
    
    def aes256_encrypt(self, plaintext: bytes) -> bytes:
        """
        Encrypt data using AES-256-CBC with HMAC-SHA256.
        Format matches agent: [IV(16 bytes)][Ciphertext(...)][HMAC(32 bytes)]
        """
        if not self._enc_key:
            print("[TRANSLATOR] ERROR: No encryption key available!")
            return plaintext
        
        # Generate random IV
        iv = os.urandom(16)
        
        # Create cipher
        cipher = AES.new(self._enc_key, AES.MODE_CBC, iv)
        
        # Pad and encrypt
        padded = pad(plaintext, AES.block_size)
        ciphertext = cipher.encrypt(padded)
        
        # Create HMAC over (IV + ciphertext)
        hmac_msg = iv + ciphertext
        mac = hmac.new(self._enc_key, hmac_msg, hashlib.sha256).digest()
        
        # Return: [IV(16)][Ciphertext][HMAC(32)] - matches agent format
        return iv + ciphertext + mac
    
    def aes256_decrypt(self, ciphertext: bytes) -> bytes:
        """
        Decrypt data using AES-256-CBC with HMAC-SHA256 validation.
        Format matches agent: [IV(16 bytes)][Ciphertext(...)][HMAC(32 bytes)]
        """
        if not self._enc_key:
            print("[TRANSLATOR] ERROR: No encryption key available!")
            return ciphertext
        
        if len(ciphertext) < 48:  # Minimum: 16 (IV) + 16 (min ciphertext) + 32 (HMAC)
            print(f"[TRANSLATOR] ERROR: Ciphertext too short! (length: {len(ciphertext)})")
            return ciphertext
        
        # Extract IV, encrypted data, and HMAC (agent format: [IV][Ciphertext][HMAC])
        iv = ciphertext[:16]
        recv_mac = ciphertext[-32:]  # HMAC at the end
        encrypted_data = ciphertext[16:-32]  # Ciphertext in the middle
        
        if len(encrypted_data) < 16:
            print(f"[TRANSLATOR] ERROR: Encrypted data too short! (length: {len(encrypted_data)})")
            return ciphertext
        
        # Verify HMAC over (IV + ciphertext)
        hmac_msg = iv + encrypted_data
        expected_mac = hmac.new(self._enc_key, hmac_msg, hashlib.sha256).digest()
        
        if not hmac.compare_digest(recv_mac, expected_mac):
            print("[TRANSLATOR] ERROR: HMAC verification failed!")
            print(f"[TRANSLATOR] Expected: {binascii.hexlify(expected_mac).decode()}")
            print(f"[TRANSLATOR] Received: {binascii.hexlify(recv_mac).decode()}")
            raise ValueError("HMAC verification failed")
        
        # Decrypt
        cipher = AES.new(self._enc_key, AES.MODE_CBC, iv)
        padded = cipher.decrypt(encrypted_data)
        
        # Unpad and return
        try:
            return unpad(padded, AES.block_size)
        except ValueError as e:
            print(f"[TRANSLATOR] ERROR: Padding error: {e}")
            raise

    async def generate_keys(self, inputMsg: TrGenerateEncryptionKeysMessage) -> TrGenerateEncryptionKeysMessageResponse:
        response = TrGenerateEncryptionKeysMessageResponse(Success=True)
        print(f"[TRANSLATOR] generate_keys called with {len(inputMsg.keys)} key(s)")
        
        if len(inputMsg.keys) > 0:
            # Store the encryption key
            self._enc_key = inputMsg.keys[0]
            print(f"[TRANSLATOR] Stored encryption key (length: {len(self._enc_key)})")
        else:
            print("[TRANSLATOR] No encryption keys provided")
            self._enc_key = None
        
        response.DecryptionKey = b""
        response.EncryptionKey = b""
        return response

    async def translate_to_c2_format(self, inputMsg: TrMythicC2ToCustomMessageFormatMessage) -> TrMythicC2ToCustomMessageFormatMessageResponse:
        response = TrMythicC2ToCustomMessageFormatMessageResponse(Success=True)
        print("[TRANSLATOR] translate_to_c2_format called (Mythic → Agent)")
        print("C2 --> IMPLANT :" + json.dumps(inputMsg.Message))

        if inputMsg.Message["action"] == "checkin":
            print("Response CHECKIN")
            response.Message = responseCheckin(inputMsg.Message["id"])

        elif inputMsg.Message["action"] == "get_tasking":
            print("Response TASKING")
            response.Message = responseTasking(inputMsg.Message["tasks"])  # base tasks
            print(f"[TRANSLATOR] Base tasking message: {len(response.Message)} bytes")
            # Append SOCKS array if present from Mythic
            socks_list = inputMsg.Message.get("socks", [])
            print(f"[TRANSLATOR] SOCKS list: {len(socks_list)} items")
            if socks_list:
                # Encode an extension block for C agent: 0xF5 | [len] | [records]
                # Each record: [Int32 server_id][Byte exit][Int32 b64len][b64]
                extension = bytearray()
                for s in socks_list:
                    sid = int(s.get("server_id", 0))
                    exitb = 1 if s.get("exit", False) else 0
                    data_str = s.get("data") or ""
                    b64 = data_str.encode() if data_str else b""
                    data_preview = data_str[:50] if data_str else "(null)"
                    print(f"[TRANSLATOR] SOCKS: sid={sid} exit={exitb} b64_len={len(b64)} data={data_preview}")
                    extension += sid.to_bytes(4, "big")
                    extension += bytes([exitb])
                    extension += len(b64).to_bytes(4, "big")
                    extension += b64
                socks_block = bytes([0xF5]) + len(extension).to_bytes(4, "big") + bytes(extension)
                print(f"[TRANSLATOR] SOCKS block total: {len(socks_block)} bytes (marker + len={5} + ext={len(extension)})")
                response.Message += socks_block
                print(f"[TRANSLATOR] Final message with SOCKS: {len(response.Message)} bytes")
            
            # Append RPFWD array if present from Mythic
            rpfwd_list = inputMsg.Message.get("rpfwd", [])
            print(f"[TRANSLATOR] RPFWD list: {len(rpfwd_list)} items")
            if rpfwd_list:
                # Encode an extension block for C agent: 0xF2 | [len] | [records]
                # Each record: [Int32 server_id][Byte exit][Int32 b64len][b64][Int32 port]
                extension = bytearray()
                for r in rpfwd_list:
                    sid = int(r.get("server_id", 0))
                    exitb = 1 if r.get("exit", False) else 0
                    data_str = r.get("data") or ""
                    b64 = data_str.encode() if data_str else b""
                    port = int(r.get("port", 0))
                    data_preview = data_str[:50] if data_str else "(null)"
                    print(f"[TRANSLATOR] RPFWD: sid={sid} exit={exitb} b64_len={len(b64)} port={port} data={data_preview}")
                    extension += sid.to_bytes(4, "big")
                    extension += bytes([exitb])
                    extension += len(b64).to_bytes(4, "big")
                    extension += b64
                    extension += port.to_bytes(4, "big")
                rpfwd_block = bytes([0xF2]) + len(extension).to_bytes(4, "big") + bytes(extension)
                print(f"[TRANSLATOR] RPFWD block total: {len(rpfwd_block)} bytes (marker + len={5} + ext={len(extension)})")
                response.Message += rpfwd_block
                print(f"[TRANSLATOR] Final message with RPFWD: {len(response.Message)} bytes")

        elif inputMsg.Message["action"] == "post_response":
            print("[TRANSLATOR] Response POSTREP recibido de Mythic")
            print(f"[TRANSLATOR] POSTREP Message keys: {list(inputMsg.Message.keys())}")
            print(f"[TRANSLATOR] POSTREP Message completo: {json.dumps(inputMsg.Message, indent=2)[:1000]}...")
            # Handle case where responses might not be present (e.g., error response from Mythic)
            responses = inputMsg.Message.get("responses", [])
            if responses:
                print(f"[TRANSLATOR] POSTREP tiene {len(responses)} respuestas")
                response.Message = responsePosting(responses)  # base responses
            else:
                # Empty response or error - send empty acknowledgment
                print("[WARN] post_response sin 'responses', enviando respuesta vacía")
                print(f"[WARN] POSTREP Message completo sin responses: {json.dumps(inputMsg.Message, indent=2)}")
                response.Message = len([]).to_bytes(4, "big")  # 0 responses
            socks_list = inputMsg.Message.get("socks", [])
            if socks_list:
                extension = bytearray()
                for s in socks_list:
                    sid = int(s.get("server_id", 0))
                    exitb = 1 if s.get("exit", False) else 0
                    data_str = s.get("data") or ""
                    b64 = data_str.encode() if data_str else b""
                    extension += sid.to_bytes(4, "big")
                    extension += bytes([exitb])
                    extension += len(b64).to_bytes(4, "big")
                    extension += b64
                response.Message += bytes([0xF5]) + len(extension).to_bytes(4, "big") + bytes(extension)
            
            # Append RPFWD array if present from Mythic
            rpfwd_list = inputMsg.Message.get("rpfwd", [])
            if rpfwd_list:
                extension = bytearray()
                for r in rpfwd_list:
                    sid = int(r.get("server_id", 0))
                    exitb = 1 if r.get("exit", False) else 0
                    data_str = r.get("data") or ""
                    b64 = data_str.encode() if data_str else b""
                    port = int(r.get("port", 0))
                    extension += sid.to_bytes(4, "big")
                    extension += bytes([exitb])
                    extension += len(b64).to_bytes(4, "big")
                    extension += b64
                    extension += port.to_bytes(4, "big")
                response.Message += bytes([0xF2]) + len(extension).to_bytes(4, "big") + bytes(extension)

        # ============================
        # NUEVOS COMANDOS SOCKS
        # ============================
        elif inputMsg.Message["action"] == "start_socks":
            print("Response START_SOCKS")
            # Construye un paquete de tipo "start_socks" con el puerto
            tasks = [{
                "command": "start_socks",
                "id": inputMsg.Message.get("id", "00000000-0000-0000-0000-000000000000"),
                "parameters": json.dumps({"port": int(inputMsg.Message.get("port", 1080))})
            }]
            response.Message = responseTasking(tasks)

        elif inputMsg.Message["action"] == "stop_socks":
            print("Response STOP_SOCKS")
            tasks = [{
                "command": "stop_socks",
                "id": inputMsg.Message.get("id", "00000000-0000-0000-0000-000000000000"),
                "parameters": ""
            }]
            response.Message = responseTasking(tasks)

        # ============================
        # NUEVOS COMANDOS RPFWD
        # ============================
        elif inputMsg.Message["action"] == "start_rpfwd":
            print("Response START_RPFWD")
            # Construye un paquete de tipo "start_rpfwd" con el puerto local
            local_port = int(inputMsg.Message.get("port", 8080))
            tasks = [{
                "command": "start_rpfwd",
                "id": inputMsg.Message.get("id", "00000000-0000-0000-0000-000000000000"),
                "parameters": json.dumps({"port": local_port})
            }]
            response.Message = responseTasking(tasks)

        elif inputMsg.Message["action"] == "stop_rpfwd":
            print("Response STOP_RPFWD")
            tasks = [{
                "command": "stop_rpfwd",
                "id": inputMsg.Message.get("id", "00000000-0000-0000-0000-000000000000"),
                "parameters": ""
            }]
            response.Message = responseTasking(tasks)

        # Apply encryption if needed (before sending to agent)
        if self._crypto_type == "aes256_hmac" and self._enc_key:
            print("[TRANSLATOR] Applying AES256-HMAC encryption before sending to agent")
            print(f"[TRANSLATOR] Plaintext message length: {len(response.Message)}")
            try:
                response.Message = self.aes256_encrypt(response.Message)
                print(f"[TRANSLATOR] Encrypted message length: {len(response.Message)}")
            except Exception as e:
                print(f"[TRANSLATOR] Encryption failed: {e}")
                # Continue without encryption if it fails
                pass
        
        return response


    def extract_socks_block(self, data):
        """Extrae el bloque SOCKS (0xF5) del mensaje del implante y lo parsea."""
        socks_array = []
        clean_data = data
        
        # Buscar el marcador 0xF5
        cursor = 0
        while cursor + 5 <= len(data):
            if data[cursor] == 0xF5:
                print(f"[TRANSLATOR] ¡Bloque SOCKS 0xF5 encontrado en offset {cursor}!")
                # Leer longitud del bloque
                ext_len = int.from_bytes(data[cursor+1:cursor+5], "big")
                print(f"[TRANSLATOR] Longitud del bloque SOCKS: {ext_len} bytes")
                
                if cursor + 5 + ext_len > len(data):
                    print(f"[TRANSLATOR] ERROR: bloque SOCKS truncado")
                    break
                
                # Parsear cada registro SOCKS dentro del bloque
                ecur = cursor + 5
                eend = cursor + 5 + ext_len
                while ecur + 9 <= eend:
                    sid = int.from_bytes(data[ecur:ecur+4], "big")
                    exitf = data[ecur+4]
                    b64len = int.from_bytes(data[ecur+5:ecur+9], "big")
                    ecur += 9
                    
                    if ecur + b64len > eend:
                        print(f"[TRANSLATOR] ERROR: registro SOCKS truncado")
                        break
                    
                    # Extraer datos base64
                    b64_data = None
                    if b64len > 0:
                        b64_data = data[ecur:ecur+b64len].decode('ascii')
                    
                    socks_record = {
                        "server_id": sid,
                        "exit": bool(exitf),
                        "data": b64_data
                    }
                    socks_array.append(socks_record)
                    print(f"[TRANSLATOR] SOCKS record: sid={sid} exit={exitf} b64_len={b64len}")
                    
                    ecur += b64len
                
                # Remover el bloque SOCKS del mensaje
                clean_data = data[:cursor]
                print(f"[TRANSLATOR] Bloque SOCKS extraído, {len(socks_array)} registros encontrados")
                break
            cursor += 1
        
        return clean_data, socks_array

    def extract_rpfwd_block(self, data):
        """
        Extract RPFWD block (marker 0xF2) from agent message
        Format: [0xF2 marker][ext_len:4][server_id:4][exit:1][b64_len:4][base64_data][port:4]...
        Returns: (clean_data_without_rpfwd, rpfwd_array)
        """
        rpfwd_array = []
        clean_data = data
        
        # Buscar el marcador 0xF2
        cursor = 0
        while cursor + 5 <= len(data):
            if data[cursor] == 0xF2:
                print(f"[TRANSLATOR] ¡Bloque RPFWD 0xF2 encontrado en offset {cursor}!")
                # Leer longitud del bloque
                ext_len = int.from_bytes(data[cursor+1:cursor+5], "big")
                print(f"[TRANSLATOR] Longitud del bloque RPFWD: {ext_len} bytes")
                
                if cursor + 5 + ext_len > len(data):
                    print(f"[TRANSLATOR] ERROR: bloque RPFWD truncado")
                    break
                
                # Parsear cada registro RPFWD dentro del bloque
                ecur = cursor + 5
                eend = cursor + 5 + ext_len
                while ecur + 13 <= eend:  # 4 (sid) + 1 (exit) + 4 (b64len) + 4 (port) = 13
                    sid = int.from_bytes(data[ecur:ecur+4], "big")
                    exitf = data[ecur+4]
                    b64len = int.from_bytes(data[ecur+5:ecur+9], "big")
                    ecur += 9
                    
                    if ecur + b64len + 4 > eend:  # Need space for port too
                        print(f"[TRANSLATOR] ERROR: registro RPFWD truncado")
                        break
                    
                    # Extraer datos base64
                    b64_data = None
                    if b64len > 0:
                        b64_data = data[ecur:ecur+b64len].decode('ascii')
                    
                    ecur += b64len
                    
                    # Leer puerto
                    port = int.from_bytes(data[ecur:ecur+4], "big")
                    ecur += 4
                    
                    rpfwd_record = {
                        "server_id": sid,
                        "exit": bool(exitf),
                        "data": b64_data,
                        "port": port
                    }
                    rpfwd_array.append(rpfwd_record)
                    print(f"[TRANSLATOR] RPFWD record: sid={sid} exit={exitf} b64_len={b64len} port={port}")
                
                # Remover el bloque RPFWD del mensaje
                clean_data = data[:cursor]
                print(f"[TRANSLATOR] Bloque RPFWD extraído, {len(rpfwd_array)} registros encontrados")
                break
            cursor += 1
        
        return clean_data, rpfwd_array

    async def translate_from_c2_format(self, inputMsg: TrCustomMessageToMythicC2FormatMessage) -> TrCustomMessageToMythicC2FormatMessageResponse:
        response = TrCustomMessageToMythicC2FormatMessageResponse(Success=True)
        print("[TRANSLATOR] translate_from_c2_format called (Agent → Mythic)")
        print(f"[TRANSLATOR] Received message length: {len(inputMsg.Message)} bytes")
        
        # Decrypt if encryption is enabled (agent encrypts before sending)
        # Format: Base64(UUID_agente(36) + AES256(...))
        data = inputMsg.Message
        if self._crypto_type == "aes256_hmac" and self._enc_key:
            print("[TRANSLATOR] Decrypting message from agent...")
            print(f"[TRANSLATOR] Message length before decryption: {len(data)} bytes")
            try:
                # Extract agent UUID (first 36 bytes) if present
                # The agent sends: Base64(UUID_agente + AES256(POST_RESPONSE + UUID_tarea + ...))
                # After Base64 decode, we have: UUID_agente + [IV][Ciphertext][HMAC]
                if len(data) >= 36:
                    # Check if first 36 bytes look like a UUID (ASCII hex with dashes)
                    potential_uuid = data[:36]
                    try:
                        uuid_str = potential_uuid.decode('ascii', errors='replace')
                        # Simple check: UUID format has dashes at positions 8, 13, 18, 23
                        if (len(uuid_str) == 36 and uuid_str[8] == '-' and uuid_str[13] == '-' and 
                            uuid_str[18] == '-' and uuid_str[23] == '-'):
                            # This looks like a UUID, extract it
                            agent_uuid = data[:36]
                            encrypted_data = data[36:]
                            print(f"[TRANSLATOR] Extracted agent UUID: {agent_uuid.decode('ascii', errors='replace')}")
                            print(f"[TRANSLATOR] Encrypted data length: {len(encrypted_data)} bytes")
                            data = self.aes256_decrypt(encrypted_data)
                            print(f"[TRANSLATOR] Decrypted message length: {len(data)} bytes")
                        else:
                            # Doesn't look like UUID, try decrypting the whole thing
                            print("[TRANSLATOR] First 36 bytes don't look like UUID, trying to decrypt whole message")
                            data = self.aes256_decrypt(data)
                            print(f"[TRANSLATOR] Decrypted message length: {len(data)} bytes")
                    except Exception as uuid_e:
                        print(f"[TRANSLATOR] Error checking for UUID: {uuid_e}, trying to decrypt whole message")
                        data = self.aes256_decrypt(data)
                        print(f"[TRANSLATOR] Decrypted message length: {len(data)} bytes")
                else:
                    # Message too short, try decrypting anyway
                    print("[TRANSLATOR] Message too short for UUID extraction, trying to decrypt")
                    data = self.aes256_decrypt(data)
                    print(f"[TRANSLATOR] Decrypted message length: {len(data)} bytes")
            except Exception as e:
                print(f"[TRANSLATOR] ERROR: Decryption failed: {e}")
                response.Success = False
                response.Error = f"Decryption failed: {str(e)}"
                return response
        # Removed excessive hex dump - use debug logging if needed
        
        # Extract SOCKS and RPFWD blocks if exist (after first command byte)
        # Note: Now data is plaintext (decrypted if encryption was used)
        clean_data, socks_array = self.extract_socks_block(data[1:])
        clean_data, rpfwd_array = self.extract_rpfwd_block(clean_data)

        if data[0] == commands["checkin"]["hex_code"]:
            print("CHECK IN")
            response.Message = checkIn(clean_data)

        elif data[0] == commands["get_tasking"]["hex_code"]:
            print("GET TASKING")
            response.Message = getTasking(clean_data)
            # Agregar array SOCKS si existe
            if socks_array:
                response.Message["socks"] = socks_array
                print(f"[TRANSLATOR] Agregados {len(socks_array)} registros SOCKS a GET TASKING")
            # Agregar array RPFWD si existe
            if rpfwd_array:
                response.Message["rpfwd"] = rpfwd_array
                print(f"[TRANSLATOR] Agregados {len(rpfwd_array)} registros RPFWD a GET TASKING")

        elif data[0] == commands["post_response"]["hex_code"]:
            print("POST RESPONSE")
            print(f"[DEBUG] POST_RESPONSE - data length: {len(data)} bytes")
            # Removed hex dump - use debug logging if needed
            print(f"[DEBUG] POST_RESPONSE - clean_data length: {len(clean_data)} bytes")
            # Removed hex dump - use debug logging if needed
            response.Message = postResponse(clean_data)
            # Agregar array SOCKS si existe
            if socks_array:
                response.Message["socks"] = socks_array
                print(f"[TRANSLATOR] Agregados {len(socks_array)} registros SOCKS a POST RESPONSE")
            # Agregar array RPFWD si existe
            if rpfwd_array:
                response.Message["rpfwd"] = rpfwd_array
                print(f"[TRANSLATOR] Agregados {len(rpfwd_array)} registros RPFWD a POST RESPONSE")

        # ============================
        # NUEVOS COMANDOS SOCKS
        # ============================
        elif data[0] == commands["start_socks"]["hex_code"]:
            print("START SOCKS")
            response.Message = startSocks(clean_data)

        elif data[0] == commands["stop_socks"]["hex_code"]:
            print("STOP SOCKS")
            response.Message = stopSocks(clean_data)

        # Note: response.Message is a dict when using translation containers
        # The HTTP profile will handle the actual byte encryption on the wire
        # We don't need to encrypt here since the translator returns dict structures
        # that Mythic will then encode and the HTTP profile will handle encryption

        return response

    def get_encryption_type(self, build_parameters: dict) -> TranslationContainerEncryptionType:
        """
        Permite a Mythic saber si el canal es cifrado o no (compatible con mythic_encrypts=True).
        Cuando crypto_type=aes256_hmac, el translator maneja el cifrado.
        El agente cifra los mensajes antes de enviarlos, el translator los descifra.
        """
        crypto = None
        enc_key_b64 = None
        
        # Extract crypto_type and enc_key from AESPSK dict (same as builder)
        for key, val in build_parameters.items():
            if isinstance(val, dict):
                if key == "AESPSK" or key == "aespsk":
                    # Extract crypto_type from 'value' field
                    if 'value' in val:
                        crypto = val['value'].lower()
                        print(f"[TRANSLATOR] Found crypto_type in AESPSK['value']: {crypto}")
                    # Extract enc_key
                    if 'enc_key' in val:
                        enc_key_b64 = val['enc_key']
                elif 'enc_key' in val:
                    enc_key_b64 = val['enc_key']
        
        # Fallback: check for direct crypto_type parameter
        if not crypto:
            crypto = build_parameters.get("crypto_type", "").lower()
        
        print(f"[TRANSLATOR] get_encryption_type: crypto_type={crypto}, enc_key={'present' if enc_key_b64 else 'missing'}")
        
        # Store crypto_type for use in translate methods
        self._crypto_type = crypto
        
        # Extract and decode enc_key
        if enc_key_b64:
            try:
                self._enc_key = base64.b64decode(enc_key_b64) if enc_key_b64 else None
                if self._enc_key:
                    print(f"[TRANSLATOR] Extracted enc_key (length: {len(self._enc_key)})")
                else:
                    print("[TRANSLATOR] enc_key is empty")
            except Exception as e:
                print(f"[TRANSLATOR] ERROR extracting enc_key: {e}")
                self._enc_key = None
        else:
            self._enc_key = None
        
        if crypto == "none" or not crypto:
            print("[TRANSLATOR] Returning NoneType")
            return TranslationContainerEncryptionType.NoneType
        
        print("[TRANSLATOR] Returning MythicEncrypts")
        return TranslationContainerEncryptionType.MythicEncrypts