epstein-files 1.1.3__py3-none-any.whl → 1.1.5__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.
@@ -1,6 +1,5 @@
1
1
  import json
2
2
  import re
3
- from abc import ABC
4
3
  from dataclasses import dataclass, field
5
4
 
6
5
  from rich.highlighter import RegexHighlighter
@@ -12,7 +11,7 @@ from epstein_files.util.constant.urls import ARCHIVE_LINK_COLOR
12
11
  from epstein_files.util.constants import (EMAILER_ID_REGEXES, EPSTEIN_V_ROTHSTEIN_EDWARDS,
13
12
  OSBORNE_LLP, REPLY_REGEX, SENT_FROM_REGEX, VIRGIN_ISLANDS)
14
13
  from epstein_files.util.doc_cfg import *
15
- from epstein_files.util.data import extract_last_name, without_falsey
14
+ from epstein_files.util.data import extract_first_name, extract_last_name, without_falsey
16
15
  from epstein_files.util.logging import logger
17
16
 
18
17
  CIVIL_ATTORNEY = 'civil attorney'
@@ -38,7 +37,6 @@ CATEGORY_STYLE_MAPPING = {
38
37
 
39
38
  CATEGORY_STYLES = {
40
39
  JSON: 'dark_red',
41
- JUNK: 'grey19',
42
40
  'letter': 'medium_orchid1'
43
41
  }
44
42
 
@@ -46,12 +44,11 @@ CATEGORY_STYLES = {
46
44
  @dataclass(kw_only=True)
47
45
  class BaseHighlight:
48
46
  """
49
- Regex and style information.
47
+ Regex and style information for things we want to highlight.
50
48
 
51
49
  Attributes:
52
- label (str): RegexHighlighter match group name, defaults to 1st 'emailers' key if only 1 emailer provided
50
+ label (str): RegexHighlighter match group name
53
51
  pattern (str): regex pattern identifying strings matching this group
54
- regex (re.Pattern): matches self.pattern
55
52
  style (str): Rich style to apply to text matching this group
56
53
  theme_style_name (str): The style name that must be a part of the rich.Console's theme
57
54
  """
@@ -79,9 +76,6 @@ class HighlightedText(BaseHighlight):
79
76
  Attributes:
80
77
  label (str): RegexHighlighter match group name, defaults to 1st 'emailers' key if only 1 emailer provided
81
78
  patterns (list[str]): regex patterns identifying strings matching this group
82
- regex (re.Pattern): matches self.pattern
83
- style (str): Rich style to apply to text matching this group
84
- theme_style_name (str): The style name that must be a part of the rich.Console's theme
85
79
  """
86
80
  patterns: list[str] = field(default_factory=list)
87
81
  _pattern: str = field(init=False)
@@ -112,6 +106,7 @@ class HighlightedNames(HighlightedText):
112
106
  """
113
107
  category: str = ''
114
108
  emailers: dict[str, str | None] = field(default_factory=dict)
109
+ should_match_first_last_name: bool = True
115
110
 
116
111
  def __post_init__(self):
117
112
  if not (self.emailers or self.patterns):
@@ -138,9 +133,12 @@ class HighlightedNames(HighlightedText):
138
133
 
139
134
  def _emailer_pattern(self, name: str) -> str:
140
135
  """Pattern matching 'name'. Extends value in EMAILER_ID_REGEXES with first/last name if it exists."""
136
+ if not self.should_match_first_last_name:
137
+ return name
138
+
141
139
  name = remove_question_marks(name)
140
+ first_name = extract_first_name(name)
142
141
  last_name = extract_last_name(name)
143
- first_name = name.removesuffix(f" {last_name}")
144
142
 
145
143
  if name in EMAILER_ID_REGEXES:
146
144
  pattern = EMAILER_ID_REGEXES[name].pattern
@@ -225,7 +223,7 @@ HIGHLIGHTED_NAMES = [
225
223
  LAWRENCE_KRAUSS: 'theoretical physicist',
226
224
  LINDA_STONE: f'ex-Microsoft, {MIT_MEDIA_LAB}',
227
225
  MARK_TRAMO: 'professor of neurology at UCLA',
228
- 'Nancy Dahl': 'wife of Lawrence Krauss',
226
+ 'Nancy Dahl': f'wife of {LAWRENCE_KRAUSS}',
229
227
  NEAL_KASSELL: 'professor of neurosurgery at University of Virginia',
230
228
  PETER_ATTIA: 'longevity medicine',
231
229
  ROBERT_TRIVERS: 'evolutionary biology',
@@ -236,20 +234,23 @@ HIGHLIGHTED_NAMES = [
236
234
  r"Brotherton",
237
235
  r"Carl\s*Sagan",
238
236
  r"Columbia",
237
+ r"Dan(iel|ny) Kahneman",
239
238
  r"David Grosof",
240
239
  r"J(ames|im)\s*Watson",
241
240
  r"(Lord\s*)?Martin\s*Rees",
242
241
  r"Massachusetts\s*Institute\s*of\s*Technology",
243
242
  r"Media\s*Lab",
244
- r"Minsky",
243
+ r"(Marvin\s*)?Minsky",
245
244
  r"MIT(\s*Media\s*Lab)?",
246
245
  r"((Noam|Valeria)\s*)?Chomsky",
247
246
  r"Norman\s*Finkelstein",
247
+ r"Oxford(?! Analytica)",
248
248
  r"Praluent",
249
+ r"Princeton(\s*University)?",
249
250
  r"Regeneron",
250
251
  r"(Richard\s*)?Dawkins",
251
252
  r"Sanofi",
252
- r"Stanford",
253
+ r"Stanford(\s*University)?(\s*Hospital)?",
253
254
  r"(Stephen\s*)?Hawking",
254
255
  r"(Steven?\s*)?Pinker",
255
256
  r"UCLA",
@@ -288,18 +289,19 @@ HIGHLIGHTED_NAMES = [
288
289
  label='bitcoin',
289
290
  style='orange1 bold',
290
291
  emailers={
291
- 'Jeffrey Wernick': 'former COO of Parler, involved in numerous crypto companies like Bitforex',
292
+ JEFFREY_WERNICK: 'former COO of Parler, involved in numerous crypto companies like Bitforex',
292
293
  JEREMY_RUBIN: 'developer/researcher',
293
294
  JOI_ITO: f"former head of {MIT_MEDIA_LAB} and MIT Digital Currency Initiative",
294
295
  ANTHONY_SCARAMUCCI: 'Skybridge Capital, FTX investor',
295
296
  },
296
297
  patterns=[
297
298
  r"Balaji",
298
- r"bitcoin",
299
+ r"bitcoin(\s*Foundation)?",
299
300
  r"block ?chain(\s*capital)?",
300
301
  r"Brock(\s*Pierce)?",
301
302
  r"coins?",
302
303
  r"cr[iy]?pto(currenc(y|ies))?",
304
+ r"Digital\s*Currenc(ies|y)(\s*Initiative)?",
303
305
  r"e-currency",
304
306
  r"(Gavin )?Andressen",
305
307
  r"(Howard\s+)?Lutnic?k",
@@ -380,7 +382,7 @@ HIGHLIGHTED_NAMES = [
380
382
  r"Ministry\sof\sState\sSecurity",
381
383
  r"Mongolian?",
382
384
  r"MSS",
383
- r"North\s*Korea",
385
+ r"North\s*Korean?",
384
386
  r"Peking",
385
387
  r"PRC",
386
388
  r"Pyongyang",
@@ -416,6 +418,7 @@ HIGHLIGHTED_NAMES = [
416
418
  r"Eric Holder",
417
419
  r"George\s*Mitchell",
418
420
  r"(George\s*)?Soros",
421
+ r"Hakeem\s*Jeffries",
419
422
  r"Hill?ary",
420
423
  r"HRC",
421
424
  r"(Jo(e|seph)\s*)?Biden",
@@ -441,7 +444,7 @@ HIGHLIGHTED_NAMES = [
441
444
  ),
442
445
  HighlightedNames(
443
446
  label='employee',
444
- style='deep_sky_blue4',
447
+ style='medium_purple4',
445
448
  emailers={
446
449
  'Alfredo Rodriguez': "Epstein's butler, stole the journal",
447
450
  ERIC_ROTH: 'jet decorator',
@@ -454,7 +457,11 @@ HIGHLIGHTED_NAMES = [
454
457
  NADIA_MARCINKO: 'pilot',
455
458
  'Sean J. Lancaster': 'airplane reseller',
456
459
  },
457
- patterns=[r"Merwin"],
460
+ patterns=[
461
+ r"Adriana\s*Ross",
462
+ r"Merwin",
463
+ r"(Sarah\s*)?Kellen", r"Vickers", # Married name is Metiers
464
+ ],
458
465
  ),
459
466
  HighlightedNames(
460
467
  label=ENTERTAINER,
@@ -498,6 +505,7 @@ HIGHLIGHTED_NAMES = [
498
505
  style='purple',
499
506
  emailers={
500
507
  'Alan S Halperin': 'partner at Paul, Weiss',
508
+ ALAN_DERSHOWITZ: 'Harvard Law School professor and all around (in)famous American lawyer',
501
509
  ARDA_BESKARDES: 'NYC immigration attorney allegedly involved in sex-trafficking operations',
502
510
  BENNET_MOSKOWITZ: f'represented the {EPSTEIN_ESTATE_EXECUTOR}s',
503
511
  BRAD_KARP: 'head of the law firm Paul Weiss',
@@ -509,6 +517,7 @@ HIGHLIGHTED_NAMES = [
509
517
  JACKIE_PERCZEK: CRIMINAL_DEFENSE_2008,
510
518
  JAY_LEFKOWITZ: f"Kirkland & Ellis partner, {CRIMINAL_DEFENSE_2008}",
511
519
  JESSICA_CADWELL: f'paralegal to {ROBERT_D_CRITTON_JR}', # house_oversight_030464
520
+ KEN_STARR: 'head of the Monica Lewinsky investigation against Bill Clinton',
512
521
  LILLY_SANCHEZ: CRIMINAL_DEFENSE_ATTORNEY,
513
522
  MARTIN_WEINBERG: CRIMINAL_DEFENSE_ATTORNEY,
514
523
  MICHAEL_MILLER: 'Steptoe LLP partner',
@@ -521,6 +530,7 @@ HIGHLIGHTED_NAMES = [
521
530
  },
522
531
  patterns=[
523
532
  r"(Barry (E. )?)?Krischer",
533
+ r"dersh",
524
534
  r"Kate Kelly",
525
535
  r"Kirkland\s*&\s*Ellis",
526
536
  r"(Leon\s*)?Jaworski",
@@ -544,6 +554,7 @@ HIGHLIGHTED_NAMES = [
544
554
  style='light_sky_blue3',
545
555
  emailers={
546
556
  ANDRZEJ_DUDA: 'former president of Poland',
557
+ 'Fabrice Aidan': f'diplomat who worked with {TERJE_ROD_LARSEN}',
547
558
  MIROSLAV_LAJCAK: 'Russia-friendly Slovakian politician, friend of Steve Bannon',
548
559
  PETER_MANDELSON: 'UK politics',
549
560
  TERJE_ROD_LARSEN: 'Norwegian diplomat',
@@ -595,27 +606,13 @@ HIGHLIGHTED_NAMES = [
595
606
  r"Strasbourg",
596
607
  r"Strauss[- ]?Kahn",
597
608
  r"Swed(en|ish)(?![-\s]+American Life Scienc)",
598
- r"Switzerland",
609
+ r"Swi(ss|tzerland)",
599
610
  r"(Tony\s)?Blair",
600
611
  r"U\.K\.",
601
612
  r"Ukrain(e|ian)",
602
613
  r"Vienna",
603
614
  r"Zug",
604
- ],
605
- ),
606
- HighlightedNames(
607
- label='famous lawyer',
608
- style='medium_purple3',
609
- emailers={
610
- ALAN_DERSHOWITZ: 'Harvard Law School professor and all around (in)famous American lawyer',
611
- 'Fabrice Aidan': f'diplomat who worked with {TERJE_ROD_LARSEN}',
612
- KEN_STARR: 'head of the Monica Lewinsky investigation against Bill Clinton',
613
- },
614
- patterns=[
615
- r"(David\s*)?Bo[il]es",
616
- r"dersh",
617
- r"(Gloria\s*)?Allred",
618
- r"(Mi(chael|ke)\s*)?Avenatti",
615
+ r"Zurich",
619
616
  ],
620
617
  ),
621
618
  HighlightedNames(
@@ -667,7 +664,8 @@ HIGHLIGHTED_NAMES = [
667
664
  r"j\.?p\.?\s*morgan(\.?com|\s*Chase)?",
668
665
  r"Madoff",
669
666
  r"Merrill(\s*Lynch)?",
670
- r"(Michael\s*)?(Cembalest|Milken)",
667
+ r"(Michael\s*)?Cembalest",
668
+ r"(Mi(chael|ke)\s*)?Milken(\s*Conference)?",
671
669
  r"Mizrahi\s*Bank",
672
670
  r"MLPF&S",
673
671
  r"Morgan Stanley",
@@ -694,6 +692,7 @@ HIGHLIGHTED_NAMES = [
694
692
  },
695
693
  patterns=[
696
694
  r"Andrew Farkas",
695
+ r"Jonanthan and Kimberly Farkus",
697
696
  r"Thomas\s*(J\.?\s*)?Barrack(\s*Jr)?",
698
697
  ],
699
698
  ),
@@ -800,24 +799,26 @@ HIGHLIGHTED_NAMES = [
800
799
  r"Arianna(\s*Huffington)?",
801
800
  r"(Arthur\s*)?Kretchmer",
802
801
  r'Associated\s*Press',
802
+ r"Axios",
803
803
  r"BBC",
804
- r"Bloomberg",
805
804
  r"Breitbart",
806
805
  r"Charlie\s*Rose",
807
806
  r"China\s*Daily",
808
807
  r"CNBC",
809
808
  r"CNN(politics?)?",
810
- r"Con[cs]hita",
811
- r"Sarnoff",
809
+ r"Con[cs]hita", r"Sarnoff",
810
+ r"Daily Business Review",
812
811
  r"(?<!Virgin[-\s]Islands[-\s])Daily\s*(Beast|Mail|News|Telegraph)",
813
812
  r"(David\s*)?(Pecker|Pegg)",
814
813
  r"David\s*Brooks",
815
814
  r"Ed\s*Krassenstein",
816
815
  r"(Emily\s*)?Michot",
817
816
  r"Ezra\s*Klein",
817
+ r"Fox\s*News(\.com)?",
818
818
  r"FrontPage Magazine",
819
819
  r"FT",
820
820
  r"(George\s*)?Stephanopoulus",
821
+ r"Ger(ald|ry)\s*Baker",
821
822
  r"Globe\s*and\s*Mail",
822
823
  r"Good\s*Morning\s*America",
823
824
  r"Graydon(\s*Carter)?",
@@ -829,9 +830,14 @@ HIGHLIGHTED_NAMES = [
829
830
  r"(Katie\s*)?Couric",
830
831
  r"Keith\s*Larsen",
831
832
  r"L\.?A\.?\s*Times",
833
+ r"Law(360|\.com|fare)",
834
+ r"MarketWatch",
832
835
  r"Miami\s*Herald",
836
+ r"(Mi(chael|ke)\s*)?Bloomberg",
833
837
  r"(Michele\s*)?Dargan",
838
+ r"Morning News USA",
834
839
  r"(National\s*)?Enquirer",
840
+ r"Newsweek",
835
841
  r"NYer",
836
842
  r"Palm\s*Beach\s*(Daily\s*News|Post)",
837
843
  r"PERVERSION\s*OF\s*JUSTICE",
@@ -843,6 +849,8 @@ HIGHLIGHTED_NAMES = [
843
849
  r"Susan Edelman",
844
850
  r"(The\s*)?Financial\s*Times",
845
851
  r"The\s*Guardian",
852
+ r"TheHill",
853
+ r"(The\s*)?Mail\s*On\s*Sunday",
846
854
  r"(The\s*)?N(ew\s*)?Y(ork\s*)?(P(ost)?|T(imes)?)",
847
855
  r"(The\s*)?New\s*Yorker",
848
856
  r"(The\s*)?Wall\s*Street\s*Journal",
@@ -857,6 +865,18 @@ HIGHLIGHTED_NAMES = [
857
865
  r"[-\w.]+@(bbc|independent|mailonline|mirror|thetimes)\.co\.uk",
858
866
  ],
859
867
  ),
868
+ HighlightedNames(
869
+ label=JUNK,
870
+ style='gray46',
871
+ emailers={
872
+ 'asmallworld@travel.asmallworld.net': None,
873
+ "digest-noreply@quora.com": None,
874
+ 'editorialstaff@flipboard.com': None,
875
+ 'How To Academy': None,
876
+ 'Jokeland': None,
877
+ },
878
+ should_match_first_last_name=False,
879
+ ),
860
880
  HighlightedNames(
861
881
  label='Latin America',
862
882
  style='yellow',
@@ -866,11 +886,12 @@ HIGHLIGHTED_NAMES = [
866
886
  r"Bra[sz]il(ian)?",
867
887
  r"Caracas",
868
888
  r"Castro",
889
+ r"Chile",
869
890
  r"Colombian?",
870
891
  r"Cuban?",
871
892
  r"El\s*Salvador",
872
893
  r"((Enrique )?Pena )?Nieto",
873
- r"Lat(in)?\s*Am(erica)?",
894
+ r"Lat(in)?\s*Am(erican?)?",
874
895
  r"Lula",
875
896
  r"Mexic(an|o)",
876
897
  r"(Nicolas\s+)?Maduro",
@@ -990,6 +1011,7 @@ HIGHLIGHTED_NAMES = [
990
1011
  r"Basiji?",
991
1012
  r"Beirut",
992
1013
  r"Benghazi",
1014
+ r"Brunei",
993
1015
  r"Cairo",
994
1016
  r"Chagoury",
995
1017
  r"Damascus",
@@ -1078,6 +1100,7 @@ HIGHLIGHTED_NAMES = [
1078
1100
  },
1079
1101
  patterns=[
1080
1102
  r"\w+@mc2mm.com",
1103
+ r"MC2",
1081
1104
  r"model(ed|ing)",
1082
1105
  r"(Nicole\s*)?Junkerman", # Also a venture fund manager now
1083
1106
  ],
@@ -1100,6 +1123,7 @@ HIGHLIGHTED_NAMES = [
1100
1123
  patterns=[
1101
1124
  r"(Matt(hew)? )?Hiltzi[gk]",
1102
1125
  REPUTATION_MGMT,
1126
+ r"Reputation.com",
1103
1127
  ],
1104
1128
  ),
1105
1129
  HighlightedNames(
@@ -1123,7 +1147,6 @@ HIGHLIGHTED_NAMES = [
1123
1147
  r"(?<!Merwin Dela )Cruz",
1124
1148
  r"Devin\s*Nunes",
1125
1149
  r"(Don\s*)?McGa[hn]n",
1126
- r"Fox\s*News",
1127
1150
  r"George\s*(H\.?\s*)?(W\.?\s*)?Bush",
1128
1151
  r"(George\s*)?Nader",
1129
1152
  r"GOP",
@@ -1160,7 +1183,7 @@ HIGHLIGHTED_NAMES = [
1160
1183
  style='indian_red',
1161
1184
  emailers={
1162
1185
  ARIANE_DE_ROTHSCHILD: 'heiress',
1163
- JOHNNY_EL_HACHEM: f'works with {ARIANE_DE_ROTHSCHILD}',
1186
+ JOHNNY_EL_HACHEM: f'Edmond de Rothschild Private Equity',
1164
1187
  },
1165
1188
  patterns=['AdR'],
1166
1189
  ),
@@ -1208,7 +1231,6 @@ HIGHLIGHTED_NAMES = [
1208
1231
  r"(Vitaly\s*)?Churkin",
1209
1232
  ],
1210
1233
  ),
1211
-
1212
1234
  HighlightedNames(
1213
1235
  label='Southeast Asia',
1214
1236
  style='light_salmon3 bold',
@@ -1220,7 +1242,7 @@ HIGHLIGHTED_NAMES = [
1220
1242
  r"Malaysian?",
1221
1243
  r"Myan?mar",
1222
1244
  r"Philippines",
1223
- r"South\s*Korea",
1245
+ r"South\s*Korean?",
1224
1246
  r"Tai(pei|wan)",
1225
1247
  r"Thai(land)?",
1226
1248
  r"Vietnam(ese)?",
@@ -1245,7 +1267,10 @@ HIGHLIGHTED_NAMES = [
1245
1267
  r"Eric\s*Schmidt",
1246
1268
  r"Greylock(\s*Partners)?",
1247
1269
  r"(?<!(ustin|Moshe)\s)Hoffmand?",
1270
+ r"(Jeff\s*)?Bezos",
1271
+ r"Larry Page",
1248
1272
  r"LinkedIn",
1273
+ r"(Marc\s*)?Andreess?en",
1249
1274
  r"(Mark\s*)?Zuckerberg",
1250
1275
  r"Masa(yoshi)?(\sSon)?",
1251
1276
  r"Najeev",
@@ -1273,7 +1298,7 @@ HIGHLIGHTED_NAMES = [
1273
1298
  r"\bDJ?T\b",
1274
1299
  r"Donald J. Tramp",
1275
1300
  r"(Donald\s+(J\.\s+)?)?Trump(ism|\s*(Org(anization)?|Properties)(\s*LLC)?)?",
1276
- r"Don(ald| *Jr)(?! Rubin)",
1301
+ r"Don(ald| *Jr)(?! (B|Rubin))",
1277
1302
  r"Ivank?a",
1278
1303
  r"Jared",
1279
1304
  r"Kushner",
@@ -1282,6 +1307,7 @@ HIGHLIGHTED_NAMES = [
1282
1307
  r"(Marla\s*)?Maples",
1283
1308
  r"(Matt(hew)? )?Calamari",
1284
1309
  r"\bMatt C\b",
1310
+ r"Michael\s*Cohen",
1285
1311
  r"Melania",
1286
1312
  r"(Michael (J.? )?)?Boccio",
1287
1313
  r"Paul Rampell",
@@ -1295,6 +1321,8 @@ HIGHLIGHTED_NAMES = [
1295
1321
  label='victim',
1296
1322
  style='orchid1',
1297
1323
  patterns=[
1324
+ r"(David\s*)?Bo[il]es",
1325
+ r"(Gloria\s*)?Allred",
1298
1326
  r"(Jane|Tiffany)\s*Doe",
1299
1327
  r"Katie\s*Johnson",
1300
1328
  r"(Virginia\s+((L\.?|Roberts)\s+)?)?Giuffre",
@@ -1313,6 +1341,7 @@ HIGHLIGHTED_NAMES = [
1313
1341
  patterns=[
1314
1342
  r"(Alan(\s*P.)?|MINTZ)\s*FRAADE",
1315
1343
  r"(J\.?\s*)?(Stan(ley)?\s*)?Pottinger",
1344
+ r"(Mi(chael|ke)\s*)?Avenatti",
1316
1345
  r"Paul\s*(G.\s*)?Cassell",
1317
1346
  r"Rothstein\s*Rosenfeldt\s*Adler",
1318
1347
  r"(Scott\s*)?Rothstein",
@@ -1354,7 +1383,7 @@ HIGHLIGHTED_NAMES = [
1354
1383
  patterns=[
1355
1384
  r"BG",
1356
1385
  r"b?g?C3",
1357
- r"(Bill\s*((and|or)\s*Melinda\s*)?)?Gates",
1386
+ r"(Bill\s*((and|or)\s*Melinda\s*)?)?Gates(\s*Foundation)?",
1358
1387
  r"Melinda(\s*Gates)?",
1359
1388
  r"Microsoft",
1360
1389
  r"MSFT",
@@ -1369,6 +1398,7 @@ HIGHLIGHTED_NAMES = [
1369
1398
  },
1370
1399
  patterns=[
1371
1400
  r"(American\s*)?Dharma",
1401
+ r"Biosphere",
1372
1402
  r"((Steve|Sean)\s*)?Bannon?",
1373
1403
  ],
1374
1404
  ),
@@ -1409,7 +1439,7 @@ HIGHLIGHTED_TEXTS = [
1409
1439
  HighlightedText(
1410
1440
  label='header_field',
1411
1441
  style='plum4',
1412
- patterns=[r'^(> )?(Date|From|Sent|To|C[cC]|Importance|Subject|Bee|B[cC]{2}|Attachments):'],
1442
+ patterns=[r'^(> )?(Date|From|Sent|To|C[cC]|Importance|Reply-To|Subject|Bee|B[cC]{2}|Attachments):'],
1413
1443
  ),
1414
1444
  HighlightedText(
1415
1445
  label='http_links',
@@ -1456,6 +1486,7 @@ HIGHLIGHTED_TEXTS = [
1456
1486
  ]
1457
1487
 
1458
1488
  ALL_HIGHLIGHTS = HIGHLIGHTED_NAMES + HIGHLIGHTED_TEXTS
1489
+ JUNK_EMAILERS = [name for name in [hn for hn in HIGHLIGHTED_NAMES if hn.label == JUNK][0].emailers.keys()]
1459
1490
 
1460
1491
 
1461
1492
  class EpsteinHighlighter(RegexHighlighter):
@@ -1507,6 +1538,10 @@ def styled_category(category: str | None) -> Text:
1507
1538
  return Text(category, get_style_for_category(category) or 'wheat4')
1508
1539
 
1509
1540
 
1541
+ def styled_name(name: str | None, default_style: str = DEFAULT_NAME_STYLE) -> Text:
1542
+ return Text(name or UNKNOWN, style=get_style_for_name(name, default_style=default_style))
1543
+
1544
+
1510
1545
  def _get_highlight_group_for_name(name: str | None) -> HighlightedNames | None:
1511
1546
  if name is None:
1512
1547
  return None
@@ -11,21 +11,24 @@ from epstein_files.util.constant import output_files
11
11
  from epstein_files.util.constant.html import *
12
12
  from epstein_files.util.constant.names import *
13
13
  from epstein_files.util.constant.output_files import JSON_FILES_JSON_PATH, JSON_METADATA_PATH
14
- from epstein_files.util.constant.strings import TIMESTAMP_DIM, TIMESTAMP_STYLE
14
+ from epstein_files.util.constant.strings import DEFAULT_NAME_STYLE, TIMESTAMP_DIM, TIMESTAMP_STYLE
15
15
  from epstein_files.util.data import dict_sets_to_lists, sort_dict
16
16
  from epstein_files.util.env import args
17
17
  from epstein_files.util.file_helper import log_file_write
18
- from epstein_files.util.highlighted_group import QUESTION_MARKS_TXT
18
+ from epstein_files.util.highlighted_group import (JUNK_EMAILERS, QUESTION_MARKS_TXT, get_category_txt_for_name,
19
+ get_info_for_name, get_style_for_name, styled_name)
19
20
  from epstein_files.util.logging import logger
20
21
  from epstein_files.util.rich import *
21
22
 
23
+ OTHER_INTERESTING_EMAILS_SUBTITLE = 'Other Interesting Emails\n(these emails have been flagged as being of particular interest)'
22
24
  PRINT_COLOR_KEY_EVERY_N_EMAILS = 150
25
+ ALT_INFO_STYLE = 'medium_purple4'
23
26
 
24
27
  # Order matters. Default names to print emails for.
25
28
  DEFAULT_EMAILERS = [
26
29
  JEREMY_RUBIN,
27
- JOI_ITO,
28
30
  JABOR_Y,
31
+ JOI_ITO,
29
32
  STEVEN_SINOFSKY,
30
33
  AL_SECKEL,
31
34
  DANIEL_SIAD,
@@ -44,6 +47,18 @@ DEFAULT_EMAILERS = [
44
47
  JENNIFER_JACQUET,
45
48
  ZUBAIR_KHAN,
46
49
  None,
50
+ JEFFREY_EPSTEIN,
51
+ ]
52
+
53
+ INTERESTING_EMAIL_IDS = [
54
+ '032229', # Michael Wolff on strategy
55
+ '028784', # seminars: Money / Power
56
+ '029342', # Hakeem Jeffries
57
+ '023454', # Email invitation sent to tech CEOs + Epstein
58
+ '030630', # 'What happens with zubair's project?'
59
+ '033178', # 'How is it going with Zubair?'
60
+ '022396', # Ukraine friend
61
+ # '023627', # Michael Wolff article (already printed bc epstein->epstein email)
47
62
  ]
48
63
 
49
64
  INVALID_FOR_EPSTEIN_WEB = JUNK_EMAILERS + KRASSNER_RECIPIENTS + [
@@ -56,30 +71,15 @@ INVALID_FOR_EPSTEIN_WEB = JUNK_EMAILERS + KRASSNER_RECIPIENTS + [
56
71
 
57
72
  def print_email_timeline(epstein_files: EpsteinFiles) -> None:
58
73
  """Print a table of all emails in chronological order."""
59
- emails = [email for email in epstein_files.non_duplicate_emails() if not email.is_junk_mail()]
60
- table = build_table(f'All {len(emails):,} Non-Junk Emails in Chronological Order', highlight=True)
61
- table.add_column('ID', style=TIMESTAMP_DIM)
62
- table.add_column('Sent At', style='dim')
63
- table.add_column('Author', max_width=20)
64
- table.add_column('Recipients', max_width=22)
65
- table.add_column('Length', justify='right', style='wheat4')
66
- table.add_column('Subject')
67
-
68
- for email in Document.sort_by_timestamp(emails):
69
- if email.is_junk_mail():
70
- continue
74
+ emails = Document.sort_by_timestamp([e for e in epstein_files.non_duplicate_emails() if not e.is_junk_mail()])
75
+ title = f'Table of All {len(emails):,} Non-Junk Emails in Chronological Order (actual emails below)'
76
+ table = Email.build_emails_table(emails, title=title, show_length=True)
77
+ console.print(Padding(table, (2, 0)))
78
+ print_subtitle_panel('The Chronologically Ordered Emails')
79
+ console.line()
71
80
 
72
- table.add_row(
73
- email.epstein_media_link(link_txt=email.source_file_id()),
74
- email.timestamp_without_seconds(),
75
- email.author_txt(),
76
- email.recipients_txt(max_full_names=1),
77
- f"{email.length()}",
78
- email.subject(),
79
- )
80
-
81
- console.line(2)
82
- console.print(table)
81
+ for email in emails:
82
+ console.print(email)
83
83
 
84
84
 
85
85
  def print_emails_section(epstein_files: EpsteinFiles) -> list[Email]:
@@ -112,8 +112,19 @@ def print_emails_section(epstein_files: EpsteinFiles) -> list[Email]:
112
112
  print_color_key()
113
113
  num_emails_printed_since_last_color_key = 0
114
114
 
115
- if not args.names:
116
- epstein_files.print_email_device_info()
115
+ if args.names:
116
+ return already_printed_emails
117
+
118
+ # Print other interesting emails
119
+ already_printed_ids = [email.file_id for email in already_printed_emails]
120
+ extra_emails = [e for e in epstein_files.for_ids(INTERESTING_EMAIL_IDS) if e.file_id not in already_printed_ids]
121
+ print_subtitle_panel(OTHER_INTERESTING_EMAILS_SUBTITLE)
122
+ console.line()
123
+
124
+ for other_email in extra_emails:
125
+ console.print(other_email)
126
+
127
+ epstein_files.print_email_device_info()
117
128
 
118
129
  if args.all_emails:
119
130
  _verify_all_emails_were_printed(epstein_files, already_printed_emails)
@@ -219,7 +230,7 @@ def _all_emailers_table(epstein_files: EpsteinFiles) -> Table:
219
230
  attributed_emails = [e for e in epstein_files.non_duplicate_emails() if e.author]
220
231
  footer = f"(identified {len(epstein_files.email_author_counts)} authors of {len(attributed_emails):,}"
221
232
  footer = f"{footer} out of {len(epstein_files.non_duplicate_emails()):,} emails)"
222
- counts_table = build_table("All of the Email Counterparties Who Appear in the Files", caption=footer)
233
+ counts_table = build_table("Everyone Who Sent or Received an Email in the Files", caption=footer)
223
234
 
224
235
  add_cols_to_table(counts_table, [
225
236
  'Name',
@@ -237,7 +248,7 @@ def _all_emailers_table(epstein_files: EpsteinFiles) -> Table:
237
248
 
238
249
  emailer_counts = {
239
250
  emailer: epstein_files.email_author_counts[emailer] + epstein_files.email_recipient_counts[emailer]
240
- for emailer in epstein_files.all_emailers(True)
251
+ for emailer in epstein_files.all_emailers(include_useless=True)
241
252
  }
242
253
 
243
254
  for name, count in sort_dict(emailer_counts):
@@ -287,7 +298,7 @@ def _table_of_selected_emailers(_list: list[str | None], epstein_files: EpsteinF
287
298
  grey_idx = 0
288
299
 
289
300
  for i, name in enumerate(_list):
290
- earliest_email_date = (epstein_files.earliest_email_at(name) or FALLBACK_TIMESTAMP).date()
301
+ earliest_email_date = (epstein_files.earliest_email_at(name)).date()
291
302
  year_months = (earliest_email_date.year * 12) + earliest_email_date.month
292
303
 
293
304
  # Color year rollovers more brightly
@@ -302,20 +313,20 @@ def _table_of_selected_emailers(_list: list[str | None], epstein_files: EpsteinF
302
313
  info = get_info_for_name(name)
303
314
  style = get_style_for_name(name, default_style='none')
304
315
 
316
+ if name == JEFFREY_EPSTEIN:
317
+ info = Text('(emails sent by Epstein to himself that would not otherwise be printed)', style=ALT_INFO_STYLE)
305
318
  if category and category.plain == 'paula': # TODO: hacky
306
319
  category = None
307
320
  elif category and info:
308
321
  info = info.removeprefix(f"{category.plain}, ").removeprefix(category.plain)
309
322
  elif not name:
310
- info = Text('(emails whose author or recipient could not be determined)', style='medium_purple4')
311
- elif name in JUNK_EMAILERS:
312
- category = Text('junk', style='gray30')
323
+ info = Text('(emails whose author or recipient could not be determined)', style=ALT_INFO_STYLE)
313
324
  elif style == 'none' and '@' not in name and not (category or info):
314
325
  info = QUESTION_MARKS_TXT
315
326
 
316
327
  table.add_row(
317
328
  Text(str(earliest_email_date), style=f"grey{GREY_NUMBERS[grey_idx]}"),
318
- Text(name or UNKNOWN, style=get_style_for_name(name or UNKNOWN, default_style='dim')),
329
+ styled_name(name, default_style='dim'),
319
330
  category,
320
331
  f"{len(epstein_files.emails_for(name)):,}",
321
332
  info or '',