import mythic_container
from mythic_container import MythicCommandBase
import json
import sys
from .logging import logger
from mythic_container.MythicGoRPC import *
from collections.abc import Callable, Awaitable


class MythicRPCStatus:
    Success = "success"
    Error = "error"

    def __init__(self, status: str):
        self.status = status

    def __str__(self):
        return self.status

    def __eq__(self, obj):
        if isinstance(obj, str):
            return self.status == obj
        elif isinstance(obj, MythicRPCStatus):
            return self.status == obj.status
        elif isinstance(obj, MythicCommandBase.MythicStatus):
            return self.status == obj.status
        else:
            return False


RPCStatus = MythicRPCStatus


class RPCResponse:
    def __init__(self, resp: dict = None):
        self._raw_resp = resp
        self.status = ""
        self.response = {}
        self.error = None
        if "status" in resp:
            status = resp.pop("status")
            if status == "success":
                self.status = MythicRPCStatus.Success
                self.response = resp.pop("response", None)
                self.error = None
            else:
                self.status = MythicRPCStatus.Error
                self.error = resp["error"]
                self.response = resp.pop("response", None)
        elif "success" in resp:
            success = resp.pop("success")
            if success:
                self.status = MythicRPCStatus.Success
                self.error = resp.pop("error", None)
                self.response = resp
            else:
                self.status = MythicRPCStatus.Error
                self.error = resp.pop("error", None)
                self.response = resp

    @property
    def status(self):
        return self._status

    @status.setter
    def status(self, status):
        self._status = status

    @property
    def error(self):
        return self._error

    @error.setter
    def error(self, error):
        self._error = error

    @property
    def response(self):
        return self._response

    @response.setter
    def response(self, response):
        self._response = response

    def __str__(self):
        return json.dumps(self._raw_resp)


async def legacyGetFile(x: dict) -> RPCResponse:
    resp = await SendMythicRPCFileSearch(MythicRPCFileSearchMessage(
        TaskID=x.pop("task_id", None),
        CallbackID=x.pop("callback_id", None),
        LimitByCallback=x.pop("limit_by_callback", None),
        MaxResults=x.pop("max_results", None),
        Filename=x.pop("filename", None),
        AgentFileID=x.pop("file_id", None),
        Comment=x.pop("comment", None),
    ))

    if x.pop("get_contents", False):
        logger.warning(
            "the get_contents flag on the 'get_file' RPC Call is no longer supported. Please use the new SendMythicRPCFileGetContent function instead.")
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
        "response": [y.to_json() for y in resp.Files] if resp.Files is not None else []
    })


async def legacySearchPayloads(x: dict) -> RPCResponse:
    resp = await SendMythicRPCPayloadSearch(MythicRPCPayloadSearchMessage(
        CallbackID=x.pop("callback_id", None),
        PayloadUUID=None,
        Description=x.pop("description", None),
        Filename=x.pop("filename", None),
        PayloadTypes=x.pop("payload_types", None),
        IncludeAutoGeneratedPayloads=x.pop("include_auto_generated", None),
    ))
    if x.pop("build_parameters", None) is not None:
        logger.warning(
            "the build_parameters argument on the `search_payloads' RPC call is no longer supported. Please use the new SendMythicRPCPayloadSearch function instead.")
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
        "response": [y.to_json() for y in resp.Payloads] if resp.Payloads is not None else []
    })


async def legacyGetTasks(x: dict) -> RPCResponse:
    resp = await SendMythicRPCTaskSearch(MythicRPCTaskSearchMessage(
        TaskID=x.pop("task_id"),
        SearchHost=x.pop("host"),
        SearchAgentTaskID=x.pop("requested_uuid", None),
        SearchTaskID=x.pop("requested_id", None)
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
        "response": [y.to_json() for y in resp.Tasks] if resp.Tasks is not None else []
    })


async def legacyGetResponses(x: dict) -> RPCResponse:
    resp = await SendMythicRPCResponseSearch(MythicRPCResponseSearchMessage(
        TaskID=x.pop("task_id", None)
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
        "response": [y.to_json() for y in resp.Responses] if resp.Responses is not None else []
    })


