triangle-utils 1.2.12 → 1.3.1

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.
@@ -0,0 +1,655 @@
1
+ import * as nodemailer from "nodemailer"
2
+
3
+ import * as crypto from "crypto"
4
+ import { Config } from "./types/Config"
5
+
6
+ const election_ids = new Set([
7
+ "2026-house-nc-11-election",
8
+ "2026-house-co-05-election",
9
+ "2026-house-il-01-election",
10
+ "2026-house-co-03-election",
11
+ "2026-house-pa-12-election",
12
+ "2026-house-nc-10-election",
13
+ "2026-house-fl-22-election",
14
+ "2026-house-fl-19-election",
15
+ "2026-house-ny-04-election",
16
+ "2026-house-tx-38-election",
17
+ "2026-house-pa-07-election",
18
+ "2026-house-ct-02-election",
19
+ "2026-house-tx-20-election",
20
+ "2026-house-or-01-election",
21
+ "2026-house-ca-42-election",
22
+ "2026-house-mi-05-election",
23
+ "2026-house-ne-01-election",
24
+ "2026-sen-ne-election",
25
+ "2026-house-nj-09-election",
26
+ "2026-house-nc-12-election",
27
+ "2026-house-nh-01-election",
28
+ "2026-house-ny-14-election",
29
+ "2026-house-ny-22-election",
30
+ "2026-sen-de-election",
31
+ "2026-house-nc-06-election",
32
+ "2026-house-fl-26-election",
33
+ "2026-house-az-04-election",
34
+ "2026-house-az-07-election",
35
+ "2026-house-nc-02-election",
36
+ "2026-house-vt-al-election",
37
+ "2026-house-in-06-election",
38
+ "2026-house-ca-19-election",
39
+ "2026-house-va-07-election",
40
+ "2026-house-ok-03-election",
41
+ "2026-house-ma-07-election",
42
+ "2026-house-fl-15-election",
43
+ "2026-sen-nh-election",
44
+ "2026-house-ks-03-election",
45
+ "2026-house-ga-02-election",
46
+ "2026-house-tx-09-election",
47
+ "2026-house-pa-08-election",
48
+ "2026-house-in-09-election",
49
+ "2026-house-la-05-election",
50
+ "2026-house-nj-10-election",
51
+ "2026-house-tx-36-election",
52
+ "2026-house-ky-04-election",
53
+ "2026-house-mo-01-election",
54
+ "2026-house-mn-07-election",
55
+ "2026-house-ri-01-election",
56
+ "2026-house-ny-01-election",
57
+ "2026-house-tx-23-election",
58
+ "2026-house-mt-01-election",
59
+ "2026-house-nv-01-election",
60
+ "2026-house-mn-01-election",
61
+ "2026-house-wa-10-election",
62
+ "2026-house-fl-18-election",
63
+ "2026-house-ky-01-election",
64
+ "2026-house-ga-06-election",
65
+ "2026-house-ny-10-election",
66
+ "2026-house-nj-05-election",
67
+ "2026-house-al-03-election",
68
+ "2026-house-mn-02-election",
69
+ "2026-house-sc-04-election",
70
+ "2026-house-tx-11-election",
71
+ "2026-house-mo-06-election",
72
+ "2026-house-tn-09-election",
73
+ "2026-house-il-04-election",
74
+ "2026-house-ca-40-election",
75
+ "2026-house-fl-27-election",
76
+ "2026-house-ok-01-election",
77
+ "2026-house-tx-07-election",
78
+ "2026-house-pa-15-election",
79
+ "2026-house-nm-01-election",
80
+ "2026-house-tx-04-election",
81
+ "2026-house-fl-13-election",
82
+ "2026-house-ny-11-election",
83
+ "2026-house-ga-09-election",
84
+ "2026-house-ca-37-election",
85
+ "2026-house-ca-43-election",
86
+ "2026-house-ca-39-election",
87
+ "2026-house-ca-38-election",
88
+ "2026-house-ga-03-election",
89
+ "2026-house-in-07-election",
90
+ "2026-house-ca-30-election",
91
+ "2026-house-il-08-election",
92
+ "2026-house-fl-14-election",
93
+ "2026-house-tx-13-election",
94
+ "2026-house-il-07-election",
95
+ "2026-sen-sc-election",
96
+ "2026-house-wy-al-election",
97
+ "2026-house-hi-02-election",
98
+ "2026-house-il-02-election",
99
+ "2026-house-fl-11-election",
100
+ "2026-house-az-02-election",
101
+ "2026-house-ca-02-election",
102
+ "2026-house-fl-12-election",
103
+ "2026-sen-ma-election",
104
+ "2026-sen-la-election",
105
+ "2026-house-va-09-election",
106
+ "2026-house-ms-02-election",
107
+ "2026-house-ca-08-election",
108
+ "2026-house-id-02-election",
109
+ "2026-house-tn-02-election",
110
+ "2026-sen-ri-election",
111
+ "2026-house-ia-04-election",
112
+ "2026-house-il-11-election",
113
+ "2026-sen-al-election",
114
+ "2026-house-ca-27-election",
115
+ "2026-house-sc-03-election",
116
+ "2026-sen-nc-election",
117
+ "2026-house-ar-01-election",
118
+ "2026-house-oh-02-election",
119
+ "2026-house-fl-04-election",
120
+ "2026-house-oh-08-election",
121
+ "2026-house-me-01-election",
122
+ "2026-house-ca-31-election",
123
+ "2026-house-nc-08-election",
124
+ "2026-house-tx-34-election",
125
+ "2026-house-oh-12-election",
126
+ "2026-house-tn-06-election",
127
+ "2026-house-oh-09-election",
128
+ "2026-house-ca-03-election",
129
+ "2026-house-nc-07-election",
130
+ "2026-house-ca-13-election",
131
+ "2026-house-ar-03-election",
132
+ "2026-house-ny-13-election",
133
+ "2026-house-ga-12-election",
134
+ "2026-sen-id-election",
135
+ "2026-house-nj-07-election",
136
+ "2026-sen-ga-election",
137
+ "2026-house-ny-05-election",
138
+ "2026-sen-mi-election",
139
+ "2026-house-ca-25-election",
140
+ "2026-house-va-03-election",
141
+ "2026-sen-ar-election",
142
+ "2026-sen-tx-election",
143
+ "2026-house-ca-09-election",
144
+ "2026-house-wa-08-election",
145
+ "2026-sen-tn-election",
146
+ "2026-house-ca-33-election",
147
+ "2026-house-ga-14-election",
148
+ "2026-house-ok-02-election",
149
+ "2026-house-fl-03-election",
150
+ "2026-house-id-01-election",
151
+ "2026-house-ca-16-election",
152
+ "2026-house-nc-13-election",
153
+ "2026-house-ms-01-election",
154
+ "2026-sen-mt-election",
155
+ "2026-house-nv-02-election",
156
+ "2026-house-ga-01-election",
157
+ "2026-house-mn-06-election",
158
+ "2026-house-ga-10-election",
159
+ "2026-house-or-05-election",
160
+ "2026-house-wi-04-election",
161
+ "2026-house-wi-07-election",
162
+ "2026-house-ks-04-election",
163
+ "2026-house-al-05-election",
164
+ "2026-house-oh-01-election",
165
+ "2026-house-al-07-election",
166
+ "2026-house-ne-02-election",
167
+ "2026-house-ca-18-election",
168
+ "2026-house-tx-32-election",
169
+ "2026-house-ca-44-election",
170
+ "2026-house-az-05-election",
171
+ "2026-house-al-01-election",
172
+ "2026-house-fl-20-election",
173
+ "2026-house-ma-05-election",
174
+ "2026-house-ca-34-election",
175
+ "2026-house-md-05-election",
176
+ "2026-house-ca-49-election",
177
+ "2026-house-ca-41-election",
178
+ "2026-house-tn-04-election",
179
+ "2026-house-tx-35-election",
180
+ "2026-house-co-07-election",
181
+ "2026-house-oh-13-election",
182
+ "2026-house-ny-24-election",
183
+ "2026-house-ca-36-election",
184
+ "2026-house-ga-11-election",
185
+ "2026-house-sc-01-election",
186
+ "2026-house-ca-20-election",
187
+ "2026-house-nj-12-election",
188
+ "2026-house-mi-13-election",
189
+ "2026-house-ca-29-election",
190
+ "2026-house-ma-03-election",
191
+ "2026-house-md-08-election",
192
+ "2026-house-md-06-election",
193
+ "2026-house-mi-01-election",
194
+ "2026-house-oh-11-election",
195
+ "2026-house-nv-03-election",
196
+ "2026-house-tx-01-election",
197
+ "2026-house-in-05-election",
198
+ "2026-house-ny-23-election",
199
+ "2026-house-co-01-election",
200
+ "2026-house-mi-12-election",
201
+ "2026-house-ia-02-election",
202
+ "2026-house-or-03-election",
203
+ "2026-house-ut-04-election",
204
+ "2026-house-ny-07-election",
205
+ "2026-house-ar-04-election",
206
+ "2026-sen-nm-election",
207
+ "2026-house-hi-01-election",
208
+ "2026-house-tx-15-election",
209
+ "2026-house-md-02-election",
210
+ "2026-house-mi-11-election",
211
+ "2026-house-ca-28-election",
212
+ "2026-house-oh-15-election",
213
+ "2026-house-mo-03-election",
214
+ "2026-house-ga-05-election",
215
+ "2026-house-mo-05-election",
216
+ "2026-house-tn-07-election",
217
+ "2026-house-in-01-election",
218
+ "2026-house-de-al-election",
219
+ "2026-house-wv-01-election",
220
+ "2026-house-co-04-election",
221
+ "2026-house-tx-10-election",
222
+ "2026-house-fl-17-election",
223
+ "2026-house-nd-al-election",
224
+ "2026-house-ny-21-election",
225
+ "2026-house-ky-05-election",
226
+ "2026-house-md-04-election",
227
+ "2026-house-oh-03-election",
228
+ "2026-house-sc-02-election",
229
+ "2026-house-ma-02-election",
230
+ "2026-house-fl-01-election",
231
+ "2026-house-ny-06-election",
232
+ "2026-house-il-12-election",
233
+ "2026-house-va-06-election",
234
+ "2026-house-tx-06-election",
235
+ "2026-house-ca-51-election",
236
+ "2026-house-ok-05-election",
237
+ "2026-house-va-08-election",
238
+ "2026-house-wv-02-election",
239
+ "2026-house-ca-32-election",
240
+ "2026-house-pa-11-election",
241
+ "2026-house-mn-05-election",
242
+ "2026-house-mn-04-election",
243
+ "2026-house-ca-26-election",
244
+ "2026-house-ca-10-election",
245
+ "2026-house-fl-23-election",
246
+ "2026-house-ca-04-election",
247
+ "2026-house-nc-01-election",
248
+ "2026-house-mn-08-election",
249
+ "2026-house-ny-12-election",
250
+ "2026-house-mn-03-election",
251
+ "2026-house-ms-04-election",
252
+ "2026-house-oh-06-election",
253
+ "2026-house-il-03-election",
254
+ "2026-house-mi-09-election",
255
+ "2026-house-tx-27-election",
256
+ "2026-house-ri-02-election",
257
+ "2026-house-co-06-election",
258
+ "2026-house-tx-21-election",
259
+ "2026-house-mt-02-election",
260
+ "2026-sen-or-election",
261
+ "2026-house-tn-01-election",
262
+ "2026-house-mi-10-election",
263
+ "2026-sen-ak-election",
264
+ "2026-house-ky-03-election",
265
+ "2026-house-ca-48-election",
266
+ "2026-house-tx-05-election",
267
+ "2026-house-il-05-election",
268
+ "2026-house-il-10-election",
269
+ "2026-house-ca-21-election",
270
+ "2026-house-tx-28-election",
271
+ "2026-house-pa-09-election",
272
+ "2026-sen-wv-election",
273
+ "2026-house-nh-02-election",
274
+ "2026-house-sc-07-election",
275
+ "2026-house-nj-04-election",
276
+ "2026-house-mi-08-election",
277
+ "2026-house-wa-09-election",
278
+ "2026-house-il-13-election",
279
+ "2026-house-ma-01-election",
280
+ "2026-house-tx-26-election",
281
+ "2026-house-mo-04-election",
282
+ "2026-house-ma-08-election",
283
+ "2026-house-tx-08-election",
284
+ "2026-house-la-01-election",
285
+ "2026-house-ny-09-election",
286
+ "2026-house-wa-01-election",
287
+ "2026-house-il-14-election",
288
+ "2026-house-ca-17-election",
289
+ "2026-house-wi-06-election",
290
+ "2026-house-tx-12-election",
291
+ "2026-house-fl-05-election",
292
+ "2026-house-oh-04-election",
293
+ "2026-sen-me-election",
294
+ "2026-house-ne-03-election",
295
+ "2026-sen-va-election",
296
+ "2026-house-ct-01-election",
297
+ "2026-house-tx-16-election",
298
+ "2026-house-il-06-election",
299
+ "2026-house-wa-02-election",
300
+ "2026-house-nc-09-election",
301
+ "2026-house-sc-06-election",
302
+ "2026-house-ut-01-election",
303
+ "2026-house-ca-15-election",
304
+ "2026-house-ky-06-election",
305
+ "2026-house-ca-14-election",
306
+ "2026-sen-wy-election",
307
+ "2026-sen-ks-election",
308
+ "2026-house-co-02-election",
309
+ "2026-house-az-09-election",
310
+ "2026-house-mi-07-election",
311
+ "2026-house-ny-08-election",
312
+ "2026-house-ga-04-election",
313
+ "2026-house-md-01-election",
314
+ "2026-house-or-02-election",
315
+ "2026-house-ca-22-election",
316
+ "2026-sen-fl-election",
317
+ "2026-sen-oh-election",
318
+ "2026-house-in-02-election",
319
+ "2026-house-fl-10-election",
320
+ "2026-house-az-06-election",
321
+ "2026-house-tx-14-election",
322
+ "2026-house-wi-01-election",
323
+ "2026-house-va-01-election",
324
+ "2026-house-in-03-election",
325
+ "2026-house-md-03-election",
326
+ "2026-house-ks-02-election",
327
+ "2026-house-ga-13-election",
328
+ "2026-house-fl-07-election",
329
+ "2026-house-tx-17-election",
330
+ "2026-house-va-04-election",
331
+ "2026-house-mi-03-election",
332
+ "2026-sen-ok-election",
333
+ "2026-house-nv-04-election",
334
+ "2026-house-sc-05-election",
335
+ "2026-house-pa-04-election",
336
+ "2026-house-ny-25-election",
337
+ "2026-house-il-16-election",
338
+ "2026-house-la-02-election",
339
+ "2026-house-fl-09-election",
340
+ "2026-house-in-04-election",
341
+ "2026-house-ca-45-election",
342
+ "2026-house-tx-33-election",
343
+ "2026-sen-ms-election",
344
+ "2026-house-al-06-election",
345
+ "2026-house-tx-19-election",
346
+ "2026-house-pa-05-election",
347
+ "2026-house-ny-16-election",
348
+ "2026-house-in-08-election",
349
+ "2026-house-nc-04-election",
350
+ "2026-house-or-06-election",
351
+ "2026-house-tx-02-election",
352
+ "2026-house-nc-14-election",
353
+ "2026-house-pa-14-election",
354
+ "2026-house-nm-03-election",
355
+ "2026-house-ct-05-election",
356
+ "2026-house-il-09-election",
357
+ "2026-house-va-10-election",
358
+ "2026-house-ca-06-election",
359
+ "2026-house-ms-03-election",
360
+ "2026-house-fl-08-election",
361
+ "2026-house-ga-07-election",
362
+ "2026-house-tx-03-election",
363
+ "2026-house-ca-46-election",
364
+ "2026-house-pa-06-election",
365
+ "2026-house-oh-05-election",
366
+ "2026-house-va-11-election",
367
+ "2026-house-tx-22-election",
368
+ "2026-house-nj-06-election",
369
+ "2026-house-tn-05-election",
370
+ "2026-house-ny-20-election",
371
+ "2026-house-oh-14-election",
372
+ "2026-house-ia-01-election",
373
+ "2026-house-fl-02-election",
374
+ "2026-house-al-02-election",
375
+ "2026-house-ia-03-election",
376
+ "2026-house-me-02-election",
377
+ "2026-house-va-02-election",
378
+ "2026-house-nj-02-election",
379
+ "2026-house-wi-05-election",
380
+ "2026-house-ar-02-election",
381
+ "2026-house-tn-08-election",
382
+ "2026-house-ca-52-election",
383
+ "2026-house-ok-04-election",
384
+ "2026-sen-mn-election",
385
+ "2026-sen-sd-election",
386
+ "2026-house-ca-47-election",
387
+ "2026-house-ca-50-election",
388
+ "2026-house-ny-26-election",
389
+ "2026-house-la-03-election",
390
+ "2026-house-mo-07-election",
391
+ "2026-house-la-06-election",
392
+ "2026-house-pa-17-election",
393
+ "2026-house-wa-04-election",
394
+ "2026-house-tn-03-election",
395
+ "2026-house-nj-01-election",
396
+ "2026-sen-ky-election",
397
+ "2026-house-tx-29-election",
398
+ "2026-house-fl-25-election",
399
+ "2026-house-ny-19-election",
400
+ "2026-house-nc-03-election",
401
+ "2026-house-ak-al-election",
402
+ "2026-house-or-04-election",
403
+ "2026-sen-nj-election",
404
+ "2026-house-mi-02-election",
405
+ "2026-house-ny-18-election",
406
+ "2026-house-ny-17-election",
407
+ "2026-house-ca-07-election",
408
+ "2026-house-tx-30-election",
409
+ "2026-house-pa-01-election",
410
+ "2026-house-nm-02-election",
411
+ "2026-house-wa-07-election",
412
+ "2026-house-ca-11-election",
413
+ "2026-house-tx-37-election",
414
+ "2026-house-il-17-election",
415
+ "2026-house-tx-31-election",
416
+ "2026-house-fl-16-election",
417
+ "2026-house-nc-05-election",
418
+ "2026-house-mo-08-election",
419
+ "2026-house-fl-24-election",
420
+ "2026-house-oh-07-election",
421
+ "2026-sen-il-election",
422
+ "2026-house-ky-02-election",
423
+ "2026-house-pa-13-election",
424
+ "2026-house-pa-16-election",
425
+ "2026-house-mo-02-election",
426
+ "2026-house-mi-06-election",
427
+ "2026-house-ct-03-election",
428
+ "2026-house-ut-02-election",
429
+ "2026-house-tx-25-election",
430
+ "2026-house-pa-03-election",
431
+ "2026-house-fl-21-election",
432
+ "2026-house-ca-05-election",
433
+ "2026-house-ma-09-election",
434
+ "2026-house-wa-03-election",
435
+ "2026-house-nj-03-election",
436
+ "2026-house-wa-05-election",
437
+ "2026-house-az-01-election",
438
+ "2026-house-fl-06-election",
439
+ "2026-house-az-03-election",
440
+ "2026-house-pa-02-election",
441
+ "2026-house-la-04-election",
442
+ "2026-house-tx-24-election",
443
+ "2026-house-wi-03-election",
444
+ "2026-house-nj-08-election",
445
+ "2026-house-wi-08-election",
446
+ "2026-house-ny-15-election",
447
+ "2026-house-sd-al-election",
448
+ "2026-house-ca-12-election",
449
+ "2026-house-wa-06-election",
450
+ "2026-house-ks-01-election",
451
+ "2026-sen-co-election",
452
+ "2026-house-ca-35-election",
453
+ "2026-house-ny-02-election",
454
+ "2026-house-nj-11-election",
455
+ "2026-house-tx-18-election",
456
+ "2026-house-md-07-election",
457
+ "2026-house-ma-04-election",
458
+ "2026-house-ca-24-election",
459
+ "2026-house-pa-10-election",
460
+ "2026-house-il-15-election",
461
+ "2026-house-mi-04-election",
462
+ "2026-house-wi-02-election",
463
+ "2026-house-fl-28-election",
464
+ "2026-house-ct-04-election",
465
+ "2026-house-ca-23-election",
466
+ "2026-house-va-05-election",
467
+ "2026-sen-ia-election",
468
+ "2026-house-al-04-election",
469
+ "2026-house-oh-10-election",
470
+ "2026-house-ma-06-election",
471
+ "2026-house-ga-08-election",
472
+ "2026-house-ca-01-election",
473
+ "2026-house-az-08-election",
474
+ "2026-house-ny-03-election",
475
+ "2026-house-co-08-election",
476
+ "2026-house-ut-03-election"
477
+ ])
478
+
479
+ interface Encryption {
480
+ iv : string,
481
+ ciphertext : string
482
+ }
483
+
484
+ export class Utils_Misc {
485
+
486
+ readonly config : Config
487
+ readonly text_encoder : TextEncoder
488
+ readonly transporter
489
+
490
+ constructor(config : Config) {
491
+ this.config = config
492
+ this.text_encoder = new TextEncoder()
493
+ if (config.google_email !== undefined && config.google_app_password !== undefined) {
494
+ this.transporter = nodemailer.createTransport({
495
+ service: "Gmail",
496
+ host: "smtp.gmail.com",
497
+ port: 465,
498
+ secure: true,
499
+ auth: {
500
+ user: config.google_email,
501
+ pass: config.google_app_password,
502
+ }
503
+ })
504
+ }
505
+ }
506
+
507
+ async wait(duration : number) {
508
+ return new Promise(resolve => setTimeout(resolve, duration))
509
+ }
510
+
511
+ get_current_time() {
512
+ return (new Date()).toISOString()
513
+ }
514
+
515
+ get_current_milliseconds() {
516
+ return (new Date()).getTime()
517
+ }
518
+
519
+ async send_email(recipient : string, subject : string, text : string) : Promise<void> {
520
+ if (this.transporter === undefined) {
521
+ return
522
+ }
523
+ for (let i = 0; i < 3; i++) {
524
+ try {
525
+ await this.transporter.sendMail({
526
+ from: this.config.alerts_email,
527
+ to: recipient,
528
+ subject: subject,
529
+ text: text
530
+ })
531
+ return
532
+ } catch (error) {
533
+ console.log("EMAIL ERROR", error)
534
+ }
535
+ }
536
+ }
537
+
538
+ async admin_alert(text : string) {
539
+ console.log("ADMIN ALERT:", text)
540
+ await this.send_email(this.config.google_email, "ADMIN ALERT", text)
541
+ }
542
+
543
+ async safe_run(f : () => Promise<any>) : Promise<void> {
544
+ try {
545
+ await f()
546
+ } catch (error) {
547
+ if (!(error instanceof Error)) {
548
+ return
549
+ }
550
+ if (error.stack !== undefined) {
551
+ await this.admin_alert(error.stack.toString())
552
+ } else {
553
+ await this.admin_alert(error.toString())
554
+ }
555
+ }
556
+ }
557
+
558
+ async iterate<T>(inputs : T[], f : (input : T) => Promise<any>, concurrency : number = 1, print_indices : boolean = false) {
559
+ let index = 0
560
+ let iterators = []
561
+ for (let i = 0; i < concurrency; i++) {
562
+ iterators.push((async () => {
563
+ while (index < inputs.length) {
564
+ index += 1
565
+ if (print_indices) {
566
+ console.log(i + ":" + (index - 1) + "/" + inputs.length)
567
+ }
568
+ await this.safe_run(() => f(inputs[index - 1]))
569
+ }
570
+ })())
571
+ }
572
+ await Promise.all(iterators)
573
+ }
574
+
575
+ async sha256(input : string) : Promise<string> {
576
+ const input_buffer = this.text_encoder.encode(input);
577
+
578
+ const hash_buffer = await crypto.subtle.digest("SHA-256", input_buffer)
579
+
580
+ const hash_array = Array.from(new Uint8Array(hash_buffer))
581
+
582
+ const hash = hash_array.map(b => b.toString(16).padStart(2, "0")).join("")
583
+ return hash
584
+ }
585
+
586
+ encrypt(text : string) : Encryption {
587
+ const iv = crypto.randomBytes(16)
588
+ const cipher = crypto.createCipheriv("aes-256-cbc", Buffer.from(this.config.secret_key, "hex"), iv)
589
+ let ciphertext = cipher.update(text, "utf8", "hex")
590
+ ciphertext += cipher.final("hex")
591
+ return {
592
+ iv: iv.toString("hex"),
593
+ ciphertext: ciphertext
594
+ }
595
+ }
596
+
597
+ decrypt(encryption : Encryption) : string {
598
+ const iv = encryption.iv
599
+ const ciphertext = encryption.ciphertext
600
+ const decipher = crypto.createDecipheriv("aes-256-cbc", Buffer.from(this.config.secret_key, "hex"), Buffer.from(iv, "hex"))
601
+ let text = decipher.update(ciphertext, "hex", "utf8")
602
+ text += decipher.final("utf8")
603
+ return text
604
+ }
605
+
606
+ get_secret_hash(username : string) : string {
607
+ const secret_hash = crypto.createHmac("sha256", this.config.cognito_client_secret)
608
+ .update(username + this.config.cognito_client_id)
609
+ .digest("base64")
610
+ return secret_hash
611
+ }
612
+
613
+ get_election_id(year : string, office : string, state : string, district : string) : string | undefined {
614
+ if (year === undefined || office === undefined || state === undefined || office === "P") {
615
+ return undefined
616
+ }
617
+ if (office === "H" && (district === undefined || district.length !== 2)) {
618
+ return undefined
619
+ }
620
+ if (year.length !== 4 || office.length !== 1 || state.length !== 2) {
621
+ return undefined
622
+ }
623
+ const office_name = { "H" : "house", "S" : "sen", "P" : "pres" }[office]
624
+ const election_id = year + "-" + office_name + "-" + state.toLowerCase() + (office === "H" ? ("-" + district.toLowerCase()) : "") + "-election"
625
+ if (!election_ids.has(election_id)) {
626
+ return undefined
627
+ }
628
+ return election_id
629
+ }
630
+
631
+ get_chunk_indices(text_length : number, max_length = 2500, overlap = 50) : [number, number][] {
632
+ const num_chunks = Math.ceil((text_length + overlap) / max_length)
633
+ const chunk_length = Math.ceil((text_length - overlap) / num_chunks + overlap)
634
+ const chunk_indices : [number, number][] = []
635
+ for (let i = 0; i < num_chunks; i++) {
636
+ chunk_indices.push([
637
+ (chunk_length - overlap) * i,
638
+ (chunk_length - overlap) * i + chunk_length
639
+ ])
640
+ }
641
+ return chunk_indices
642
+ }
643
+
644
+ chunkify(text : string, max_length = 2500, overlap = 50) : {
645
+ chunk_index : [number, number],
646
+ chunk_text : string
647
+ }[] {
648
+ const chunk_indices = this.get_chunk_indices(text.length, max_length, overlap)
649
+ const chunks = chunk_indices.map(chunk_index => ({
650
+ chunk_index : chunk_index,
651
+ chunk_text : text.substring(...chunk_index)
652
+ }))
653
+ return chunks
654
+ }
655
+ }