epstein-files 1.2.0__py3-none-any.whl → 1.2.1__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.
- epstein_files/__init__.py +11 -24
- epstein_files/documents/communication.py +0 -3
- epstein_files/documents/document.py +61 -18
- epstein_files/documents/email.py +11 -5
- epstein_files/documents/emails/email_header.py +10 -2
- epstein_files/documents/imessage/text_message.py +3 -2
- epstein_files/documents/other_file.py +16 -34
- epstein_files/epstein_files.py +23 -33
- epstein_files/person.py +39 -65
- epstein_files/util/constant/names.py +13 -6
- epstein_files/util/constant/strings.py +0 -1
- epstein_files/util/constant/urls.py +1 -0
- epstein_files/util/constants.py +3 -1
- epstein_files/util/data.py +1 -1
- epstein_files/util/doc_cfg.py +3 -3
- epstein_files/util/env.py +4 -4
- epstein_files/util/highlighted_group.py +112 -94
- epstein_files/util/logging.py +1 -1
- epstein_files/util/output.py +36 -12
- epstein_files/util/rich.py +14 -14
- epstein_files/util/timer.py +14 -0
- {epstein_files-1.2.0.dist-info → epstein_files-1.2.1.dist-info}/METADATA +5 -2
- epstein_files-1.2.1.dist-info/RECORD +34 -0
- epstein_files-1.2.0.dist-info/RECORD +0 -34
- {epstein_files-1.2.0.dist-info → epstein_files-1.2.1.dist-info}/LICENSE +0 -0
- {epstein_files-1.2.0.dist-info → epstein_files-1.2.1.dist-info}/WHEEL +0 -0
- {epstein_files-1.2.0.dist-info → epstein_files-1.2.1.dist-info}/entry_points.txt +0 -0
epstein_files/person.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from dataclasses import dataclass, field
|
|
2
2
|
from datetime import datetime, date
|
|
3
|
+
from typing import Sequence
|
|
3
4
|
|
|
4
5
|
from rich.console import Group, RenderableType
|
|
5
6
|
from rich.padding import Padding
|
|
@@ -18,13 +19,14 @@ from epstein_files.util.data import days_between, flatten, without_falsey
|
|
|
18
19
|
from epstein_files.util.env import args
|
|
19
20
|
from epstein_files.util.highlighted_group import (QUESTION_MARKS_TXT, HighlightedNames,
|
|
20
21
|
get_highlight_group_for_name, get_style_for_name, styled_category, styled_name)
|
|
21
|
-
from epstein_files.util.rich import GREY_NUMBERS,
|
|
22
|
+
from epstein_files.util.rich import GREY_NUMBERS, TABLE_TITLE_STYLE, build_table, console, join_texts, print_centered
|
|
22
23
|
|
|
23
24
|
ALT_INFO_STYLE = 'medium_purple4'
|
|
24
25
|
CC = 'cc:'
|
|
25
26
|
MIN_AUTHOR_PANEL_WIDTH = 80
|
|
26
27
|
EMAILER_INFO_TITLE = 'Email Conversations Will Appear'
|
|
27
|
-
UNINTERESTING_CC_INFO = "
|
|
28
|
+
UNINTERESTING_CC_INFO = "cc: or bcc: recipient only"
|
|
29
|
+
UNINTERESTING_CC_INFO_NO_CONTACT = f"{UNINTERESTING_CC_INFO}, no direct contact with Epstein"
|
|
28
30
|
|
|
29
31
|
INVALID_FOR_EPSTEIN_WEB = JUNK_EMAILERS + MAILING_LISTS + [
|
|
30
32
|
'ACT for America',
|
|
@@ -100,6 +102,10 @@ class Person:
|
|
|
100
102
|
links = [self.external_link_txt(site) for site in PERSON_LINK_BUILDERS]
|
|
101
103
|
return Text('', justify='center', style='dim').append(join_texts(links, join=' / ')) #, encloser='()'))#, encloser='‹›'))
|
|
102
104
|
|
|
105
|
+
def has_any_epstein_emails(self) -> bool:
|
|
106
|
+
contacts = [e.author for e in self.emails] + flatten([e.recipients for e in self.emails])
|
|
107
|
+
return JEFFREY_EPSTEIN in contacts
|
|
108
|
+
|
|
103
109
|
def highlight_group(self) -> HighlightedNames | None:
|
|
104
110
|
return get_highlight_group_for_name(self.name)
|
|
105
111
|
|
|
@@ -132,7 +138,10 @@ class Person:
|
|
|
132
138
|
if highlight_group and isinstance(highlight_group, HighlightedNames) and self.name:
|
|
133
139
|
return highlight_group.info_for(self.name)
|
|
134
140
|
elif self.is_uninteresting_cc:
|
|
135
|
-
|
|
141
|
+
if self.has_any_epstein_emails():
|
|
142
|
+
return UNINTERESTING_CC_INFO
|
|
143
|
+
else:
|
|
144
|
+
return UNINTERESTING_CC_INFO_NO_CONTACT
|
|
136
145
|
|
|
137
146
|
def info_with_category(self) -> str:
|
|
138
147
|
return ', '.join(without_falsey([self.category(), self.info_str()]))
|
|
@@ -144,13 +153,18 @@ class Person:
|
|
|
144
153
|
return Text('(emails whose author or recipient could not be determined)', style=ALT_INFO_STYLE)
|
|
145
154
|
elif self.category() == JUNK:
|
|
146
155
|
return Text(f"({JUNK} mail)", style='tan dim')
|
|
156
|
+
elif self.is_uninteresting_cc and (self.info_str() or '').startswith(UNINTERESTING_CC_INFO):
|
|
157
|
+
if self.info_str() == UNINTERESTING_CC_INFO:
|
|
158
|
+
return Text(f"({self.info_str()})", style='wheat4 dim')
|
|
159
|
+
else:
|
|
160
|
+
return Text(f"({self.info_str()})", style='plum4 dim')
|
|
147
161
|
elif self.is_a_mystery():
|
|
148
|
-
return Text(QUESTION_MARKS, style='
|
|
149
|
-
elif self.is_uninteresting_cc and self.info_str() == UNINTERESTING_CC_INFO:
|
|
150
|
-
return Text(f"({self.info_str()})", style='wheat4 dim')
|
|
162
|
+
return Text(QUESTION_MARKS, style='honeydew2 bold')
|
|
151
163
|
elif self.info_str() is None:
|
|
152
164
|
if self.name in MAILING_LISTS:
|
|
153
|
-
return Text('(mailing list)', style=f"
|
|
165
|
+
return Text('(mailing list)', style=f"pale_turquoise4 dim")
|
|
166
|
+
elif self.category():
|
|
167
|
+
return Text(QUESTION_MARKS, style=self.style())
|
|
154
168
|
else:
|
|
155
169
|
return None
|
|
156
170
|
else:
|
|
@@ -214,8 +228,8 @@ class Person:
|
|
|
214
228
|
return self._printable_emails()
|
|
215
229
|
|
|
216
230
|
def print_emails_table(self) -> None:
|
|
217
|
-
|
|
218
|
-
print_centered(Padding(
|
|
231
|
+
table = Email.build_emails_table(self._unique_printable_emails(), self.name)
|
|
232
|
+
print_centered(Padding(table, (0, 5, 0, 5)))
|
|
219
233
|
|
|
220
234
|
if self.is_linkable():
|
|
221
235
|
print_centered(self.external_links_line())
|
|
@@ -223,7 +237,7 @@ class Person:
|
|
|
223
237
|
console.line()
|
|
224
238
|
|
|
225
239
|
def sort_key(self) -> list[int | str]:
|
|
226
|
-
counts = [len(self.unique_emails())]
|
|
240
|
+
counts = [len(self.unique_emails()), int(self.has_any_epstein_emails())]
|
|
227
241
|
counts = [-1 * count for count in counts]
|
|
228
242
|
|
|
229
243
|
if args.sort_alphabetical:
|
|
@@ -234,14 +248,14 @@ class Person:
|
|
|
234
248
|
def style(self) -> str:
|
|
235
249
|
return get_style_for_name(self.name)
|
|
236
250
|
|
|
237
|
-
def unique_emails(self) ->
|
|
238
|
-
return
|
|
251
|
+
def unique_emails(self) -> Sequence[Email]:
|
|
252
|
+
return Document.without_dupes(self.emails)
|
|
239
253
|
|
|
240
254
|
def unique_emails_by(self) -> list[Email]:
|
|
241
|
-
return
|
|
255
|
+
return Document.without_dupes(self.emails_by())
|
|
242
256
|
|
|
243
257
|
def unique_emails_to(self) -> list[Email]:
|
|
244
|
-
return
|
|
258
|
+
return Document.without_dupes(self.emails_to())
|
|
245
259
|
|
|
246
260
|
def _printable_emails(self):
|
|
247
261
|
"""For Epstein we only want to print emails he sent to himself."""
|
|
@@ -250,24 +264,27 @@ class Person:
|
|
|
250
264
|
else:
|
|
251
265
|
return self.emails
|
|
252
266
|
|
|
267
|
+
def _unique_printable_emails(self):
|
|
268
|
+
return Document.without_dupes(self._printable_emails())
|
|
269
|
+
|
|
253
270
|
def __str__(self):
|
|
254
271
|
return f"{self.name_str()}"
|
|
255
272
|
|
|
256
273
|
@staticmethod
|
|
257
|
-
def emailer_info_table(people: list['Person'], highlighted: list['Person'] | None = None) -> Table:
|
|
274
|
+
def emailer_info_table(people: list['Person'], highlighted: list['Person'] | None = None, show_epstein_total: bool = False) -> Table:
|
|
258
275
|
"""Table of info about emailers."""
|
|
259
276
|
highlighted = highlighted or people
|
|
260
277
|
highlighted_names = [p.name for p in highlighted]
|
|
261
|
-
is_selection = len(people) != len(highlighted) or args.
|
|
278
|
+
is_selection = len(people) != len(highlighted) or args.emailers_info
|
|
262
279
|
|
|
263
280
|
if is_selection:
|
|
264
|
-
title = Text(f"{EMAILER_INFO_TITLE} in This Order for the Highlighted Names (
|
|
265
|
-
title.append(THE_OTHER_PAGE_TXT).append("
|
|
281
|
+
title = Text(f"{EMAILER_INFO_TITLE} in This Order for the Highlighted Names (", style=TABLE_TITLE_STYLE)
|
|
282
|
+
title.append(THE_OTHER_PAGE_TXT).append(" has the rest)")
|
|
266
283
|
else:
|
|
267
284
|
title = f"{EMAILER_INFO_TITLE} in Chronological Order Based on Timestamp of First Email"
|
|
268
285
|
|
|
269
286
|
table = build_table(title)
|
|
270
|
-
table.add_column('
|
|
287
|
+
table.add_column('First')
|
|
271
288
|
table.add_column('Name', max_width=24, no_wrap=True)
|
|
272
289
|
table.add_column('Category', justify='left', style='dim italic')
|
|
273
290
|
table.add_column('Num', justify='right', style='white')
|
|
@@ -296,55 +313,12 @@ class Person:
|
|
|
296
313
|
Text(str(earliest_email_date), style=f"grey{GREY_NUMBERS[0 if is_selection else grey_idx]}"),
|
|
297
314
|
person.name_txt(), # TODO: make link?
|
|
298
315
|
person.category_txt(),
|
|
299
|
-
f"{len(person.
|
|
300
|
-
f"{len(person.unique_emails_by())}",
|
|
301
|
-
f"{len(person.unique_emails_to())}",
|
|
316
|
+
f"{len(person.unique_emails() if show_epstein_total else person._unique_printable_emails())}",
|
|
317
|
+
Text(f"{len(person.unique_emails_by())}", style='dim' if len(person.unique_emails_by()) == 0 else ''),
|
|
318
|
+
Text(f"{len(person.unique_emails_to())}", style='dim' if len(person.unique_emails_to()) == 0 else ''),
|
|
302
319
|
f"{person.email_conversation_length_in_days()}",
|
|
303
320
|
person.info_txt() or '',
|
|
304
321
|
style='' if person.name in highlighted_names else 'dim',
|
|
305
322
|
)
|
|
306
323
|
|
|
307
324
|
return table
|
|
308
|
-
|
|
309
|
-
@staticmethod
|
|
310
|
-
def emailer_stats_table(people: list['Person']) -> Table:
|
|
311
|
-
email_authors = [p for p in people if p.emails_by() and p.name]
|
|
312
|
-
all_emails = Document.uniquify(flatten([p.unique_emails() for p in people]))
|
|
313
|
-
attributed_emails = [email for email in all_emails if email.author]
|
|
314
|
-
footer = f"(identified {len(email_authors)} authors of {len(attributed_emails):,}"
|
|
315
|
-
footer = f"{footer} out of {len(attributed_emails):,} emails)"
|
|
316
|
-
|
|
317
|
-
counts_table = build_table(
|
|
318
|
-
f"All {len(email_authors)} People Who Sent or Received an Email in the Files",
|
|
319
|
-
caption=footer,
|
|
320
|
-
cols=[
|
|
321
|
-
'Name',
|
|
322
|
-
{'name': 'Count', 'justify': 'right', 'style': 'bold bright_white'},
|
|
323
|
-
{'name': 'Sent', 'justify': 'right', 'style': 'gray74'},
|
|
324
|
-
{'name': 'Recv', 'justify': 'right', 'style': 'gray74'},
|
|
325
|
-
{'name': 'First', 'style': TIMESTAMP_STYLE},
|
|
326
|
-
{'name': 'Last', 'style': LAST_TIMESTAMP_STYLE},
|
|
327
|
-
{'name': 'Days', 'justify': 'right', 'style': 'dim'},
|
|
328
|
-
JMAIL,
|
|
329
|
-
EPSTEIN_MEDIA,
|
|
330
|
-
EPSTEIN_WEB,
|
|
331
|
-
'Twitter',
|
|
332
|
-
]
|
|
333
|
-
)
|
|
334
|
-
|
|
335
|
-
for person in sorted(people, key=lambda person: person.sort_key()):
|
|
336
|
-
counts_table.add_row(
|
|
337
|
-
person.name_link(),
|
|
338
|
-
f"{len(person.unique_emails()):,}",
|
|
339
|
-
f"{len(person.unique_emails_by()):,}",
|
|
340
|
-
f"{len(person.unique_emails_to()):,}",
|
|
341
|
-
str(person.earliest_email_date()),
|
|
342
|
-
str(person.last_email_date()),
|
|
343
|
-
f"{person.email_conversation_length_in_days()}",
|
|
344
|
-
person.external_link_txt(JMAIL),
|
|
345
|
-
person.external_link_txt(EPSTEIN_MEDIA) if person.is_linkable() else '',
|
|
346
|
-
person.external_link_txt(EPSTEIN_WEB) if person.is_linkable() else '',
|
|
347
|
-
person.external_link_txt(TWITTER),
|
|
348
|
-
)
|
|
349
|
-
|
|
350
|
-
return counts_table
|
|
@@ -214,11 +214,11 @@ UBS = 'UBS'
|
|
|
214
214
|
|
|
215
215
|
# First and last names that should be made part of a highlighting regex for emailers
|
|
216
216
|
NAMES_TO_NOT_HIGHLIGHT = """
|
|
217
|
-
al alain alan alfredo allen alex alexander amanda andres andrew
|
|
218
|
-
bard barrett barry bill black bob boris brad bruce
|
|
219
|
-
carolyn chris christina
|
|
217
|
+
al alain alan alfredo allen alex alexander amanda andres andrew anthony
|
|
218
|
+
bard barrett barry bennet bill black bob boris brad bruce
|
|
219
|
+
caroline carolyn chris christina cohen
|
|
220
220
|
dan daniel danny darren dave david donald
|
|
221
|
-
ed edward edwards enterprise enterprises entourage epstein eric erika etienne
|
|
221
|
+
ed edward edwards enforcement enterprise enterprises entourage epstein eric erika etienne
|
|
222
222
|
faith forget fred friendly frost fuller
|
|
223
223
|
gerald george gold gordon
|
|
224
224
|
haddad harry hay heather henry hill hoffman
|
|
@@ -226,8 +226,8 @@ NAMES_TO_NOT_HIGHLIGHT = """
|
|
|
226
226
|
jack james jay jean jeff jeffrey jennifer jeremy jessica joel john jon jonathan joseph jr
|
|
227
227
|
kahn karl kate katherine kelly ken kevin krassner
|
|
228
228
|
larry laurie lawrence leon lesley linda link lisa
|
|
229
|
-
mann marc marie mark martin melanie michael mike miller mitchell miles morris moskowitz
|
|
230
|
-
nancy neal new nicole
|
|
229
|
+
mann marc marie mark martin matthew melanie michael mike miller mitchell miles morris moskowitz
|
|
230
|
+
nancy neal new nicole norman
|
|
231
231
|
owen
|
|
232
232
|
paul paula pen peter philip prince
|
|
233
233
|
randall rangel reid richard robert rodriguez roger rosenberg ross roth roy rubin
|
|
@@ -296,3 +296,10 @@ def extract_last_name(name: str) -> str:
|
|
|
296
296
|
return ' '.join(first_last_names[-2:])
|
|
297
297
|
else:
|
|
298
298
|
return first_last_names[-1]
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def reversed_name(name: str) -> str:
|
|
302
|
+
if ' ' not in name:
|
|
303
|
+
return name
|
|
304
|
+
|
|
305
|
+
return f"{extract_last_name(name)}, {extract_first_name(name)}"
|
|
@@ -33,6 +33,7 @@ extracted_file_url = lambda f: f"{EXTRACTS_BASE_URL}/{f}"
|
|
|
33
33
|
# External URLs
|
|
34
34
|
COFFEEZILLA_ARCHIVE_URL = 'https://journaliststudio.google.com/pinpoint/search?collection=061ce61c9e70bdfd'
|
|
35
35
|
COURIER_NEWSROOM_ARCHIVE_URL = 'https://journaliststudio.google.com/pinpoint/search?collection=092314e384a58618'
|
|
36
|
+
EPSTEIN_DOCS_URL = 'https://epstein-docs.github.io'
|
|
36
37
|
OVERSIGHT_REPUBLICANS_PRESSER_URL = 'https://oversight.house.gov/release/oversight-committee-releases-additional-epstein-estate-documents/'
|
|
37
38
|
RAW_OVERSIGHT_DOCS_GOOGLE_DRIVE_URL = 'https://drive.google.com/drive/folders/1hTNH5woIRio578onLGElkTWofUSWRoH_'
|
|
38
39
|
SUBSTACK_URL = 'https://cryptadamus.substack.com/p/i-made-epsteins-text-messages-great'
|
epstein_files/util/constants.py
CHANGED
|
@@ -661,6 +661,7 @@ EMAILS_CONFIG = [
|
|
|
661
661
|
EmailCfg(id='032023', is_fwded_article=True, duplicate_ids=['032012']), # American-Israeli Cooperative Enterprise Newsletter
|
|
662
662
|
EmailCfg(id='021758', is_fwded_article=True, duplicate_ids=['030616']), # Radar Online article about Epstein's early prison release
|
|
663
663
|
EmailCfg(id='033297', is_fwded_article=True, duplicate_ids=['033586']), # Sultan Sulayem fwding article about Trump and Russia
|
|
664
|
+
EmailCfg(id='030983', is_fwded_article=True), # Power Line blog Alex Acosta and Jeffrey Epstein Plea Deal Analysis
|
|
664
665
|
EmailCfg(id='031774', is_fwded_article=True), # Krassner fwd of Palmer Report article
|
|
665
666
|
EmailCfg(id='033345', is_fwded_article=True), # Krassner fwd of Palmer Report article
|
|
666
667
|
EmailCfg(id='029903', is_fwded_article=True), # Krassner fwd of Ann Coulter article about Epstein
|
|
@@ -874,7 +875,7 @@ TWEET = 'tweet'
|
|
|
874
875
|
# Legal cases
|
|
875
876
|
BRUNEL_V_EPSTEIN = f"{JEAN_LUC_BRUNEL} v. {JEFFREY_EPSTEIN} and Tyler McDonald d/b/a YI.org"
|
|
876
877
|
EDWARDS_V_DERSHOWITZ = f"{BRAD_EDWARDS} & {PAUL_G_CASSELL} v. {ALAN_DERSHOWITZ}"
|
|
877
|
-
EPSTEIN_V_ROTHSTEIN_EDWARDS = f"Epstein v. Scott Rothstein, {BRAD_EDWARDS},
|
|
878
|
+
EPSTEIN_V_ROTHSTEIN_EDWARDS = f"Epstein v. Scott Rothstein, {BRAD_EDWARDS}, & L.M."
|
|
878
879
|
GIUFFRE_V_DERSHOWITZ = f"{VIRGINIA_GIUFFRE} v. {ALAN_DERSHOWITZ}"
|
|
879
880
|
GIUFFRE_V_EPSTEIN = f"{VIRGINIA_GIUFFRE} v. {JEFFREY_EPSTEIN}"
|
|
880
881
|
GIUFFRE_V_MAXWELL = f"{VIRGINIA_GIUFFRE} v. {GHISLAINE_MAXWELL}"
|
|
@@ -1723,6 +1724,7 @@ UNINTERESTING_EMAILERS = FLIGHT_IN_2012_PEOPLE + IRAN_DEAL_RECIPIENTS + [
|
|
|
1723
1724
|
'Oliver Goodenough', # Robert Trivers CC
|
|
1724
1725
|
'Peter Aldhous', # Lawrence Krauss CC
|
|
1725
1726
|
'Players2', # Hoffenberg CC
|
|
1727
|
+
'Police Code Enforcement', # Kirk Blouin / John Page CC
|
|
1726
1728
|
'Sam Harris', # Lawrence Krauss CC
|
|
1727
1729
|
SAMUEL_LEFF, # Random CC
|
|
1728
1730
|
'Sean T Lehane', # Random CC
|
epstein_files/util/data.py
CHANGED
|
@@ -29,7 +29,7 @@ escape_single_quotes = lambda text: text.replace("'", r"\'")
|
|
|
29
29
|
iso_timestamp = lambda dt: dt.isoformat().replace('T', ' ')
|
|
30
30
|
days_between = lambda dt1, dt2: (dt2 - dt1).days + 1
|
|
31
31
|
days_between_str = lambda dt1, dt2: f"{days_between(dt1, dt2)} day" + ('s' if days_between(dt1, dt2) > 1 else '')
|
|
32
|
-
|
|
32
|
+
remove_zero_time = lambda dt: dt.isoformat().removesuffix('T00:00:00')
|
|
33
33
|
uniquify = lambda _list: list(set(_list))
|
|
34
34
|
without_falsey = lambda _list: [e for e in _list if e]
|
|
35
35
|
|
epstein_files/util/doc_cfg.py
CHANGED
|
@@ -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
|
|
11
|
+
from epstein_files.util.data import remove_zero_time, 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]]
|
|
@@ -81,6 +81,7 @@ class DocCfg:
|
|
|
81
81
|
dupe_type: DuplicateType | None = None
|
|
82
82
|
duplicate_ids: list[str] = field(default_factory=list)
|
|
83
83
|
duplicate_of_id: str | None = None
|
|
84
|
+
is_attribution_uncertain: bool = False
|
|
84
85
|
is_interesting: bool | None = None
|
|
85
86
|
is_synthetic: bool = False
|
|
86
87
|
timestamp: datetime | None = None
|
|
@@ -162,7 +163,7 @@ class DocCfg:
|
|
|
162
163
|
elif _field.name == 'timestamp' and self.date is not None:
|
|
163
164
|
continue # Don't print both timestamp and date
|
|
164
165
|
elif isinstance(value, datetime):
|
|
165
|
-
value_str =
|
|
166
|
+
value_str = remove_zero_time(value)
|
|
166
167
|
add_prop(_field, f"parse('{value_str}')" if CONSTANTIZE_NAMES else f"'{value}'")
|
|
167
168
|
elif isinstance(value, str):
|
|
168
169
|
if "'" in value:
|
|
@@ -206,7 +207,6 @@ class CommunicationCfg(DocCfg):
|
|
|
206
207
|
is_attribution_uncertain (bool): True if we have a good idea of who the author is but are not 100% certain
|
|
207
208
|
"""
|
|
208
209
|
attribution_reason: str | None = None
|
|
209
|
-
is_attribution_uncertain: bool = False
|
|
210
210
|
|
|
211
211
|
def __repr__(self) -> str:
|
|
212
212
|
return super().__repr__()
|
epstein_files/util/env.py
CHANGED
|
@@ -38,7 +38,7 @@ output.add_argument('--all-emails', '-ae', action='store_true', help='all the em
|
|
|
38
38
|
output.add_argument('--all-other-files', '-ao', action='store_true', help='all the non-email, non-text msg files instead of just the interesting ones')
|
|
39
39
|
parser.add_argument('--build', '-b', nargs="?", default=None, const=DEFAULT_FILE, help='write output to HTML file')
|
|
40
40
|
output.add_argument('--email-timeline', action='store_true', help='print a table of all emails in chronological order')
|
|
41
|
-
output.add_argument('--emailers-info
|
|
41
|
+
output.add_argument('--emailers-info', action='store_true', help='write a .png of the eeailers info table')
|
|
42
42
|
output.add_argument('--json-files', action='store_true', help='pretty print all the raw JSON data files in the collection and exit')
|
|
43
43
|
output.add_argument('--json-metadata', action='store_true', help='dump JSON metadata for all files and exit')
|
|
44
44
|
output.add_argument('--output-emails', '-oe', action='store_true', help='generate emails section')
|
|
@@ -67,9 +67,9 @@ debug.add_argument('--suppress-logs', '-sl', action='store_true', help='set debu
|
|
|
67
67
|
args = parser.parse_args()
|
|
68
68
|
is_html_script = parser.prog in HTML_SCRIPTS
|
|
69
69
|
|
|
70
|
-
args.build = args.build
|
|
70
|
+
args.build = args.build
|
|
71
71
|
args.debug = args.deep_debug or args.debug or is_env_var_set('DEBUG')
|
|
72
|
-
args.names = [None if n == 'None' else n for n in (args.names or [])]
|
|
72
|
+
args.names = [None if n == 'None' else n.strip() for n in (args.names or [])]
|
|
73
73
|
args.output_emails = args.output_emails or args.all_emails
|
|
74
74
|
args.output_other = args.output_other or args.all_other_files or args.uninteresting
|
|
75
75
|
args.overwrite_pickle = args.overwrite_pickle or (is_env_var_set('OVERWRITE_PICKLE') and not is_env_var_set('PICKLED'))
|
|
@@ -83,7 +83,7 @@ if is_html_script:
|
|
|
83
83
|
if any([is_output_arg(arg) and val for arg, val in vars(args).items()]):
|
|
84
84
|
if args.email_timeline:
|
|
85
85
|
exit_with_error(f"--email-timeline option is mutually exlusive with other output options")
|
|
86
|
-
elif not args.email_timeline:
|
|
86
|
+
elif not args.email_timeline and not args.emailers_info:
|
|
87
87
|
logger.warning(f"No output section chosen; outputting default selection of texts, selected emails, and other files...")
|
|
88
88
|
args.output_texts = args.output_emails = args.output_other = True
|
|
89
89
|
|