hasher-matcher-actioner/hmalib/scripts/cli/shell.py (105 lines of code) (raw):
#! /usr/bin/env python3
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
import cmd
import os
import argparse
import time
import threading
import uuid
import json
import datetime
from dataclasses import dataclass
import numpy as np
import pandas as pd
import typing as t
import hmalib.scripts.common.utils as utils
import hmalib.scripts.cli.command_base as base
from hmalib.scripts.common.client_lib import DeployedInstanceClient
from hmalib.scripts.common.listener import Listener
from hmalib.scripts.common.submitter import Submitter
from hmalib.common.classification_models import ClassificationLabel
from hmalib.common.configs.evaluator import ActionLabel, ActionRule
from hmalib.common.configs.actioner import ActionPerformer, WebhookPostActionPerformer
class ShellCommand(base.Command, base.NeedsAPIAccess):
"""
Prototype shell using HMA utils to interact via the API.
"""
@classmethod
def init_argparse(cls, ap: argparse.ArgumentParser) -> None:
ap.add_argument(
"--cmd",
help=f"run one command and exit. Options: {HMAShell.get_commands()}",
)
def __init__(
self,
cmd: str = "",
) -> None:
self.cmd = cmd
@classmethod
def get_name(cls) -> str:
return "shell"
@classmethod
def get_help(cls) -> str:
return "open interactive shell OR run single command (via --cmd)"
def execute(self, api: utils.HasherMatcherActionerAPI) -> None:
if self.cmd:
HMAShell(api).onecmd(self.cmd)
else:
HMAShell(api).cmdloop()
class HMAShell(cmd.Cmd):
intro = "Welcome! Type help or ? to list commands.\n"
prompt = "> "
def __init__(self, api: utils.HasherMatcherActionerAPI):
super(HMAShell, self).__init__()
self.api = api
# Query Commands
def do_dataset_configs(self, arg):
"Get list of current dataset configs: dataset_configs"
print(self._format_json_object_to_str(self.api.get_dataset_configs()))
def do_matches(self, arg):
"Get list of current match objects: matches"
matches = self.api.get_all_matches()
print(self._format_json_object_to_str(matches))
print(f"Total Matches: {len(matches)}")
def do_actions(self, arg):
"Get list of current actions: actions"
print(self._format_json_object_to_str(self.api.get_actions()))
def do_action_rules(self, arg):
"Get list of current action_rules: action_rules"
print(self._format_json_object_to_str(self.api.get_action_rules()))
# Query Content Commands
def do_hash_details_for_id(self, arg):
"Get hash_details for content id: hash_details_for_id <content id>"
print(self._format_json_object_to_str(self.api.get_content_hash_details(arg)))
def do_matches_for_id(self, arg):
"Get matches for content id: matches_for_id <content id>"
print(self._format_json_object_to_str(self.api.get_content_matches(arg)))
def do_matches_for_hash(self, arg):
"Get matches for a hash: matches_for_hash [pdq|video_md5] <hash>"
arg_lst = arg.split()
signal_type = arg_lst[0]
hash_val = arg_lst[1]
print(
self._format_json_object_to_str(
self.api.get_matches_for_hash(signal_type, hash_val)
)
)
def do_action_history_for_id(self, arg):
"Get action_history for content id: action_history_for_id <content id>"
print(self._format_json_object_to_str(self.api.get_content_action_history(arg)))
# Create Commands
# Submit Commands
# TODO
# Test Commands
def do_run_basic_test(self, arg):
"Set up, run, and cleanup a basic test: run_basic_test"
DeployedInstanceClient(api=self.api).run_basic_test()
# Utility commands
def do_quit(self, arg):
"Close the shell: quit"
print("\nClosing Shell...\n")
return True
def _format_json_object_to_str(self, json_object):
return json.dumps(json_object, indent=2)
@classmethod
def get_commands(cls):
names = dir(cls)
cmds = []
names.sort()
# There can be duplicates if routines overridden
prevname = ""
for name in names:
if name[:3] == "do_":
if name == prevname:
continue
prevname = name
cmd = name[3:]
cmds.append(cmd)
return cmds