python-threatexchange/threatexchange/fb_threatexchange/collab_config.py (58 lines of code) (raw):

#!/usr/bin/env python # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved """ A wrapper around the collaboration config file. This file controls the behavior of the all-in-one command, and roughly corresponds to a single-signal sharing usecase. """ import json import re import typing as t from . import descriptor class CollaborationConfig: KEY_NAME = "name" KEY_PRIVACY_GROUPS = "privacy_groups" KEY_LABELS = "labels" KEY_SAMPLE_TAG = "sample_tag" def __init__( self, name: str, labels: t.Dict[str, t.Any], privacy_groups: t.List[int], sample_tag: t.Optional[str] = None, show_safe_list=False, # (safe_list == signals only listed as NON_MALICIOUS, e.g. sample data) ): self.name = name self.privacy_groups = privacy_groups self.labels = labels self.sample_tag = sample_tag self.show_safe_list = show_safe_list @property def default_state_dir_name(self) -> str: return re.sub("\W+", "_", self.name.lower()) @property def labels_for_collaboration(self) -> t.Set[str]: ret = set(self.labels) ret.update(descriptor.ThreatDescriptor.SPECIAL_TAGS) return ret @classmethod def load(cls, file: t.IO): content = json.load(file) return cls( content.get(cls.KEY_NAME, "Sample Config"), content[cls.KEY_LABELS], content.get(cls.KEY_PRIVACY_GROUPS, []), content.get(cls.KEY_SAMPLE_TAG), ) def store(self, filename: str): with open(filename, "w") as f: out = { self.KEY_NAME: self.name, self.KEY_LABELS: self.labels, self.KEY_PRIVACY_GROUPS: self.privacy_groups, } if self.sample_tag: out[self.KEY_SAMPLE_TAG] = self.sample_tag json.dump(out, f, indent=4) @classmethod def get_example_config(cls) -> "CollaborationConfig": """ Get a config to access the public sample data under media_priority_samples """ return cls( name="ThreatExchange Samples", labels={"media_priority_samples": {}}, privacy_groups=[], sample_tag="media_priority_samples", show_safe_list=True, # Show sample data (lone NON_MALICIOUS descriptors) )