epstein-files 1.0.11__py3-none-any.whl → 1.0.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -65,8 +65,8 @@ EMAILER_ID_REGEXES: dict[str, re.Pattern] = {
65
65
  BORIS_NIKOLIC: re.compile(r'(boris )?nikolic?', re.IGNORECASE),
66
66
  BRAD_EDWARDS: re.compile(r'Brad(ley)?(\s*J(.?|ames))?\s*Edwards', re.IGNORECASE),
67
67
  BRAD_KARP: re.compile(r'Brad (S.? )?Karp|Karp, Brad', re.IGNORECASE),
68
- 'Dangene and Jennie Enterprise': re.compile(r'Dangene and Jennie Enterprise?', re.IGNORECASE),
69
- DANNY_FROST: re.compile(r'Frost, Danny|frostd@dany.nyc.gov', re.IGNORECASE),
68
+ DANGENE_AND_JENNIE_ENTERPRISE: re.compile(r'Dangene and Jennie Enterprise?', re.IGNORECASE),
69
+ DANNY_FROST: re.compile(r'Frost, Danny|frostd@dany.nyc.gov|Danny\s*Frost', re.IGNORECASE),
70
70
  DARREN_INDYKE: re.compile(r'darren$|Darren\s*(K\.?\s*)?[il]n[dq]_?yke?|dkiesq', re.IGNORECASE),
71
71
  DAVID_FISZEL: re.compile(r'David\s*Fis?zel', re.IGNORECASE),
72
72
  DAVID_HAIG: re.compile(fr'{DAVID_HAIG}|Haig, David', re.IGNORECASE),
@@ -128,7 +128,7 @@ EMAILER_ID_REGEXES: dict[str, re.Pattern] = {
128
128
  PRINCE_ANDREW: re.compile(r'Prince Andrew|The Duke', re.IGNORECASE),
129
129
  REID_WEINGARTEN: re.compile(r'Weingarten, Rei[cdi]|Rei[cdi] Weingarten', re.IGNORECASE),
130
130
  RICHARD_KAHN: re.compile(r'rich(ard)? kahn?', re.IGNORECASE),
131
- ROBERT_D_CRITTON: re.compile(r'Robert D.? Critton Jr.?', re.IGNORECASE),
131
+ ROBERT_D_CRITTON_JR: re.compile(r'Robert D.? Critton Jr.?', re.IGNORECASE),
132
132
  ROBERT_LAWRENCE_KUHN: re.compile(r'Robert\s*(Lawrence)?\s*Kuhn', re.IGNORECASE),
133
133
  ROBERT_TRIVERS: re.compile(r'tri[vy]ersr@gmail|Robert\s*Trivers?', re.IGNORECASE),
134
134
  ROSS_GOW: re.compile(fr"{ROSS_GOW}|ross@acuityreputation.com", re.IGNORECASE),
@@ -163,6 +163,7 @@ EMAILERS = [
163
163
  DEEPAK_CHOPRA,
164
164
  GLENN_DUBIN,
165
165
  GORDON_GETTY,
166
+ 'Kevin Bright',
166
167
  'Jack Lang',
167
168
  JACK_SCAROLA,
168
169
  JAY_LEFKOWITZ,
@@ -257,7 +258,6 @@ JP_MORGAN_EYE_ON_THE_MARKET = f"Eye On The Market"
257
258
  LAWRENCE_KRAUSS_ASU_ORIGINS = f"{LAWRENCE_KRAUSS}'s ASU Origins Project"
258
259
  KEN_STARR_LETTER = f"letter to judge overseeing Epstein's criminal prosecution, mentions Alex Acosta"
259
260
  MICHAEL_WOLFF_EPSTEIN_ARTICLE_DRAFT = f"draft of an unpublished article about Epstein by {MICHAEL_WOLFF} written ca. 2014/2015"
260
- NERIO_ALESSANDRI = 'Nerio Alessandri (Founder and Chairman of Technogym S.p.A. Italy)'
261
261
  NIGHT_FLIGHT_BOOK = f'"Night Flight" (draft)'
262
262
  NOBEL_CHARITABLE_TRUST = 'Nobel Charitable Trust'
263
263
  OBAMA_JOKE = 'joke about Obama'
@@ -265,12 +265,11 @@ PALM_BEACH_CODE_ENFORCEMENT = f'{PALM_BEACH} Code Enforcement'
265
265
  PALM_BEACH_TSV = f"TSV of {PALM_BEACH} property"
266
266
  PALM_BEACH_WATER_COMMITTEE = f'{PALM_BEACH} Water Committee'
267
267
  PATTERSON_BOOK_SCANS = f'pages of "Filthy Rich: The Shocking True Story of {JEFFREY_EPSTEIN}"'
268
- SHIMON_POST = 'The Shimon Post'
268
+ REAL_DEAL_ARTICLE = 'article by Keith Larsen'
269
269
  SHIMON_POST_ARTICLE = f'selection of articles about the mideast'
270
270
  SINGLE_PAGE = 'single page of'
271
271
  STRANGE_BEDFELLOWS = "'Strange Bedfellows' list of invitees f. Johnny Depp, Woody Allen, Obama, and more"
272
272
  SWEDISH_LIFE_SCIENCES_SUMMIT = f"{BARBRO_C_EHNBOM}'s Swedish American Life Science Summit (SALSS)"
273
- THE_REAL_DEAL_ARTICLE = 'article by Keith Larsen'
274
273
  TRUMP_DISCLOSURES = f"Donald Trump financial disclosures from U.S. Office of Government Ethics"
275
274
  UBS_CIO_REPORT = 'CIO Monthly Extended report'
276
275
  UN_GENERAL_ASSEMBLY = '67th U.N. General Assembly'
@@ -500,7 +499,7 @@ EMAILS_CONFIG = [
500
499
  EmailCfg(
501
500
  id='029977',
502
501
  author=LAWRANCE_VISOSKI,
503
- recipients=[JEFFREY_EPSTEIN, DARREN_INDYKE, LESLEY_GROFF, RICHARD_KAHN] + FLIGHT_IN_2012_PEOPLE,
502
+ recipients=cast(list[str | None], [JEFFREY_EPSTEIN, DARREN_INDYKE, LESLEY_GROFF, RICHARD_KAHN] + FLIGHT_IN_2012_PEOPLE),
504
503
  attribution_reason=LARRY_REASON,
505
504
  duplicate_ids=['031129'],
506
505
  ),
@@ -508,7 +507,7 @@ EMAILS_CONFIG = [
508
507
  EmailCfg(id='033488', author=LAWRANCE_VISOSKI, duplicate_ids=['033154']),
509
508
  EmailCfg(id='033309', author=LINDA_STONE, attribution_reason='"Co-authored with iPhone autocorrect"'),
510
509
  EmailCfg(id='017581', author='Lisa Randall', attribution_reason='reply header'),
511
- EmailCfg(id='026609', author='Mark Green', attribution_reason='Actually a fwd'),
510
+ EmailCfg(id='026609', author='Mark Green', attribution_reason='Actually a fwd, Mark Green is in signature'),
512
511
  EmailCfg(id='030472', author=MARTIN_WEINBERG, attribution_reason='Maybe. in reply', is_attribution_uncertain=True),
513
512
  EmailCfg(id='030235', author=MELANIE_WALKER, attribution_reason='In fwd'),
514
513
  EmailCfg(id='032343', author=MELANIE_WALKER, attribution_reason='Name seen in later reply 032346'),
@@ -573,7 +572,7 @@ EMAILS_CONFIG = [
573
572
  attribution_reason='ends with "Respectfully, terry"',
574
573
  author=TERRY_KAFKA,
575
574
  fwded_text_after='From: Mike Cohen',
576
- recipients=[JEFFREY_EPSTEIN, MARK_EPSTEIN, MICHAEL_BUCHHOLTZ] + IRAN_DEAL_RECIPIENTS,
575
+ recipients=cast(list[str | None], [JEFFREY_EPSTEIN, MARK_EPSTEIN, MICHAEL_BUCHHOLTZ] + IRAN_DEAL_RECIPIENTS),
577
576
  duplicate_ids=['028482'],
578
577
  ),
579
578
  EmailCfg(id='029992', author=TERRY_KAFKA, attribution_reason='Quoted reply'),
@@ -665,6 +664,10 @@ EMAILS_CONFIG = [
665
664
  EmailCfg(id='029849', is_fwded_article=True, duplicate_ids=['033482']), # Fareed Zakaria: Trump sells America short),
666
665
  EmailCfg(id='032023', is_fwded_article=True, duplicate_ids=['032012']), # American-Israeli Cooperative Enterprise Newsletter
667
666
  EmailCfg(id='021758', is_fwded_article=True, duplicate_ids=['030616']), # Radar Online article about Epstein's early prison release
667
+ EmailCfg(id='031774', is_fwded_article=True), # Krassner fwd of Palmer Report article
668
+ EmailCfg(id='033345', is_fwded_article=True), # Krassner fwd of Palmer Report article
669
+ EmailCfg(id='029903', is_fwded_article=True), # Krassner fwd of Ann Coulter article about Epstein
670
+ EmailCfg(id='030266', is_fwded_article=True), # Krassner fwd of article about Dershowitz
668
671
  EmailCfg(id='030868', is_fwded_article=True), # 'He doesn't like this sh*t': Trump reportedly hates his job and his staff after 1 month
669
672
  EmailCfg(id='026755', is_fwded_article=True), # HuffPo
670
673
  EmailCfg(id='016218', is_fwded_article=True), # AT&T confirms it paid Trump lawyer Cohen for insights on Trump
@@ -710,6 +713,8 @@ EMAILS_CONFIG = [
710
713
  EmailCfg(id='033311', is_fwded_article=True), # 2016 election polls
711
714
  EmailCfg(id='026580', is_fwded_article=True), # NPR: Antigua: Land Of Sun, Sand, And Super Cheap
712
715
  EmailCfg(id='031340', is_fwded_article=True), # Article about Alex Jones threatening Robert Mueller
716
+ EmailCfg(id='030209', is_fwded_article=True), # Atlantic Council Syria: Blackberry Diplomacy
717
+ EmailCfg(id='026605', is_fwded_article=True), # Article about Ruemmler turning down attorney general job by NEDRA PICKLER
713
718
  EmailCfg(id='033297', is_fwded_article=True, duplicate_ids=['033586']), # Sultan Sulayem fwding article about Trump and Russia
714
719
  EmailCfg(id='032475', timestamp=parse('2017-02-15 13:31:25')),
715
720
  EmailCfg(id='030373', timestamp=parse('2018-10-03 01:49:27')),
@@ -852,9 +857,9 @@ EMAILS_CONFIG = [
852
857
  EmailCfg(id='030015', fwded_text_after='Bill Clinton reportedly'),
853
858
  EmailCfg(id='026312', fwded_text_after='Steve Bannon trying to get on disgraced'),
854
859
  EmailCfg(id='031742', fwded_text_after="Trump's former campaign manager Paul Manafort"),
855
- EmailCfg(id='012197_4', fwded_text_after="Thanks -- Jay"),
856
860
  EmailCfg(id='028925', fwded_text_after='> on Jan 4, 2015'),
857
861
  EmailCfg(id='029773', fwded_text_after='Omar Quadhafi', duplicate_ids=['012685']),
862
+ EmailCfg(id='012197_4', fwded_text_after="Thanks -- Jay"),
858
863
  ]
859
864
 
860
865
 
@@ -925,6 +930,7 @@ OTHER_FILES_ARTICLES = [
925
930
  DocCfg(id='029865', author=LA_TIMES, description=f"front page article about {DEEPAK_CHOPRA} and young Iranians", date='2016-11-05'),
926
931
  DocCfg(id='026598', author=LA_TIMES, description=f"op-ed about why America needs a Ministry of Culture"),
927
932
  DocCfg(id='027024', author=LA_TIMES, description=f"Scientists Create Human Embryos to Make Stem Cells", date='2013-05-15'),
933
+ DocCfg(id='022811', author='Law.com', description='Sarah Ransome Identifies Herself in Epstein Sex Trafficking Case', date='2018-01-09'),
928
934
  DocCfg(id='031776', author='Law360', description=f"article about Michael Avenatti by Andrew Strickler"),
929
935
  DocCfg(id='023102', author=f'Litigation Daily', description=f"article about {REID_WEINGARTEN}", date='2015-09-04'),
930
936
  DocCfg(id='029340', author=f'MarketWatch', description=f'article about estate taxes, particularly Epstein\'s favoured GRATs'),
@@ -1186,7 +1192,7 @@ OTHER_FILES_LEGAL = [
1186
1192
  ]
1187
1193
 
1188
1194
  OTHER_FILES_CONFERENCES = [
1189
- DocCfg(id='014315', author=BOFA_MERRILL, description=f'2016 Future of Financials Conference'),
1195
+ DocCfg(id='014315', author=BOFA_MERRILL, description=f'2016 Future of Financials Conference, attached to 014312'),
1190
1196
  DocCfg(id='026825', author=DEUTSCHE_BANK, description=f"Asset & Wealth Management featured speaker bios"), # Really "Deutsche Asset" which may not be Deutsche Bank?
1191
1197
  DocCfg(id='023123', author=LAWRENCE_KRAUSS_ASU_ORIGINS, description=f"{STRANGE_BEDFELLOWS} (old draft)"),
1192
1198
  DocCfg(id='023120', author=LAWRENCE_KRAUSS_ASU_ORIGINS, description=STRANGE_BEDFELLOWS, duplicate_ids=['023121'], dupe_type='earlier'),
@@ -1335,8 +1341,8 @@ OTHER_FILES_PROPERTY = [
1335
1341
  DocCfg(id='016554', author=PALM_BEACH_CODE_ENFORCEMENT, description='board minutes', date='2008-07-17', duplicate_ids=['016616', '016574']),
1336
1342
  DocCfg(id='016636', author=PALM_BEACH_WATER_COMMITTEE, description=f"Meeting on January 29, 2009"),
1337
1343
  DocCfg(id='022417', author='Park Partners NYC', description=f"letter to partners in real estate project with architectural plans"),
1338
- DocCfg(id='027068', author=THE_REAL_DEAL, description=f"{THE_REAL_DEAL_ARTICLE} Palm House Hotel Bankruptcy and EB-5 Visa Fraud Allegations"),
1339
- DocCfg(id='029520', author=THE_REAL_DEAL, description=f"{THE_REAL_DEAL_ARTICLE} 'Lost Paradise at the Palm House'", date='2019-06-17'),
1344
+ DocCfg(id='027068', author=THE_REAL_DEAL, description=f"{REAL_DEAL_ARTICLE} Palm House Hotel Bankruptcy and EB-5 Visa Fraud Allegations"),
1345
+ DocCfg(id='029520', author=THE_REAL_DEAL, description=f"{REAL_DEAL_ARTICLE} 'Lost Paradise at the Palm House'", date='2019-06-17'),
1340
1346
  DocCfg(id='016597', author='Trump Properties LLC', description=f'appeal of some decision about Mar-a-Lago by {PALM_BEACH} authorities'),
1341
1347
  DocCfg(id='018743', description=f"Las Vegas property listing"),
1342
1348
  DocCfg(id='016695', description=f"{PALM_BEACH} property info (?)"),
@@ -1497,13 +1503,13 @@ OTHER_FILES_MISC = [
1497
1503
  DocCfg(id='032206', category=SKYPE_LOG, author=LAWRENCE_KRAUSS),
1498
1504
  DocCfg(id='032208', category=SKYPE_LOG, author=LAWRENCE_KRAUSS),
1499
1505
  DocCfg(id='032209', category=SKYPE_LOG, author=LAWRENCE_KRAUSS),
1506
+ DocCfg(id='032210', category=SKYPE_LOG, author='linkspirit', is_interesting=True),
1500
1507
  DocCfg(
1501
1508
  id='018224',
1502
1509
  category=SKYPE_LOG,
1503
- description=f'Skype conversations with linkspirit (French?) and {LAWRENCE_KRAUSS}',
1510
+ author=f'linkspirit (French?) and {LAWRENCE_KRAUSS}',
1504
1511
  is_interesting=True, # we don't know who linkspirit is yet
1505
1512
  ),
1506
- DocCfg(id='032210', category=SKYPE_LOG, description=f'Skype conversation with linkspirit', is_interesting=True),
1507
1513
  DocCfg(
1508
1514
  id='025147',
1509
1515
  author=BROCKMAN_INC,
@@ -21,12 +21,12 @@ ALL_NAMES = [v for k, v in vars(names).items() if isinstance(v, str) and CONSTAN
21
21
  PACIFIC_TZ = tz.gettz("America/Los_Angeles")
22
22
  TIMEZONE_INFO = {"PDT": PACIFIC_TZ, "PST": PACIFIC_TZ} # Suppresses annoying warnings from parse() calls
23
23
 
24
-
25
24
  collapse_newlines = lambda text: MULTINEWLINE_REGEX.sub('\n\n', text)
26
25
  date_str = lambda dt: dt.isoformat()[0:10] if dt else None
27
26
  escape_double_quotes = lambda text: text.replace('"', r'\"')
28
27
  escape_single_quotes = lambda text: text.replace("'", r"\'")
29
28
  iso_timestamp = lambda dt: dt.isoformat().replace('T', ' ')
29
+ remove_zero_time_from_timestamp_str = lambda dt: dt.isoformat().removesuffix('T00:00:00')
30
30
  uniquify = lambda _list: list(set(_list))
31
31
  without_falsey = lambda _list: [e for e in _list if e]
32
32
 
@@ -8,7 +8,7 @@ from dateutil.parser import parse
8
8
 
9
9
  from epstein_files.util.constant.names import *
10
10
  from epstein_files.util.constant.strings import *
11
- from epstein_files.util.data import without_falsey
11
+ from epstein_files.util.data import remove_zero_time_from_timestamp_str, without_falsey
12
12
 
13
13
  DuplicateType = Literal['earlier', 'quoted', 'redacted', 'same']
14
14
  Metadata = dict[str, bool | datetime | int | str | list[str | None] |dict[str, bool | str]]
@@ -47,12 +47,11 @@ FINANCIAL_REPORTS_AUTHORS = [
47
47
  ]
48
48
 
49
49
  # Fields like timestamp and author are better added from the Document object
50
- INVALID_FOR_METADATA = [
50
+ NON_METADATA_FIELDS = [
51
51
  'actual_text',
52
52
  'date',
53
53
  'id',
54
- 'timestamp',
55
- 'was_generated',
54
+ 'is_synthetic',
56
55
  ]
57
56
 
58
57
 
@@ -68,10 +67,10 @@ class DocCfg:
68
67
  date (str | None): If passed will be immediated parsed into the 'timestamp' field
69
68
  dupe_of_id (str | None): If this is a dupe the ID of the duplicated file. This file will be suppressed
70
69
  dupe_type (DuplicateType | None): The type of duplicate this file is or its 'duplicate_ids' are
71
- duplicate_ids (list[str]): Inverse of 'dupe_of_id' - this file will NOT be suppressed but 'duplicate_ids' will be
70
+ duplicate_ids (list[str]): IDs of *other* documents that are dupes of this document
72
71
  is_interesting (bool): Override other considerations and always consider this file interesting
73
72
  timestamp (datetime | None): Time this email was sent, file was created, article published, etc.
74
- was_generated (bool): True if this object was generated by the duplicate_cfgs() method
73
+ is_synthetic (bool): True if this config was generated by the duplicate_cfgs() method
75
74
  """
76
75
  id: str
77
76
  author: str | None = None
@@ -82,8 +81,8 @@ class DocCfg:
82
81
  dupe_type: DuplicateType | None = None
83
82
  duplicate_ids: list[str] = field(default_factory=list)
84
83
  is_interesting: bool = False
84
+ is_synthetic: bool = False
85
85
  timestamp: datetime | None = None
86
- was_generated: bool = False
87
86
 
88
87
  def __post_init__(self):
89
88
  if self.date:
@@ -94,13 +93,17 @@ class DocCfg:
94
93
 
95
94
  def complete_description(self) -> str | None:
96
95
  """String that summarizes what is known about this document."""
97
- if self.category and not self.description:
96
+ if self.category and not self.description and not self.author:
98
97
  return self.category
99
98
  elif self.category == REPUTATION:
100
99
  return f"{REPUTATION_MGMT}: {self.description}"
100
+ elif self.category == SKYPE_LOG:
101
+ msg = f"{self.category} of conversation with {self.author}" if self.author else self.category
102
+ return f"{msg} {self.description}" if self.description else msg
101
103
  elif self.author and self.description:
102
104
  if self.category in [ACADEMIA, BOOK]:
103
- return self.title_by_author()
105
+ title = self.description if '"' in self.description else f"'{self.description}'"
106
+ return f"{title} by {self.author}"
104
107
  elif self.category == FINANCE and self.author in FINANCIAL_REPORTS_AUTHORS:
105
108
  return f"{self.author} report: '{self.description}'"
106
109
  elif self.category == LEGAL and 'v.' in self.author:
@@ -111,10 +114,6 @@ class DocCfg:
111
114
  pieces = without_falsey([self.author, self.description])
112
115
  return ' '.join(pieces) if pieces else None
113
116
 
114
- def duplicate_reason(self) -> str | None:
115
- if self.dupe_type is not None:
116
- return DUPE_TYPE_STRS[self.dupe_type]
117
-
118
117
  def duplicate_cfgs(self) -> Generator['DocCfg', None, None]:
119
118
  """Create synthetic DocCfg objects that set the 'dupe_of_id' field to point back to this object."""
120
119
  for id in self.duplicate_ids:
@@ -123,35 +122,17 @@ class DocCfg:
123
122
  dupe_cfg.dupe_of_id = self.id
124
123
  dupe_cfg.duplicate_ids = []
125
124
  dupe_cfg.dupe_type = self.dupe_type
126
- dupe_cfg.was_generated = True
125
+ dupe_cfg.is_synthetic = True
127
126
  yield dupe_cfg
128
127
 
129
128
  def metadata(self) -> Metadata:
130
- non_null_fields = {k: v for k, v in asdict(self).items() if v and k not in INVALID_FOR_METADATA}
131
-
132
- if self.category in [EMAIL, TEXT_MESSAGE]:
133
- del non_null_fields['category']
134
-
135
- return non_null_fields
136
-
137
- def non_null_field_names(self) -> list[str]:
138
- return [f.name for f in self.sorted_fields() if getattr(self, f.name)]
139
-
140
- def sorted_fields(self) -> list[Field]:
141
- return sorted(fields(self), key=lambda f: FIELD_SORT_KEY.get(f.name, f.name))
142
-
143
- def title_by_author(self) -> str:
144
- if not (self.author and self.description):
145
- raise RuntimeError(f"Can't call title_by_author() without author and description!")
146
-
147
- title = self.description if '"' in self.description else f"'{self.description}'"
148
- return f"{title} by {self.author}"
129
+ return {k: v for k, v in asdict(self).items() if k not in NON_METADATA_FIELDS and v}
149
130
 
150
131
  def _props_strs(self) -> list[str]:
151
132
  props = []
152
133
  add_prop = lambda f, value: props.append(f"{f.name}={value}")
153
134
 
154
- for _field in self.sorted_fields():
135
+ for _field in sorted(fields(self), key=lambda f: FIELD_SORT_KEY.get(f.name, f.name)):
155
136
  value = getattr(self, _field.name)
156
137
 
157
138
  if value is None or value is False or (isinstance(value, list) and len(value) == 0):
@@ -160,13 +141,13 @@ class DocCfg:
160
141
  add_prop(_field, constantize_name(str(value)) if CONSTANTIZE_NAMES else f"'{value}'")
161
142
  elif _field.name == 'category' and value in [EMAIL, TEXT_MESSAGE]:
162
143
  continue
163
- elif _field.name == 'recipients' and isinstance(value, list):
144
+ elif _field.name == 'recipients' and value:
164
145
  recipients_str = str([constantize_name(r) if (CONSTANTIZE_NAMES and r) else r for r in value])
165
146
  add_prop(_field, recipients_str.replace("'", '') if CONSTANTIZE_NAMES else recipients_str)
166
147
  elif _field.name == 'timestamp' and self.date is not None:
167
148
  continue # Don't print both timestamp and date
168
149
  elif isinstance(value, datetime):
169
- value_str = re.sub(' 00:00:00', '', str(value))
150
+ value_str = remove_zero_time_from_timestamp_str(value)
170
151
  add_prop(_field, f"parse('{value_str}')" if CONSTANTIZE_NAMES else f"'{value}'")
171
152
  elif isinstance(value, str):
172
153
  if "'" in value:
@@ -221,18 +202,15 @@ class EmailCfg(CommunicationCfg):
221
202
  """
222
203
  Attributes:
223
204
  actual_text (str | None): In dire cases of broken OCR we just configure the body of the email as a string.
205
+ fwded_text_after (str | None): If set, any text after this is a fwd of an article or similar
224
206
  is_fwded_article (bool): True if this is a newspaper article someone fwded. Used to exclude articles from word counting.
225
207
  recipients (list[str | None]): Who received the email
226
208
  """
227
- actual_text: str | None = None # Override for the Email._actual_text() method for particularly broken emails
228
- fwded_text_after: str | None = None # If set, any text after this is a fwd of an article or similar
209
+ actual_text: str | None = None
210
+ fwded_text_after: str | None = None
229
211
  is_fwded_article: bool = False
230
212
  recipients: list[str | None] = field(default_factory=list)
231
213
 
232
- @classmethod
233
- def from_doc_cfg(cls, cfg: DocCfg) -> 'EmailCfg':
234
- return cls(**asdict(cfg))
235
-
236
214
  # This is necessary because for some dumb reason @dataclass(repr=False) doesn't cut it
237
215
  def __repr__(self) -> str:
238
216
  return super().__repr__()
@@ -11,8 +11,10 @@ FILENAME_LENGTH = len(HOUSE_OVERSIGHT_PREFIX) + 6
11
11
  KB = 1024
12
12
  MB = KB * KB
13
13
 
14
+ file_size = lambda file_path: Path(file_path).stat().st_size
15
+ file_size_str = lambda file_path: file_size_to_str(file_size(file_path))
14
16
 
15
- # Coerce methods hands both string and int arguments.
17
+ # Coerce methods handle both string and int arguments.
16
18
  coerce_file_name = lambda filename_or_id: coerce_file_stem(filename_or_id) + '.txt'
17
19
  coerce_file_path = lambda filename_or_id: DOCS_DIR.joinpath(coerce_file_name(filename_or_id))
18
20
  id_str = lambda id: f"{int(id):06d}"
@@ -44,14 +46,6 @@ def extract_file_id(filename_or_id: int | str | Path) -> str:
44
46
  return file_match.group(1)
45
47
 
46
48
 
47
- def file_size(file_path: str | Path) -> int:
48
- return Path(file_path).stat().st_size
49
-
50
-
51
- def file_size_str(file_path: str | Path) -> str:
52
- return file_size_to_str(file_size(file_path))
53
-
54
-
55
49
  def file_size_to_str(size: int) -> str:
56
50
  digits = 2
57
51
 
@@ -223,6 +223,7 @@ HIGHLIGHTED_NAMES = [
223
223
  'Linda Pinto': 'interior design at Alberto Pinto Cabinet',
224
224
  MERWIN_DELA_CRUZ: None, # HOUSE_OVERSIGHT_032652 Groff says "Jojo and Merwin both requested off Nov. 25 and 26"
225
225
  NADIA_MARCINKO: 'pilot',
226
+ 'Sean J. Lancaster': 'airplane reseller',
226
227
  }
227
228
  ),
228
229
  HighlightedNames(
@@ -260,6 +261,8 @@ HIGHLIGHTED_NAMES = [
260
261
  MARTIN_WEINBERG: CRIMINAL_DEFENSE_ATTORNEY,
261
262
  MICHAEL_MILLER: 'Steptoe LLP partner',
262
263
  REID_WEINGARTEN: 'Steptoe LLP partner',
264
+ ROBERT_D_CRITTON_JR: 'criminal defense attorney',
265
+ 'Robert Gold': None,
263
266
  'Roy Black': CRIMINAL_DEFENSE_2008,
264
267
  SCOTT_J_LINK: None,
265
268
  TONJA_HADDAD_COLEMAN: f'{EPSTEIN_V_ROTHSTEIN_EDWARDS_ATTORNEY}, maybe daughter of Fred Haddad?',
@@ -297,28 +300,17 @@ HIGHLIGHTED_NAMES = [
297
300
  }
298
301
  ),
299
302
  HighlightedNames(
300
- label='friend',
301
- style='tan',
302
- pattern=r"Andrew Farkas|Thomas\s*(J\.?\s*)?Barrack(\s*Jr)?",
303
- emailers = {
304
- DAVID_STERN: f'emailed Epstein from Moscow, appears to know chairman of {DEUTSCHE_BANK}',
305
- JONATHAN_FARKAS: "heir to the Alexander's department store fortune",
306
- 'linkspirit': "Skype username of someone Epstein communicated with",
307
- 'Peter Thomas Roth': 'student of Epstein at Dalton, skincare company founder',
308
- STEPHEN_HANSON: None,
309
- TOM_BARRACK: 'long time friend of Trump',
310
- }
311
- ),
312
- HighlightedNames(
313
- label='finance',
303
+ label=FINANCE,
314
304
  style='green',
315
- pattern=r'Apollo|Ari\s*Glass|Bank|(Bernie\s*)?Madoff|Black(rock|stone)|B\s*of\s*A|Boothbay(\sFund\sManagement)?|Chase\s*Bank|Credit\s*Suisse|DB|Deutsche\s*(Asset|Bank)|Electron\s*Capital\s*(Partners)?|Fenner|FRBNY|Goldman(\s*Sachs)|HSBC|Invesco|(Janet\s*)?Yellen|(Jerome\s*)?Powell(?!M\. Cabot)|(Jimmy\s*)?Cayne|JPMC?|j\.?p\.?\s*morgan(\.?com|\s*Chase)?|Madoff|Merrill(\s*Lynch)?|(Michael\s*)?(Cembalest|Milken)|Mizrahi\s*Bank|MLPF&S|((anti.?)?money\s+)?launder(s?|ers?|ing)?(\s+money)?|Morgan Stanley|(Peter L. )?Scher|(Ray\s*)?Dalio|Schwartz?man|Serageldin|UBS|us.gio@jpmorgan.com',
305
+ pattern=r'Apollo|Ari\s*Glass|Bank|(Bernie\s*)?Madoff|Black(rock|stone)|B\s*of\s*A|Boothbay(\sFund\sManagement)?|Chase\s*Bank|Credit\s*Suisse|DB|Deutsche\s*(Asset|Bank)|Electron\s*Capital\s*(Partners)?|Fenner|FRBNY|Goldman(\s*Sachs)|HSBC|Invesco|(Janet\s*)?Yellen|(Jerome\s*)?Powell(?!M\. Cabot)|(Jimmy\s*)?Cayne|JPMC?|j\.?p\.?\s*morgan(\.?com|\s*Chase)?|Madoff|Merrill(\s*Lynch)?|(Michael\s*)?(Cembalest|Milken)|Mizrahi\s*Bank|MLPF&S|((anti.?)?money\s+)?launder(s?|ers?|ing)?(\s+money)?|Morgan Stanley|(Peter L. )?Scher|(Ray\s*)?Dalio|(Richard\s*)?LeFrak|Schwartz?man|Serageldin|UBS|us.gio@jpmorgan.com',
316
306
  emailers={
317
307
  AMANDA_ENS: 'Citigroup',
308
+ BRAD_WECHSLER: f"head of {LEON_BLACK}'s personal investment vehicle according to FT",
318
309
  DANIEL_SABBA: 'UBS Investment Bank',
319
310
  DAVID_FISZEL: 'CIO Honeycomb Asset Management',
320
311
  JES_STALEY: 'former CEO of Barclays',
321
312
  JIDE_ZEITLIN: 'former partner at Goldman Sachs, allegations of sexual misconduct',
313
+ 'Laurie Cameron': 'currency trading',
322
314
  LEON_BLACK: 'Apollo CEO',
323
315
  MARC_LEON: 'Luxury Properties Sari Morrocco',
324
316
  MELANIE_SPINELLA: f'representative of {LEON_BLACK}',
@@ -327,9 +319,23 @@ HIGHLIGHTED_NAMES = [
327
319
  PAUL_MORRIS: 'Deutsche Bank',
328
320
  }
329
321
  ),
322
+ HighlightedNames(
323
+ label='friend',
324
+ style='tan',
325
+ pattern=r"Andrew Farkas|Thomas\s*(J\.?\s*)?Barrack(\s*Jr)?",
326
+ emailers = {
327
+ DANGENE_AND_JENNIE_ENTERPRISE: 'founders of the members-only CORE club',
328
+ DAVID_STERN: f'emailed Epstein from Moscow, appears to know chairman of {DEUTSCHE_BANK}',
329
+ JONATHAN_FARKAS: "heir to the Alexander's department store fortune",
330
+ 'linkspirit': "Skype username of someone Epstein communicated with",
331
+ 'Peter Thomas Roth': 'student of Epstein at Dalton, skincare company founder',
332
+ STEPHEN_HANSON: None,
333
+ TOM_BARRACK: 'long time friend of Trump',
334
+ },
335
+ ),
330
336
  HighlightedNames(
331
337
  label=HARVARD.lower(),
332
- style='deep_pink2',
338
+ style='light_goldenrod3',
333
339
  pattern=r'Cambridge|(Derek\s*)?Bok|Elisa(\s*New)?|Harvard(\s*(Business|Law|University)(\s*School)?)?|(Jonathan\s*)?Zittrain|(Stephen\s*)?Kosslyn',
334
340
  emailers = {
335
341
  "Donald Rubin": f"Professor of Statistics",
@@ -378,7 +384,7 @@ HIGHLIGHTED_NAMES = [
378
384
  HighlightedNames(
379
385
  label=JOURNALIST,
380
386
  style='bright_yellow',
381
- pattern=r'Palm\s*Beach\s*(Daily\s*News|Post)|ABC(\s*News)?|Alex\s*Yablon|(Andrew\s*)?Marra|Arianna(\s*Huffington)?|(Arthur\s*)?Kretchmer|BBC|Bloomberg|Breitbart|Charlie\s*Rose|China\s*Daily|CNBC|CNN(politics?)?|Con[cs]hita|Sarnoff|(?<!Virgin[-\s]Islands[-\s])Daily\s*(Beast|Mail|News|Telegraph)|(David\s*)?Pecker|David\s*Brooks|Ed\s*Krassenstein|(Emily\s*)?Michot|Ezra\s*Klein|(George\s*)?Stephanopoulus|Globe\s*and\s*Mail|Good\s*Morning\s*America|Graydon(\s*Carter)?|Huffington(\s*Post)?|Ingram, David|(James\s*)?Patterson|Jonathan\s*Karl|Julie\s*(K.?\s*)?Brown|(Katie\s*)?Couric|Keith\s*Larsen|L\.?A\.?\s*Times|Miami\s*Herald|(Michele\s*)?Dargan|(National\s*)?Enquirer|(The\s*)?N(ew\s*)?Y(ork\s*)?(P(ost)?|T(imes)?)|(The\s*)?New\s*Yorker|NYer|PERVERSION\s*OF\s*JUSTICE|Politico|Pro\s*Publica|(Sean\s*)?Hannity|Sulzberger|SunSentinel|Susan Edelman|(Uma\s*)?Sanghvi|(The\s*)?Wa(shington\s*)?Po(st)?|Viceland|Vick[iy]\s*Ward|Vox|WGBH|(The\s*)?Wall\s*Street\s*Journal|WSJ|[-\w.]+@(bbc|independent|mailonline|mirror|thetimes)\.co\.uk',
387
+ pattern=r'Palm\s*Beach\s*(Daily\s*News|Post)|ABC(\s*News)?|Alex\s*Yablon|(Andrew\s*)?Marra|Arianna(\s*Huffington)?|(Arthur\s*)?Kretchmer|BBC|Bloomberg|Breitbart|Charlie\s*Rose|China\s*Daily|CNBC|CNN(politics?)?|Con[cs]hita|Sarnoff|(?<!Virgin[-\s]Islands[-\s])Daily\s*(Beast|Mail|News|Telegraph)|(David\s*)?Pecker|David\s*Brooks|Ed\s*Krassenstein|(Emily\s*)?Michot|Ezra\s*Klein|(George\s*)?Stephanopoulus|Globe\s*and\s*Mail|Good\s*Morning\s*America|Graydon(\s*Carter)?|Huffington(\s*Post)?|Ingram, David|(James\s*)?(Hill|Patterson)|Jonathan\s*Karl|Julie\s*(K.?\s*)?Brown|(Katie\s*)?Couric|Keith\s*Larsen|L\.?A\.?\s*Times|Miami\s*Herald|(Michele\s*)?Dargan|(National\s*)?Enquirer|(The\s*)?N(ew\s*)?Y(ork\s*)?(P(ost)?|T(imes)?)|(The\s*)?New\s*Yorker|NYer|PERVERSION\s*OF\s*JUSTICE|Politico|Pro\s*Publica|(Sean\s*)?Hannity|Sulzberger|SunSentinel|Susan Edelman|(Uma\s*)?Sanghvi|(The\s*)?Wa(shington\s*)?Po(st)?|Viceland|Vick[iy]\s*Ward|Vox|WGBH|(The\s*)?Wall\s*Street\s*Journal|WSJ|[-\w.]+@(bbc|independent|mailonline|mirror|thetimes)\.co\.uk',
382
388
  emailers = {
383
389
  EDWARD_JAY_EPSTEIN: 'reporter who wrote about the kinds of crimes Epstein was involved in, no relation to Jeffrey',
384
390
  'James Hill': 'ABC News',
@@ -398,7 +404,7 @@ HIGHLIGHTED_NAMES = [
398
404
  HighlightedNames(
399
405
  label='law enforcement',
400
406
  style='color(24) bold',
401
- pattern=r'ag|(Alicia\s*)?Valle|AML|attorney|((Bob|Robert)\s*)?Mueller|(Byung\s)?Pak|CFTC?|CIA|CIS|CVRA|Dep(artmen)?t\.?\s*of\s*(the\s*)?(Justice|Treasury)|DHS|DOJ|FBI|FCPA|FDIC|Federal\s*Bureau\s*of\s*Investigation|FinCEN|FINRA|FOIA|FTC|IRS|(James\s*)?Comey|(Jennifer\s*Shasky\s*)?Calvery|((Judge|Mark)\s*)?(Carney|Filip)|(Kirk )?Blouin|KYC|NIH|NS(A|C)|OCC|OFAC|(Lann?a\s*)?Belohlavek|lawyer|(Michael\s*)?Reiter|OGE|Office\s*of\s*Government\s*Ethics|Police Code Enforcement|(Preet\s*)?Bharara|SCOTUS|SD(FL|NY)|Southern\s*District\s*of\s*(Florida|New\s*York)|SEC|Secret\s*Service|Securities\s*and\s*Exchange\s*Commission|State\s*Dep(artmen)?t|Strzok|Supreme\s*Court|Treasury\s*(Dep(artmen)?t|Secretary)|TSA|USAID|(William\s*J\.?\s*)?Zloch',
407
+ pattern=r'ag|(Alicia\s*)?Valle|AML|(Andrew\s*)?McCabe|attorney|((Bob|Robert)\s*)?Mueller|(Byung\s)?Pak|CFTC?|CIA|CIS|CVRA|Dep(artmen)?t\.?\s*of\s*(the\s*)?(Justice|Treasury)|DHS|DOJ|FBI|FCPA|FDIC|Federal\s*Bureau\s*of\s*Investigation|FinCEN|FINRA|FOIA|FTC|IRS|(James\s*)?Comey|(Jennifer\s*Shasky\s*)?Calvery|((Judge|Mark)\s*)?(Carney|Filip)|(Kirk )?Blouin|KYC|NIH|NS(A|C)|OCC|OFAC|(Lann?a\s*)?Belohlavek|lawyer|(Michael\s*)?Reiter|OGE|Office\s*of\s*Government\s*Ethics|Police Code Enforcement|(Preet\s*)?Bharara|SCOTUS|SD(FL|NY)|Southern\s*District\s*of\s*(Florida|New\s*York)|SEC|Secret\s*Service|Securities\s*and\s*Exchange\s*Commission|State\s*Dep(artmen)?t|Strzok|Supreme\s*Court|Treasury\s*(Dep(artmen)?t|Secretary)|TSA|USAID|(William\s*J\.?\s*)?Zloch',
402
408
  emailers = {
403
409
  ANN_MARIE_VILLAFANA: 'southern district of Florida U.S. Attorney',
404
410
  DANNY_FROST: 'Director of Communications at Manhattan DA',
@@ -457,7 +463,9 @@ HIGHLIGHTED_NAMES = [
457
463
  CHRISTINA_GALBRAITH: f"{REPUTATION_MGMT}, worked on Epstein's Google search results with {TYLER_SHEARS}",
458
464
  IAN_OSBORNE: f"{OSBORNE_LLP} reputation repairer possibly hired by Epstein ca. 2011-06",
459
465
  MICHAEL_SITRICK: 'crisis PR',
466
+ 'Owen Blicksilver': 'OBPR, Inc.',
460
467
  PEGGY_SIEGAL: 'socialite',
468
+ 'R. Couri Hay': None,
461
469
  ROSS_GOW: 'Acuity Reputation Management',
462
470
  TYLER_SHEARS: f"{REPUTATION_MGMT}, worked on Epstein's Google search results with {CHRISTINA_GALBRAITH}",
463
471
  }
@@ -465,7 +473,7 @@ HIGHLIGHTED_NAMES = [
465
473
  HighlightedNames(
466
474
  label='republicans',
467
475
  style='bold dark_red',
468
- pattern=r'Alberto\sGonzale[sz]|(Alex\s*)?Acosta|(Bill\s*)?Barr|Bill\s*Shine|(Bob\s*)?Corker|(John\s*(R.?\s*)?)Bolton|Broidy|(Chris\s)?Christie|Devin\s*Nunes|(Don\s*)?McGa[hn]n|McMaster|(George\s*)?Nader|GOP|(Brett\s*)?Kavanaugh|Kissinger|Kobach|Koch\s*Brothers|Kolfage|Kudlow|Lewandowski|(Marco\s)?Rubio|(Mark\s*)Meadows|Mattis|McCain|(?<!Merwin Dela )Cruz|(Michael\s)?Hayden|((General|Mike)\s*)?(Flynn|Pence)|(Mitt\s*)?Romney|Mnuchin|Nikki|Haley|(Paul\s+)?(Manafort|Volcker)|(Peter\s)?Navarro|Pompeo|Reagan|Reince|Priebus|Republican|(Rex\s*)?Tillerson|(?<!Cynthia )(Richard\s*)?Nixon|Sasse',
476
+ pattern=r'Alberto\sGonzale[sz]|(Alex\s*)?Acosta|(Bill\s*)?Barr|Bill\s*Shine|(Bob\s*)?Corker|(John\s*(R.?\s*)?)Bolton|Broidy|(Chris\s)?Christie|Devin\s*Nunes|(Don\s*)?McGa[hn]n|McMaster|(George\s*)?Nader|GOP|(Brett\s*)?Kavanaugh|Kissinger|Kobach|Koch\s*Brothers|Kolfage|Kudlow|Lewandowski|(Marco\s)?Rubio|(Mark\s*)Meadows|Mattis|McCain|(?<!Merwin Dela )Cruz|(Michael\s)?Hayden|((General|Mike)\s*)?(Flynn|Pence)|(Mitt\s*)?Romney|Mnuchin|Nikki|Haley|(Paul\s+)?(Manafort|Volcker)|(Peter\s)?Navarro|Pompeo|Reagan|Reince|Priebus|Republican|(Rex\s*)?Tillerson|(?<!Cynthia )(Richard\s*)?Nixon|Sasse|Tea\s*Party',
469
477
  # There's no emails from these people, they're just here to automate the regex creation for both first + last names
470
478
  emailers = {
471
479
  RUDY_GIULIANI: 'disbarred formed mayor of New York City',
@@ -485,6 +493,7 @@ HIGHLIGHTED_NAMES = [
485
493
  style='red bold',
486
494
  pattern=r'Alfa\s*Bank|Anya\s*Rasulova|Chernobyl|Day\s+One\s+Ventures|(Dmitry\s)?(Kiselyov|(Lana\s*)?Pozhidaeva|Medvedev|Rybolo(o?l?ev|vlev))|Dmitry|FSB|GRU|KGB|Kislyak|Kremlin|Kuznetsova|Lavrov|Lukoil|Moscow|(Oleg\s*)?Deripaska|Oleksandr Vilkul|Rosneft|RT|St.?\s*?Petersburg|Russian?|Sberbank|Soviet(\s*Union)?|USSR|Vladimir|(Vladimir\s*)?(Putin|Yudashkin)|Women\s*Empowerment|Xitrans',
487
495
  emailers = {
496
+ 'Dasha Zhukova': 'art collector, daughter of Alexander Zhukov',
488
497
  MASHA_DROKOVA: 'silicon valley VC, former Putin Youth',
489
498
  RENATA_BOLOTOVA: 'former aspiring model, now fund manager at New York State Insurance Fund',
490
499
  SVETLANA_POZHIDAEVA: f'Epstein\'s Russian assistant who was recommended for a visa by Sergei Belyakov (FSB) and {DAVID_BLAINE}',
@@ -493,14 +502,16 @@ HIGHLIGHTED_NAMES = [
493
502
  HighlightedNames(
494
503
  label=ACADEMIA,
495
504
  style='light_goldenrod2',
496
- pattern=r'Alain Forget|Brotherton|Carl\s*Sagan|Columbia|David Grosof|J(ames|im)\s*Watson|(Lord\s*)?Martin\s*Rees|Massachusetts\s*Institute\s*of\s*Technology|MIT(\s*Media\s*Lab)?|Media\s*Lab|Minsky|((Noam|Valeria)\s*)?Chomsky|Praluent|Regeneron|(Richard\s*)?Dawkins|Sanofi|Stanford|(Stephen\s*)?Hawking|(Steven?\s*)?Pinker|UCLA',
505
+ pattern=r'Alain Forget|Brotherton|Carl\s*Sagan|Columbia|David Grosof|J(ames|im)\s*Watson|(Lord\s*)?Martin\s*Rees|Massachusetts\s*Institute\s*of\s*Technology|MIT(\s*Media\s*Lab)?|Media\s*Lab|Minsky|((Noam|Valeria)\s*)?Chomsky|Norman\s*Finkelstein|Praluent|Regeneron|(Richard\s*)?Dawkins|Sanofi|Stanford|(Stephen\s*)?Hawking|(Steven?\s*)?Pinker|UCLA',
497
506
  emailers = {
498
507
  DAVID_HAIG: None,
499
508
  JOSCHA_BACH: 'cognitive science / AI research',
500
509
  'Daniel Kahneman': 'Nobel economic sciences laureate and cognitivie psychologist (?)',
510
+ 'Ed Boyden': 'Associate Professor, MIT Media Lab neurobiology',
501
511
  LAWRENCE_KRAUSS: 'theoretical physicist',
502
512
  LINDA_STONE: 'ex-Microsoft, MIT Media Lab',
503
513
  MARK_TRAMO: 'professor of neurology at UCLA',
514
+ 'Nancy Dahl': f'wife of {LAWRENCE_KRAUSS}',
504
515
  NEAL_KASSELL: 'professor of neurosurgery at University of Virginia',
505
516
  PETER_ATTIA: 'longevity medicine',
506
517
  ROBERT_TRIVERS: 'evolutionary biology',
@@ -661,7 +672,7 @@ def get_style_for_category(category: str) -> str | None:
661
672
  elif category in [CONFERENCE, SPEECH]:
662
673
  return f"{get_style_for_category(ACADEMIA)} dim"
663
674
  elif category == SOCIAL:
664
- return f"{get_style_for_category(PUBLICIST)}"
675
+ return get_style_for_category(PUBLICIST)
665
676
 
666
677
  category = CATEGORY_STYLE_MAPPING.get(category, category)
667
678
 
@@ -32,7 +32,7 @@ LOG_LEVEL_ENV_VAR = 'LOG_LEVEL'
32
32
  # Augment the standard log highlighter with 'epstein_filename' matcher
33
33
  class LogHighlighter(ReprHighlighter):
34
34
  highlights = ReprHighlighter.highlights + [
35
- *[fr"(?P<{doc_type}>{doc_type})" for doc_type in DOC_TYPE_STYLES.keys()],
35
+ *[fr"(?P<{doc_type}>{doc_type}(Cfg)?)" for doc_type in DOC_TYPE_STYLES.keys()],
36
36
  "(?P<epstein_filename>" + FILE_NAME_REGEX.pattern + ')',
37
37
  ]
38
38
 
@@ -125,7 +125,7 @@ def print_json_files(epstein_files: EpsteinFiles):
125
125
  console.print_json(json_file.json_str(), indent=4, sort_keys=False)
126
126
 
127
127
 
128
- def print_json_metadata(epstein_files: EpsteinFiles) -> None:
128
+ def write_json_metadata(epstein_files: EpsteinFiles) -> None:
129
129
  json_str = epstein_files.json_metadata()
130
130
 
131
131
  if args.build:
@@ -33,6 +33,7 @@ GREY_NUMBERS = [58, 39, 39, 35, 30, 27, 23, 23, 19, 19, 15, 15, 15]
33
33
  DEFAULT_NAME_STYLE = 'gray46'
34
34
  INFO_STYLE = 'white dim italic'
35
35
  KEY_STYLE='honeydew2 bold'
36
+ LAST_TIMESTAMP_STYLE='wheat4'
36
37
  SECTION_HEADER_STYLE = 'bold white on blue3'
37
38
  SOCIAL_MEDIA_LINK_STYLE = 'pale_turquoise4'
38
39
  SUBSTACK_POST_LINK_STYLE = 'bright_cyan'
@@ -79,10 +80,18 @@ console = Console(**CONSOLE_ARGS)
79
80
  highlighter = CONSOLE_ARGS['highlighter']
80
81
 
81
82
 
82
- def add_cols_to_table(table: Table, col_names: list[str]) -> None:
83
+ def add_cols_to_table(table: Table, col_names: list[str | dict]) -> None:
83
84
  """Left most col will be left justified, rest are center justified."""
84
85
  for i, col in enumerate(col_names):
85
- table.add_column(col, justify='left' if i == 0 else 'center')
86
+ if isinstance(col, dict):
87
+ col_name = col['name']
88
+ kwargs = col
89
+ del kwargs['name']
90
+ else:
91
+ col_name = col
92
+ kwargs = {}
93
+
94
+ table.add_column(col_name, justify='left' if i == 0 else 'center', **kwargs)
86
95
 
87
96
 
88
97
  def build_highlighter(pattern: str) -> EpsteinHighlighter:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: epstein-files
3
- Version: 1.0.11
3
+ Version: 1.0.13
4
4
  Summary: Tools for working with the Jeffrey Epstein documents released in November 2025.
5
5
  Home-page: https://michelcrypt4d4mus.github.io/epstein_text_messages/
6
6
  License: GPL-3.0-or-later
@@ -0,0 +1,33 @@
1
+ epstein_files/__init__.py,sha256=qVFB7sS6XSlZX-ByyDwdbGSn2h06aoX2Mx8WcgRb-To,4710
2
+ epstein_files/documents/communication.py,sha256=i6eob0ucnI7AY1sGuJlzrtU_C0mxEtrPEQZE4yNeM9w,2049
3
+ epstein_files/documents/document.py,sha256=VsXIJhY7HTUlQrnTzYv5VLtYugdb-c2ClrfInPb5l2M,17095
4
+ epstein_files/documents/email.py,sha256=P2c8Z23qaiWj6qWf4QKTuLvqKDoUJmu7SyzJ6FQCmPA,40727
5
+ epstein_files/documents/emails/email_header.py,sha256=wkPfSLbmzkAeQwvhf0bAeFDLPbQT-EeG0v8vNNLYktM,7502
6
+ epstein_files/documents/imessage/text_message.py,sha256=4gFvTfulj_Su10lNQl6Hq_p9ArTrSmn5pfC22YRJXjI,2794
7
+ epstein_files/documents/json_file.py,sha256=tIYTwA3FYkwVZSpXvFYyUoH9m2sGYCD1U0ttamH6r1o,1306
8
+ epstein_files/documents/messenger_log.py,sha256=BW3J52a9XxNVoK7SxtfJGydSNPoeKGE0PkdkMpf9sJ0,6294
9
+ epstein_files/documents/other_file.py,sha256=pnl_q1o7ur3eeqGPwsYL2qbM3Y8O9LX6j6LbWnoxAiE,9939
10
+ epstein_files/epstein_files.py,sha256=sbgS7GlrlWo1kuH4YXUSvbYX_SApgrwhpx6_qdHmrBM,19119
11
+ epstein_files/util/constant/common_words.py,sha256=aR0UjoWmxyR49XS-DtHECQ1CiA_bK8hNP6CQ1TS9yZA,3696
12
+ epstein_files/util/constant/html.py,sha256=9U098TGzlghGg4WfxLYHyub5JGR17Dv7VP5i2MSu8Kk,1415
13
+ epstein_files/util/constant/names.py,sha256=ObLJCvit_C1cwLc-7Wcjh-C5oQrpww1HLk6DrEvnu8E,10368
14
+ epstein_files/util/constant/output_files.py,sha256=BkV4_gmdj46RfGy5SFYp6dgTty3FtlBth5YGmaGutls,1700
15
+ epstein_files/util/constant/strings.py,sha256=02DwbhAe8qBRq5HOUFx5FafXJ1P2-RJf9TCVu2b7UDQ,1932
16
+ epstein_files/util/constant/urls.py,sha256=EKzpL1np3cdyYvUlgv1zl9IJU8Vrg8jXpAu6YpM0_Bk,5283
17
+ epstein_files/util/constants.py,sha256=tSHrgzDOTx0KwGy4HI7ShIwaRMX1o7otW3CkKvRplZs,112121
18
+ epstein_files/util/data.py,sha256=gOaETo4LvN3VgRvA1dB2_NRDL3wiL-xBICZ2jfD-knk,2997
19
+ epstein_files/util/doc_cfg.py,sha256=irQljeGXlB9wbRbP05pWQZMS2-DbhdugfVGD8Q2UhSg,9006
20
+ epstein_files/util/env.py,sha256=HnYcfHSNkwVJ_T75Woy43_OpDyxD0KHPj3GxcVx86N4,5751
21
+ epstein_files/util/file_helper.py,sha256=tacTe1GcAnckPFvjMgxRRSLnFgr2aVIYsgfDR_C9uXk,2780
22
+ epstein_files/util/highlighted_group.py,sha256=rKJsUQfPzQwMMu5--QWsxNFxW303RI8yq69sw4vi2RA,36720
23
+ epstein_files/util/logging.py,sha256=fuREq06xUUI3DfCV2JE-8QM-sQKxpLDj0_AYFO6qR1M,1983
24
+ epstein_files/util/output.py,sha256=XcflgSOlzUGj6FsFaK6j4Dljld8A0h_uVV7ERcI_EYw,8120
25
+ epstein_files/util/rich.py,sha256=V8WDQPuCcubn46HW1cLZ6uT-CBAnBB17Hozsvv7Pd4g,14987
26
+ epstein_files/util/search_result.py,sha256=1fxe0KPBQXBk4dLfu6m0QXIzYfZCzvaSkWqvghJGzxY,567
27
+ epstein_files/util/timer.py,sha256=8hxW4Y1JcTUfnBrHh7sL2pM9xu1sL4HFQM4CmmzTarU,837
28
+ epstein_files/util/word_count.py,sha256=8qBTuq3d0Q-3fwiuECKWi2RfL-KUiZD8TciwvfL0D_o,9353
29
+ epstein_files-1.0.13.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
30
+ epstein_files-1.0.13.dist-info/METADATA,sha256=ZfGSbuEOmAhzDs_a6KiKjXfhLNRwcZoXklAK1KphX7I,5480
31
+ epstein_files-1.0.13.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
32
+ epstein_files-1.0.13.dist-info/entry_points.txt,sha256=5qYgwAXpxegeAicD_rzda_trDRnUC51F5UVDpcZ7j6Q,240
33
+ epstein_files-1.0.13.dist-info/RECORD,,
@@ -1,33 +0,0 @@
1
- epstein_files/__init__.py,sha256=4zxX1tw-0xMwpM-Sbq7PezV0YNS9zN-P6gc9BQ1BqKU,4710
2
- epstein_files/documents/communication.py,sha256=SunZdjMhR9v6y8LlQ6jhIu8vYjSndaBK0Su1mKnhfj0,2060
3
- epstein_files/documents/document.py,sha256=dECV0bSnOJzPfOIHyHeG5rNxKd6uwuiso35-sQZg9No,18353
4
- epstein_files/documents/email.py,sha256=yXiW7mB4myU8G9DY7PnnqazaCqeAR3dHr35NfBplfRU,38519
5
- epstein_files/documents/emails/email_header.py,sha256=wkPfSLbmzkAeQwvhf0bAeFDLPbQT-EeG0v8vNNLYktM,7502
6
- epstein_files/documents/imessage/text_message.py,sha256=3HlNp75JIoMlWj7PaUWIFry3qlGEmpGu5OmdmsBYS34,2807
7
- epstein_files/documents/json_file.py,sha256=HsnVWPZXVxTF_DadL2YtJtsiXKXOd18PUs05O33tjNc,1317
8
- epstein_files/documents/messenger_log.py,sha256=uSPlg85jGTwod1cV9f7MtxSNqmMZ61JBFzoiRNqg52M,6263
9
- epstein_files/documents/other_file.py,sha256=S_Y-SxYYYXtx42JHmhFWl5BbTduNI7cwQjeYHBJA7sc,9950
10
- epstein_files/epstein_files.py,sha256=SaD4DJJ5tRxY97Ei4BdOgLzHQ9wrBVGrP64CSqdmk-w,18691
11
- epstein_files/util/constant/common_words.py,sha256=aR0UjoWmxyR49XS-DtHECQ1CiA_bK8hNP6CQ1TS9yZA,3696
12
- epstein_files/util/constant/html.py,sha256=9U098TGzlghGg4WfxLYHyub5JGR17Dv7VP5i2MSu8Kk,1415
13
- epstein_files/util/constant/names.py,sha256=KKJEYFpdOp4xDwXe5dhrqYgF12oJODvVSFpAB28Q76A,10153
14
- epstein_files/util/constant/output_files.py,sha256=BkV4_gmdj46RfGy5SFYp6dgTty3FtlBth5YGmaGutls,1700
15
- epstein_files/util/constant/strings.py,sha256=FDtksfH50PSxtSBw9XhmqxtrgRgGxdIvGiAR2bbPpu4,1899
16
- epstein_files/util/constant/urls.py,sha256=0IdCVVvXib0i-4TZFkVHoS4zCbjOBZWcr6NkGxsmQWM,4981
17
- epstein_files/util/constants.py,sha256=LPSI6Z0n3ChFDnMGYVO80cGuSKZf0OoyUzLih_jlRKI,111434
18
- epstein_files/util/data.py,sha256=xwTqrbAi7ZDJM0iyFVOevnokP_oIQ2npkRjHzF1KGGY,2908
19
- epstein_files/util/doc_cfg.py,sha256=OZlocAWldfR8Nomiad4FxQeyhNMbd0PQ-rumKn2nWBg,9641
20
- epstein_files/util/env.py,sha256=HnYcfHSNkwVJ_T75Woy43_OpDyxD0KHPj3GxcVx86N4,5751
21
- epstein_files/util/file_helper.py,sha256=-higKqc9J5IfNpzMzg-9j1ps3beV4N2cw8kdAxfm7NA,2835
22
- epstein_files/util/highlighted_group.py,sha256=fU-8ns50uUolzPEAxadF5AnPLjn383KpEeyRXfFbv_U,35971
23
- epstein_files/util/logging.py,sha256=8e22WaBfDAKEmkcr3Gb4TdqtFSkU4FQDpk3Z6hfSzbw,1977
24
- epstein_files/util/output.py,sha256=UzTU0mNHEmeJr3w2TXAp19X497GB6_-HyW0mfztI1jk,8120
25
- epstein_files/util/rich.py,sha256=8-4IA5bwPBdDPqkPdymq3zVKB9hfy3nrT7fUrN_XevY,14744
26
- epstein_files/util/search_result.py,sha256=1fxe0KPBQXBk4dLfu6m0QXIzYfZCzvaSkWqvghJGzxY,567
27
- epstein_files/util/timer.py,sha256=8hxW4Y1JcTUfnBrHh7sL2pM9xu1sL4HFQM4CmmzTarU,837
28
- epstein_files/util/word_count.py,sha256=8qBTuq3d0Q-3fwiuECKWi2RfL-KUiZD8TciwvfL0D_o,9353
29
- epstein_files-1.0.11.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
30
- epstein_files-1.0.11.dist-info/METADATA,sha256=HBW3t1F9lkoN6GIR7ySV2kBYnJhNEF9otDZWnf03jUo,5480
31
- epstein_files-1.0.11.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
32
- epstein_files-1.0.11.dist-info/entry_points.txt,sha256=5qYgwAXpxegeAicD_rzda_trDRnUC51F5UVDpcZ7j6Q,240
33
- epstein_files-1.0.11.dist-info/RECORD,,