async def legacyGetCommands(x: dict) -> RPCResponse:
    if x.pop("loaded_only", False):
        resp = await SendMythicRPCCallbackSearchCommand(MythicRPCCallbackSearchCommandMessage(
            CallbackID=x.pop("callback_id", None),
            SearchCommandNames=x.pop("commands", None),
        ))
        return RPCResponse({
            "status": "success" if resp.Success else "error",
            "error": resp.Error,
            "response": [y.to_json() for y in resp.Commands] if resp.Commands is not None else []
        })
    else:
        resp = await SendMythicRPCCommandSearch(MythicRPCCommandSearchMessage(
            SearchPayloadTypeName=x.pop("payload_type_name", None),
            SearchCommandNames=x.pop("commands", None),
            SearchOS=x.pop("os", None)
        ))
        return RPCResponse({
            "status": "success" if resp.Success else "error",
            "error": resp.Error,
            "response": [y.to_json() for y in resp.Commands] if resp.Commands is not None else []
        })


async def legacyAddCommandsToPayload(x: dict) -> RPCResponse:
    resp = await SendMythicRPCPayloadAddCommand(MythicRPCPayloadAddCommandMessage(
        PayloadUUID=x.pop("payload_uuid", None),
        Commands=x.pop("commands", None)
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyAddCommandsToCallback(x: dict) -> RPCResponse:
    resp = await SendMythicRPCCallbackAddCommand(MythicRPCCallbackAddCommandMessage(
        TaskID=x.pop("task_id", None),
        Commands=x.pop("commands", None)
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyGetCallbackInfo(x: dict) -> RPCResponse:
    resp = await SendMythicRPCCallbackSearch(MythicRPCCallbackSearchMessage(
        AgentCallbackID=x.pop("callback_id"),
        SearchCallbackID=x.pop("callback_id")
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
        "response": [y.to_json() for y in resp.Results] if resp.Results is not None else []
    })


async def legacyCreateAgentStorage(x: dict) -> RPCResponse:
    resp = await SendMythicRPCAgentStorageCreate(MythicRPCAgentstorageCreateMessage(
        UniqueID=x.pop("unique_id", None),
        DataToStore=x.pop("data", None)
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyGetAgentStorage(x: dict) -> RPCResponse:
    resp = await SendMythicRPCAgentStorageSearch(MythicRPCAgentStorageSearchMessage(
        SearchUniqueID=x.pop("unique_id", None)
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
        "response": [y.to_json() for y in resp.AgentStorageMessages] if resp.AgentStorageMessages is not None else []
    })


async def legacyDeleteAgentStorage(x: dict) -> RPCResponse:
    resp = await SendMythicRPCAgentStorageRemove(MythicRPCAgentStorageRemoveMessage(
        UniqueID=x.pop("unique_id", None)
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyCreatePayloadFromUUID(x: dict) -> RPCResponse:
    if x.pop("generate_new_random_values", None):
        logger.warning("the generate_new_random_values flag is no longer used - values are not randomized again")
    resp = await SendMythicRPCPayloadCreateFromUUID(MythicRPCPayloadCreateFromUUIDMessage(
        TaskID=x.pop("task_id", None),
        PayloadUUID=x.pop("payload_uuid", None),
        NewDescription=x.pop("new_description", None),
        NewFilename=x.pop("filename", None),
        RemoteHost=x.pop("remote_host", None)
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
        "response": resp.NewPayloadUUID
    })


async def legacyCreatePayloadFromScratch(x: dict) -> RPCResponse:
    resp = await SendMythicRPCPayloadCreateFromScratch(MythicRPCPayloadCreateFromScratchMessage(
        TaskID=x.pop("task_id", None),
        RemoteHost=x.pop("destination_host", None),
        PayloadConfiguration=MythicRPCPayloadConfiguration(**x)
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
        "response": resp.NewPayloadUUID
    })


async def legacyCreateProcesses(x: dict) -> RPCResponse:
    processData = x.pop("processes", [])
    resp = await SendMythicRPCProcessCreate(MythicRPCProcessesCreateMessage(
        TaskID=x.pop("task_id", None),
        Processes=[MythicRPCProcessCreateData(**x) for x in processData]
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyCreateProcess(x: dict) -> RPCResponse:
    resp = await SendMythicRPCProcessCreate(MythicRPCProcessesCreateMessage(
        TaskID=x.pop("task_id", None),
        Processes=[MythicRPCProcessCreateData(**x)]
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyCreateArtifact(x: dict) -> RPCResponse:
    artifactType = x.pop("base_artifact", None)
    if artifactType is None:
        artifactType = x.pop("artifact_type", None)
    resp = await SendMythicRPCArtifactCreate(MythicRPCArtifactCreateMessage(
        TaskID=x.pop("task_id", None),
        ArtifactMessage=x.pop("artifact", None),
        BaseArtifactType=artifactType,
        ArtifactHost=x.pop("host", None)
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyCreateKeylog(x: dict) -> RPCResponse:
    resp = await SendMythicRPCKeylogCreate(MythicRPCKeylogCreateMessage(
        TaskID=x.pop("task_id", None),
        Keylogs=[MythicRPCKeylogData(
            WindowTitle=x.pop("window_title", None),
            User=x.pop("user", None),
            Keystrokes=x.pop("keystrokes", None)
        )]
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyCreateOutput(x: dict) -> RPCResponse:
    resp = await SendMythicRPCResponseCreate(MythicRPCResponseCreateMessage(
        TaskID=x.pop("task_id", None),
        Response=x.pop("output", None)
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyCreateEventLogMessage(x: dict) -> RPCResponse:
    resp = await SendMythicRPCOperationEventLogCreate(MythicRPCOperationEventLogCreateMessage(
        TaskID=x.pop("task_id", None),
        Message=x.pop("message", None),
        MessageLevel="warning" if x.pop("warning") else "info"
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyCreateCredential(x: dict) -> RPCResponse:
    resp = await SendMythicRPCCredentialCreate(MythicRPCCredentialCreateMessage(
        TaskID=x.pop("task_id", None),
        Credentials=[MythicRPCCredentialData(
            CredentialType=x.pop("credential_type", None),
            Account=x.pop("account", None),
            Realm=x.pop("realm", None),
            Credential=x.pop("credential", None),
            Comment=x.pop("comment", None)
        )]
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyCredentialSearch(x: dict) -> RPCResponse:
    resp = await SendMythicRPCCredentialSearch(MythicRPCCredentialSearchMessage(
        TaskID=x.pop('task_id', None),
        Credential=MythicRPCCredentialData(
            CredentialType=x.pop("credential_type", None),
            Realm=x.pop("realm", None),
            Account=x.pop("account", None),
            Credential=x.pop("credential", None),
            Comment=x.pop("comment", None)
        )
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
        "response": [y.to_json() for y in resp.Credentials] if resp.Credentials is not None else []
    })


async def legacyCreateFileBrowser(x: dict) -> RPCResponse:
    resp = await SendMythicRPCFileBrowserCreate(MythicRPCFileBrowserCreateMessage(
        TaskID=x.pop("task_id", None),
        FileBrowser=MythicRPCFileBrowserData(
            Host=x.pop("host", None),
            Name=x.pop("name", None),
            ParentPath=x.pop("parent_path", None),
            Permissions=x.pop("permissions", None),
            AccessTime=x.pop("access_time", None),
            ModifyTime=x.pop("modify_time", None),
            IsFile=x.pop("is_file", None),
            Size=x.pop("size", None),
            Success=x.pop("success", None),
            UpdateDeleted=x.pop("update_deleted", None),
            Files=[MythicRPCFileBrowserDataChildren(**z) for z in x.pop("files", [])]
        )
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyCreatePayloadOnHost(x: dict) -> RPCResponse:
    resp = await SendMythicRPCPayloadOnHostCreate(MythicRPCPayloadOnHostCreateMessage(
        TaskID=x.pop("task_id", None),
        PayloadOnHost=MythicRPCPayloadOnHostCreateData(
            Host=x.pop("host", None),
            PayloadUUID=x.pop("payload_uuid", None)
        )
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyCreateCallbackToken(x: dict) -> RPCResponse:
    resp = await SendMythicRPCCallbackTokenCreate(MythicRPCCallbackTokenCreateMessage(
        TaskID=x.pop("task_id", None),
        CallbackTokens=[MythicRPCCallbackTokenData(
            Action="add",
            Host=x.pop("host", None),
            TokenId=x.pop("TokenId", None)
        )]
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyCreateToken(x: dict) -> RPCResponse:
    resp = await SendMythicRPCTokenCreate(MythicRPCTokenCreateMessage(
        TaskID=x.pop("task_id", None),
        Tokens=[Token(
            TokenID=x.pop("TokenId")
        )]
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyDeleteToken(x: dict) -> RPCResponse:
    resp = await SendMythicRPCTokenRemove(MythicRPCTokenRemoveMessage(
        TaskID=x.pop("task_id", None),
        Tokens=[Token(Action="remove", TokenID=x.pop("TokenId", None))]
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyDeleteFileBrowser(x: dict) -> RPCResponse:
    resp = await SendMythicRPCFileBrowserRemove(MythicRPCFileBrowserRemoveMessage(
        TaskID=x.pop("task_id", None),
        RemovedFiles=[MythicRPCRemoveFileData(
            Host=x.pop("host", None),
            Path=x.pop("file_path", None)
        )]
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyDeleteCallbackToken(x: dict) -> RPCResponse:
    resp = await SendMythicRPCCallbackTokenRemove(MythicRPCCallbackTokenRemoveMessage(
        TaskID=x.pop("task_id", None),
        CallbackTokens=[MythicRPCCallbackTokenData(
            Action="remove",
            TokenId=x.pop("TokenId")
        )]
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyUpdateCallback(x: dict) -> RPCResponse:
    resp = await SendMythicRPCCallbackUpdate(MythicRPCCallbackUpdateMessage(
        TaskID=x.pop("task_id", None),
        User=x.pop("user", None),
        Host=x.pop("host", None),
        PID=x.pop("pid", None),
        IP=x.pop('ip', None),
        ExternalIP=x.pop("external_ip", None),
        Description=x.pop("description", None),
        IntegrityLevel=x.pop("integrity_level", None),
        OS=x.pop('os', None),
        Architecture=x.pop("architecture", None),
        Domain=x.pop("domain", None),
        ExtraInfo=x.pop("extra_info", None),
        SleepInfo=x.pop("sleep_info", None)
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyUpdateTask(x: dict) -> RPCResponse:
    resp = await SendMythicRPCTaskUpdate(MythicRPCTaskUpdateMessage(
        TaskID=x.pop("task_id", None),
        UpdateStatus=x.pop("status", None),
        UpdateCompleted=x.pop("completed", None)
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyUpdateLoadedCommands(x: dict) -> RPCResponse:
    if x.pop("add", False):
        resp = await SendMythicRPCCallbackAddCommand(MythicRPCCallbackAddCommandMessage(
            TaskID=x.pop("task_id", None),
            Commands=x.pop("commands", None)
        ))
        return RPCResponse({
            "status": "success" if resp.Success else "error",
            "error": resp.Error,
        })
    else:
        resp = await SendMythicRPCCallbackRemoveCommand(MythicRPCCallbackRemoveCommandMessage(
            TaskID=x.pop("task_id", None),
            Commands=x.pop("commands", None)
        ))
        return RPCResponse({
            "status": "success" if resp.Success else "error",
            "error": resp.Error,
        })


async def legacyCreateSubtask(x: dict) -> RPCResponse:
    params = x.pop("params_dict", None)
    if params is None:
        params = x.pop("params_string", "")
    else:
        params = json.dumps(params)
    resp = await SendMythicRPCTaskCreateSubtask(MythicRPCTaskCreateSubtaskMessage(
        TaskID=x.pop('parent_task_id', None),
        SubtaskCallbackFunction=x.pop("subtask_callback_function", None),
        CommandName=x.pop("command", None),
        Params=params,
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyCreateSubtaskGroup(x: dict) -> RPCResponse:
    tasks = x.pop("tasks", [])
    tasks = [MythicRPCTaskCreateSubtaskGroupTasks(
        SubtaskCallbackFunction=y["subtask_callback_function"] if "subtask_callback_function" in y else None,
        CommandName=y["command"] if "command" in y else None,
        Params=y["params"] if "params" in y and isinstance(y["params"], str) else json.dumps(
            y["params"]) if "params" in y and isinstance(y["params"], dict) else ""
    ) for y in tasks]
    resp = await SendMythicRPCTaskCreateSubtaskGroup(MythicRPCTaskCreateSubtaskGroupMessage(
        TaskID=x.pop("parent_task_id", None),
        GroupName=x.pop("subtask_group_name", None),
        GroupCallbackFunction=x.pop("group_callback_function", None),
        Tasks=tasks
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyCreateCallback(x: dict) -> RPCResponse:
    resp = await SendMythicRPCCallbackCreate(MythicRPCCallbackCreateMessage(
        PayloadUUID=x.pop("payload_uuid", None),
        C2ProfileName=x.pop("c2_profile", None),
        EncryptionKey=x.pop("encryption_key", None),
        DecryptionKey=x.pop("decryption_key", None),
        CryptoType=x.pop("crypto_type", None)
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyCreateFile(x: dict) -> RPCResponse:
    task_id = x.pop("task_id", None)
    resp = await SendMythicRPCFileCreate(MythicRPCFileCreateMessage(
        TaskID=task_id,
        FileContents=base64.b64decode(x.pop("file", "")),
        DeleteAfterFetch=x.pop("delete_after_fetch", None),
        Filename=x.pop("saved_file_name", None),
        IsScreenshot=x.pop("is_screenshot", None),
        IsDownloadFromAgent=x.pop("is_download", None),
        RemotePathOnTarget=x.pop("remote_path", None),
        Comment=x.pop("comment", None),
        TargetHostName=x.pop('host', None)
    ))
    if resp.Success:
        fileSearch = await SendMythicRPCFileSearch(MythicRPCFileSearchMessage(
            TaskID=task_id, AgentFileID=resp.AgentFileId
        ))
        return RPCResponse({
            "status": "success" if resp.Success else "error",
            "error": resp.Error,
            "response": fileSearch.Files[0].to_json() if fileSearch.Files is not None and len(
                fileSearch.Files) > 0 else {}
        })
    else:
        return RPCResponse({
            "status": "success" if resp.Success else "error",
            "error": resp.Error,
            "response": resp.AgentFileId
        })


async def legacyGetFileContents(x: dict) -> RPCResponse:
    resp = await SendMythicRPCFileGetContent(MythicRPCFileGetContentMessage(
        AgentFileId=x.pop("agent_file_id")
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
        "response": resp.Content
    })


async def legacyGetFileForWrapper(x: dict) -> RPCResponse:
    if x.pop("get_contents", False):
        resp = await SendMythicRPCFileGetContent(MythicRPCFileGetContentMessage(
            AgentFileId=x.pop("file_id", None)
        ))
        return RPCResponse({
            "status": "success" if resp.Success else "error",
            "error": resp.Error,
            "response": resp.Content
        })
    else:
        resp = await SendMythicRPCFileSearch(MythicRPCFileSearchMessage(
            Filename=x.pop("filename", None),
            AgentFileID=x.pop("file_id", None)
        ))
        return RPCResponse({
            "status": "success" if resp.Success else "error",
            "error": resp.Error,
            "response": [y.to_json() for y in resp.Files] if resp.Files is not None else []
        })


async def legacyUpdateFile(x: dict) -> RPCResponse:
    resp = await SendMythicRPCFileUpdate(MythicRPCFileUpdateMessage(
        AgentFileID=x.pop("file_id", None),
        Comment=x.pop("comment", None),
        Filename=x.pop("filename", None),
        ReplaceContents=x.pop("contents", None)
    ))
    return RPCResponse({
        "status": "success" if resp.Success else "error",
        "error": resp.Error,
    })


async def legacyGetPayload(x: dict) -> RPCResponse:
    if x.pop("get_contents", False):
        resp = await SendMythicRPCPayloadGetContent(MythicRPCPayloadGetContentMessage(
            PayloadUUID=x.pop("payload_uuid", None)
        ))
        return RPCResponse({
            "status": "success" if resp.Success else "error",
            "error": resp.Error,
            "response": resp.Content
        })
    else:
        resp = await SendMythicRPCPayloadSearch(MythicRPCPayloadSearchMessage(
            PayloadUUID=x.pop("payload_uuid", None)
        ))
        return RPCResponse({
            "status": "success" if resp.Success else "error",
            "error": resp.Error,
            "response": [y.to_json() for y in resp.Payloads] if resp.Payloads is not None else []
        })


class MythicRPC:
    queueMap: dict[str, Callable[[dict], Awaitable[RPCResponse]]] = {
        "get_file": legacyGetFile,
        "search_payloads": legacySearchPayloads,
        "get_tasks": legacyGetTasks,
        "get_responses": legacyGetResponses,
        "get_task_for_id": legacyGetTasks,
        "get_commands": legacyGetCommands,
        "add_commands_to_payload": legacyAddCommandsToPayload,
        "add_commands_to_callback": legacyAddCommandsToCallback,
        "get_callback_info": legacyGetCallbackInfo,
        "create_agentstorage": legacyCreateAgentStorage,
        "get_agentstorage": legacyGetAgentStorage,
        "delete_agentstorage": legacyDeleteAgentStorage,
        "create_payload_from_uuid": legacyCreatePayloadFromUUID,
        "create_payload_from_parameters": legacyCreatePayloadFromScratch,
        "create_processes": legacyCreateProcesses,
        "create_process": legacyCreateProcess,
        "create_artifact": legacyCreateArtifact,
        "create_keylog": legacyCreateKeylog,
        "create_output": legacyCreateOutput,
        "create_event_message": legacyCreateEventLogMessage,
        "create_credential": legacyCreateCredential,
        "get_credential": legacyCredentialSearch,
        "create_file_browser": legacyCreateFileBrowser,
        "create_payload_on_host": legacyCreatePayloadOnHost,
        "create_callback_token": legacyCreateCallbackToken,
        "create_token": legacyCreateToken,
        "delete_token": legacyDeleteToken,
        "delete_file_browser": legacyDeleteFileBrowser,
        "delete_callback_token": legacyDeleteCallbackToken,
        "update_callback": legacyUpdateCallback,
        "update_task_status": legacyUpdateTask,
        "update_loaded_commands": legacyUpdateLoadedCommands,
        "create_subtask": legacyCreateSubtask,
        "create_subtask_group": legacyCreateSubtaskGroup,
        "create_callback": legacyCreateCallback,
        "create_file": legacyCreateFile,
        "get_file_contents": legacyGetFileContents,
        "get_file_for_wrapper": legacyGetFileForWrapper,
        "update_file": legacyUpdateFile,
        "get_payload": legacyGetPayload,
    }

    async def execute(self, function_name: str, **func_kwargs) -> RPCResponse:
        logger.warning(f"[-] MythicRPC().execute and this function, {function_name}, are deprecated and will be removed in the next major "
                        f"release. Please update to the corresponding SendMythicRPC* function")
        if function_name in self.queueMap:
            return await self.queueMap[function_name](func_kwargs)
        else:
            logger.error(f"[-] Unknown legacy RPC function {function_name} or function was completely removed")
            return RPCResponse({"status": "error", "error": "Unknown RPC Function name"})

    async def call_c2rpc(self, n: dict, receiver: str = None) -> RPCResponse:
        response = await mythic_container.RabbitmqConnection.SendRPCDictMessage(queue=receiver + "_rpc_queue",
                                                                                body=n)
        return RPCResponse(response)

    async def execute_c2rpc(self, c2_profile: str, function_name: str, message: str, task_id: int) -> RPCResponse:
        try:
            logger.warning(f"[-] MythicRPC().execute_c2rpc and this function, {function_name}, are deprecated and will be removed in the next major "
                            f"release. Please update to the corresponding SendMythicRPC* function")
            resp = await self.call_c2rpc(
                {"action": function_name,
                 "message": message,
                 "task_id": task_id
                 },
                c2_profile)
            return resp

        except Exception as e:
            print(str(sys.exc_info()[-1].tb_lineno) + " " + str(e))
            sys.stdout.flush()
            return RPCResponse({"status": "error", "error": "Failed to call function:\n" + str(e)})
