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.
- package/dist/src/Utils.js +24 -0
- package/dist/src/Utils_Bedrock.js +89 -0
- package/dist/src/Utils_Bee.js +101 -0
- package/dist/src/Utils_DynamoDB.js +381 -0
- package/dist/src/Utils_Misc.js +627 -0
- package/dist/src/Utils_S3.js +96 -0
- package/dist/src/Utils_S3Vectors.js +131 -0
- package/dist/src/Utils_Youtube.js +35 -0
- package/{utils → dist/src}/election_ids.js +472 -474
- package/{states.js → dist/src/states.js} +253 -256
- package/dist/src/types/Config.js +1 -0
- package/dist/types/Config.js +1 -0
- package/eslint.config.ts +13 -0
- package/jest.config.js +19 -0
- package/package.json +23 -3
- package/src/Utils.ts +28 -0
- package/{utils/Utils_Bedrock.js → src/Utils_Bedrock.ts} +23 -12
- package/{utils/Utils_Bee.js → src/Utils_Bee.ts} +39 -19
- package/src/Utils_DynamoDB.ts +448 -0
- package/src/Utils_Misc.ts +655 -0
- package/{utils/Utils_S3.js → src/Utils_S3.ts} +34 -14
- package/{utils/Utils_S3Vectors.js → src/Utils_S3Vectors.ts} +43 -29
- package/{utils/Utils_Youtube.js → src/Utils_Youtube.ts} +13 -6
- package/src/types/Config.ts +9 -0
- package/test/Utils.test.ts +85 -0
- package/tsconfig.json +31 -0
- package/Utils.js +0 -33
- package/test.js +0 -62
- package/utils/Utils_CitizenPortal.js +0 -26
- package/utils/Utils_DynamoDB.js +0 -316
- package/utils/Utils_Misc.js +0 -161
package/utils/Utils_DynamoDB.js
DELETED
|
@@ -1,316 +0,0 @@
|
|
|
1
|
-
import { DynamoDB } from "@aws-sdk/client-dynamodb"
|
|
2
|
-
|
|
3
|
-
function convert_output(dynamoobject) {
|
|
4
|
-
if (dynamoobject.S !== undefined) {
|
|
5
|
-
return dynamoobject.S
|
|
6
|
-
} else if (dynamoobject.BOOL !== undefined) {
|
|
7
|
-
return dynamoobject.BOOL
|
|
8
|
-
} else if (dynamoobject.N !== undefined) {
|
|
9
|
-
return Number(dynamoobject.N)
|
|
10
|
-
} else if (dynamoobject.L !== undefined) {
|
|
11
|
-
return dynamoobject.L.map(a => convert_output(a))
|
|
12
|
-
} else if (dynamoobject.SS !== undefined) {
|
|
13
|
-
return new Set(dynamoobject.SS)
|
|
14
|
-
} else if (dynamoobject.M !== undefined) {
|
|
15
|
-
return Object.fromEntries(Object.entries(dynamoobject.M).map(([key, value]) => [key, convert_output(value)]))
|
|
16
|
-
}
|
|
17
|
-
return undefined
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function convert_input(input) {
|
|
21
|
-
if (typeof input === typeof "") {
|
|
22
|
-
return { S : input }
|
|
23
|
-
} else if (typeof input === typeof true) {
|
|
24
|
-
return { BOOL : input }
|
|
25
|
-
} else if (typeof input === typeof 3.2) {
|
|
26
|
-
return { N : input.toString() }
|
|
27
|
-
} else if (Array.isArray(input)) {
|
|
28
|
-
return { L : input.map(a => convert_input(a)) }
|
|
29
|
-
} else if (input instanceof Set) {
|
|
30
|
-
return { SS : Array.from(input) }
|
|
31
|
-
} else if (typeof input === typeof {}) {
|
|
32
|
-
return {
|
|
33
|
-
M : Object.fromEntries(Object.entries(input)
|
|
34
|
-
.filter(([key, value]) => value !== undefined && value !== null && key !== "")
|
|
35
|
-
.map(([key, value]) => [key, convert_input(value)]))
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return undefined
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async function compile_pages(request, f, compile = true) {
|
|
42
|
-
const items = []
|
|
43
|
-
let last_eval_key = undefined
|
|
44
|
-
while (true) {
|
|
45
|
-
const response = last_eval_key !== undefined ? (
|
|
46
|
-
await f({...request, ExclusiveStartKey : last_eval_key })
|
|
47
|
-
) : (
|
|
48
|
-
await f(request)
|
|
49
|
-
)
|
|
50
|
-
const new_items = response.Items.map(item => convert_output({ M : item }))
|
|
51
|
-
items.push(...new_items)
|
|
52
|
-
if (response.LastEvaluatedKey === undefined || !compile) {
|
|
53
|
-
return items
|
|
54
|
-
}
|
|
55
|
-
last_eval_key = response.LastEvaluatedKey
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export default class Utils_DynamoDB {
|
|
60
|
-
|
|
61
|
-
constructor(config) {
|
|
62
|
-
this.dynamodb = new DynamoDB({ region : config.region })
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async scan(table, options = {}) {
|
|
66
|
-
const filters = options.filters !== undefined ? options.filters : {}
|
|
67
|
-
const undefined_attribute_names = options.undefined_attribute_names !== undefined ? options.undefined_attribute_names : []
|
|
68
|
-
const defined_attribute_names = options.defined_attribute_names !== undefined ? options.defined_attribute_names : []
|
|
69
|
-
const concurrency = options.concurrency !== undefined ? options.concurrency : 1
|
|
70
|
-
const attribute_names = options.attribute_names !== undefined ? options.attribute_names : []
|
|
71
|
-
const iterators = []
|
|
72
|
-
for (let i = 0; i < concurrency; i++) {
|
|
73
|
-
const request = Object.fromEntries(Object.entries({
|
|
74
|
-
TableName : table,
|
|
75
|
-
ExpressionAttributeNames : Object.fromEntries(
|
|
76
|
-
[...Object.keys(filters), ...attribute_names, ...undefined_attribute_names, ...defined_attribute_names]
|
|
77
|
-
.map(attribute_name => ["#" + attribute_name, attribute_name])
|
|
78
|
-
),
|
|
79
|
-
ExpressionAttributeValues : Object.fromEntries(Object.entries(filters).map(([attribute_name, attribute_value]) => [":" + attribute_name, convert_input(attribute_value)])),
|
|
80
|
-
FilterExpression : [
|
|
81
|
-
...Object.keys(filters).map(attribute_name => "#" + attribute_name + " = :" + attribute_name),
|
|
82
|
-
...undefined_attribute_names.map(attribute_name => "attribute_not_exists(#" + attribute_name + ")"),
|
|
83
|
-
...defined_attribute_names.map(attribute_name => "attribute_exists(#" + attribute_name + ")")
|
|
84
|
-
].join(" AND "),
|
|
85
|
-
ProjectionExpression : attribute_names.map(attribute_name => "#" + attribute_name).join(", "),
|
|
86
|
-
Segment : i,
|
|
87
|
-
TotalSegments : concurrency
|
|
88
|
-
}).filter(([field, value]) => value !== undefined && (typeof value === typeof 3 || Object.keys(value).length !== 0)))
|
|
89
|
-
iterators.push(compile_pages(request, (request) => this.dynamodb.scan(request)))
|
|
90
|
-
}
|
|
91
|
-
const segments = await Promise.all(iterators)
|
|
92
|
-
return segments.flat()
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
async get(table, key, consistent=false) {
|
|
96
|
-
const item = await this.dynamodb.getItem({
|
|
97
|
-
ConsistentRead : consistent,
|
|
98
|
-
TableName : table,
|
|
99
|
-
Key : convert_input(key).M
|
|
100
|
-
})
|
|
101
|
-
.then(response => response.Item)
|
|
102
|
-
if (item === undefined) {
|
|
103
|
-
return undefined
|
|
104
|
-
}
|
|
105
|
-
return convert_output({ M : item })
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
async get_max(table, primary_key) {
|
|
109
|
-
if (Object.keys(primary_key).length !== 1) {
|
|
110
|
-
return undefined
|
|
111
|
-
}
|
|
112
|
-
const request = {
|
|
113
|
-
TableName : table,
|
|
114
|
-
ExpressionAttributeNames: {
|
|
115
|
-
"#a": Object.keys(primary_key)[0]
|
|
116
|
-
},
|
|
117
|
-
ExpressionAttributeValues: {
|
|
118
|
-
":a": convert_input(Object.values(primary_key)[0])
|
|
119
|
-
},
|
|
120
|
-
KeyConditionExpression: "#a = :a",
|
|
121
|
-
Limit : 1,
|
|
122
|
-
ScanIndexForward : false
|
|
123
|
-
}
|
|
124
|
-
const items = await this.dynamodb.query(request)
|
|
125
|
-
.then(response => response.Items)
|
|
126
|
-
if (items[0] === undefined) {
|
|
127
|
-
return undefined
|
|
128
|
-
}
|
|
129
|
-
return convert_output({ M : items[0] })
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
async query(table, primary_key, options = {}) {
|
|
135
|
-
const reverse = options.reverse !== undefined ? options.reverse : false
|
|
136
|
-
const compile = options.reverse !== undefined ? options.compile : true
|
|
137
|
-
if (Object.keys(primary_key).length !== 1) {
|
|
138
|
-
return undefined
|
|
139
|
-
}
|
|
140
|
-
const request = {
|
|
141
|
-
TableName : table,
|
|
142
|
-
ExpressionAttributeNames: {
|
|
143
|
-
"#a": Object.keys(primary_key)[0]
|
|
144
|
-
},
|
|
145
|
-
ExpressionAttributeValues: {
|
|
146
|
-
":a": convert_input(Object.values(primary_key)[0])
|
|
147
|
-
},
|
|
148
|
-
KeyConditionExpression: "#a = :a",
|
|
149
|
-
ScanIndexForward : !reverse
|
|
150
|
-
}
|
|
151
|
-
return await compile_pages(request, (request) => this.dynamodb.query(request), compile)
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
async query_prefix(table, primary_key, secondary_key_prefix, options = {}) {
|
|
155
|
-
const reverse = options.reverse !== undefined ? options.reverse : false
|
|
156
|
-
const compile = options.reverse !== undefined ? options.compile : true
|
|
157
|
-
if (Object.keys(primary_key).length !== 1 || Object.keys(secondary_key_prefix).length !== 1) {
|
|
158
|
-
return undefined
|
|
159
|
-
}
|
|
160
|
-
const request = {
|
|
161
|
-
TableName : table,
|
|
162
|
-
ExpressionAttributeNames: {
|
|
163
|
-
"#a": Object.keys(primary_key)[0],
|
|
164
|
-
"#b": Object.keys(secondary_key_prefix)[0]
|
|
165
|
-
},
|
|
166
|
-
ExpressionAttributeValues: {
|
|
167
|
-
":a": convert_input(Object.values(primary_key)[0]),
|
|
168
|
-
":b": convert_input(Object.values(secondary_key_prefix)[0])
|
|
169
|
-
},
|
|
170
|
-
KeyConditionExpression: "#a = :a AND begins_with(#b, :b)",
|
|
171
|
-
ScanIndexForward : !reverse
|
|
172
|
-
}
|
|
173
|
-
return await compile_pages(request, (request) => this.dynamodb.query(request), compile)
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
async query_range(table, primary_key, secondary_key_range, options = {}) {
|
|
177
|
-
const reverse = options.reverse !== undefined ? options.reverse : false
|
|
178
|
-
const compile = options.reverse !== undefined ? options.compile : true
|
|
179
|
-
if (Object.keys(primary_key).length !== 1 || Object.keys(secondary_key_range).length !== 1 || Object.values(secondary_key_range)[0].length !== 2) {
|
|
180
|
-
return undefined
|
|
181
|
-
}
|
|
182
|
-
const request = {
|
|
183
|
-
TableName : table,
|
|
184
|
-
ExpressionAttributeNames: {
|
|
185
|
-
"#a": Object.keys(primary_key)[0],
|
|
186
|
-
"#b": Object.keys(secondary_key_range)[0]
|
|
187
|
-
},
|
|
188
|
-
ExpressionAttributeValues: {
|
|
189
|
-
":a": convert_input(Object.values(primary_key)[0]),
|
|
190
|
-
":b1": convert_input(Object.values(secondary_key_range)[0][0]),
|
|
191
|
-
":b2": convert_input(Object.values(secondary_key_range)[0][1])
|
|
192
|
-
},
|
|
193
|
-
KeyConditionExpression: "#a = :a AND (#b BETWEEN :b1 AND :b2)",
|
|
194
|
-
ScanIndexForward : !reverse
|
|
195
|
-
}
|
|
196
|
-
return await compile_pages(request, (request) => this.dynamodb.query(request), compile)
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
async set(table, key, attributes) {
|
|
200
|
-
return await this.dynamodb.updateItem({
|
|
201
|
-
TableName : table,
|
|
202
|
-
Key : convert_input(key).M,
|
|
203
|
-
UpdateExpression: "set " + Object.keys(attributes)
|
|
204
|
-
.filter(attribute_name => !Object.keys(key).includes(attribute_name))
|
|
205
|
-
.filter(attribute_name => attributes[attribute_name] !== undefined)
|
|
206
|
-
.map(attribute_name => "#" + attribute_name + " = :" + attribute_name
|
|
207
|
-
).join(", "),
|
|
208
|
-
ExpressionAttributeNames: Object.fromEntries(Object.keys(attributes)
|
|
209
|
-
.filter(attribute_name => !Object.keys(key).includes(attribute_name))
|
|
210
|
-
.filter(attribute_name => attributes[attribute_name] !== undefined)
|
|
211
|
-
.map(attribute_name => ["#" + attribute_name, attribute_name]
|
|
212
|
-
)),
|
|
213
|
-
ExpressionAttributeValues: Object.fromEntries(Object.entries(attributes)
|
|
214
|
-
.filter(([attribute_name, attribute_value]) => !Object.keys(key).includes(attribute_name))
|
|
215
|
-
.filter(([attribute_name, attribute_value]) => attribute_value !== undefined)
|
|
216
|
-
.map(([attribute_name, attribute_value]) => [":" + attribute_name, convert_input(attribute_value)]
|
|
217
|
-
))
|
|
218
|
-
})
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
async append(table, key, attributes) {
|
|
222
|
-
return await this.dynamodb.updateItem({
|
|
223
|
-
TableName : table,
|
|
224
|
-
Key : convert_input(key).M,
|
|
225
|
-
UpdateExpression: "set " + Object.keys(attributes)
|
|
226
|
-
.filter(attribute_name => attributes[attribute_name] !== undefined)
|
|
227
|
-
.map(attribute_name => "#" + attribute_name + " = list_append(#" + attribute_name + ", :" + attribute_name + ")").join(", "),
|
|
228
|
-
ExpressionAttributeNames: Object.fromEntries(Object.keys(attributes)
|
|
229
|
-
.filter(attribute_name => attributes[attribute_name] !== undefined)
|
|
230
|
-
.map(attribute_name => ["#" + attribute_name, attribute_name]
|
|
231
|
-
)),
|
|
232
|
-
ExpressionAttributeValues: Object.fromEntries(Object.entries(attributes)
|
|
233
|
-
.filter(([attribute_name, attribute_value]) => attribute_value !== undefined)
|
|
234
|
-
.map(([attribute_name, attribute_value]) => [":" + attribute_name, convert_input(attribute_value)]
|
|
235
|
-
))
|
|
236
|
-
})
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
async add(table, key, attributes) {
|
|
240
|
-
const item = await this.get(table, key, true)
|
|
241
|
-
const new_attributes = {}
|
|
242
|
-
for (const [attribute, values] of Object.entries(attributes)) {
|
|
243
|
-
if (item[attribute] === undefined) {
|
|
244
|
-
continue
|
|
245
|
-
}
|
|
246
|
-
const new_values = values.filter(value => !item[attribute].includes(value))
|
|
247
|
-
if (new_values.length > 0) {
|
|
248
|
-
new_attributes[attribute] = new_values
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
if (Object.values(new_attributes).flat().length === 0) {
|
|
252
|
-
return undefined
|
|
253
|
-
}
|
|
254
|
-
return await this.append(table, key, attributes)
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
async remove(table, key, attributes) {
|
|
258
|
-
return await this.dynamodb.updateItem({
|
|
259
|
-
TableName : table,
|
|
260
|
-
Key : convert_input(key).M,
|
|
261
|
-
UpdateExpression: "remove " + attributes
|
|
262
|
-
.map(attribute_name => "#" + attribute_name).join(", "),
|
|
263
|
-
ExpressionAttributeNames: Object.fromEntries(attributes
|
|
264
|
-
.map(attribute_name => ["#" + attribute_name, attribute_name]
|
|
265
|
-
))
|
|
266
|
-
})
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
async create(table, key, attributes = {}) {
|
|
270
|
-
const item = await this.get(table, key, true)
|
|
271
|
-
if (item !== undefined) {
|
|
272
|
-
return undefined
|
|
273
|
-
}
|
|
274
|
-
return await this.dynamodb.putItem({
|
|
275
|
-
TableName : table,
|
|
276
|
-
Item : { ...convert_input(key).M, ...convert_input(attributes).M }
|
|
277
|
-
})
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
async delete(table, key) {
|
|
281
|
-
return await this.dynamodb.deleteItem({
|
|
282
|
-
TableName: table,
|
|
283
|
-
Key: Object.fromEntries(Object.keys(key).map(key_name => [key_name, convert_input(key[key_name])]))
|
|
284
|
-
})
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
async duplicate_attribute(table, attribute_name, new_attribute_name) {
|
|
288
|
-
const table_key_names = await this.dynamodb.describeTable({
|
|
289
|
-
TableName : table
|
|
290
|
-
}).then(metadata => metadata.Table.KeySchema.map(key => key.AttributeName))
|
|
291
|
-
const items = await this.scan(table, table_key_names.concat([attribute_name, new_attribute_name]))
|
|
292
|
-
if (items.filter(item => item[new_attribute_name] !== undefined).length > 0) {
|
|
293
|
-
console.log("Cannot rename.", new_attribute_name, "is an existing item.")
|
|
294
|
-
return
|
|
295
|
-
}
|
|
296
|
-
for (const item of items) {
|
|
297
|
-
if (item[attribute_name] === undefined) {
|
|
298
|
-
continue
|
|
299
|
-
}
|
|
300
|
-
const key = Object.fromEntries(table_key_names.map(key_name => [key_name, item[key_name]]))
|
|
301
|
-
await this.set(table, key, { [new_attribute_name] : item[attribute_name] })
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
async remove_attribute(table, attribute_name) {
|
|
306
|
-
const table_key_names = await this.dynamodb.describeTable({
|
|
307
|
-
TableName : table
|
|
308
|
-
}).then(metadata => metadata.Table.KeySchema.map(key => key.AttributeName))
|
|
309
|
-
const items = await this.scan(table)
|
|
310
|
-
.then(items => items.filter(item => item[attribute_name] !== undefined))
|
|
311
|
-
for (const item of items) {
|
|
312
|
-
const key = Object.fromEntries(table_key_names.map(key_name => [key_name, item[key_name]]))
|
|
313
|
-
await this.remove(table, key, [attribute_name])
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
}
|
package/utils/Utils_Misc.js
DELETED
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
import nodemailer from "nodemailer"
|
|
2
|
-
import election_ids from "./election_ids.js"
|
|
3
|
-
import crypto from "crypto"
|
|
4
|
-
|
|
5
|
-
export default class Utils_Misc {
|
|
6
|
-
|
|
7
|
-
constructor(config) {
|
|
8
|
-
this.config = config
|
|
9
|
-
this.text_encoder = new TextEncoder()
|
|
10
|
-
if (config.google_email !== undefined && config.google_app_password !== undefined) {
|
|
11
|
-
this.transporter = nodemailer.createTransport({
|
|
12
|
-
service: "Gmail",
|
|
13
|
-
host: "smtp.gmail.com",
|
|
14
|
-
port: 465,
|
|
15
|
-
secure: true,
|
|
16
|
-
auth: {
|
|
17
|
-
user: config.google_email,
|
|
18
|
-
pass: config.google_app_password,
|
|
19
|
-
}
|
|
20
|
-
})
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async wait(duration) {
|
|
25
|
-
return new Promise(resolve => setTimeout(resolve, duration))
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
get_current_time(milliseconds = false) {
|
|
29
|
-
if (milliseconds) {
|
|
30
|
-
return (new Date()).getTime()
|
|
31
|
-
}
|
|
32
|
-
return (new Date()).toISOString()
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async send_email(recipient, subject, text) {
|
|
36
|
-
for (let i = 0; i < 3; i++) {
|
|
37
|
-
try {
|
|
38
|
-
await this.transporter.sendMail({
|
|
39
|
-
from: this.config.alerts_email,
|
|
40
|
-
to: recipient,
|
|
41
|
-
subject: subject,
|
|
42
|
-
text: text
|
|
43
|
-
})
|
|
44
|
-
return
|
|
45
|
-
} catch (error) {
|
|
46
|
-
console.log("EMAIL ERROR", error)
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
async admin_alert(text) {
|
|
52
|
-
console.log("ADMIN ALERT:", text)
|
|
53
|
-
await this.send_email(this.config.google_email, "ADMIN ALERT", text)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async safe_run(f) {
|
|
57
|
-
try {
|
|
58
|
-
await f()
|
|
59
|
-
} catch (error) {
|
|
60
|
-
if (error.stack !== undefined) {
|
|
61
|
-
await this.admin_alert(error.stack.toString())
|
|
62
|
-
} else {
|
|
63
|
-
await this.admin_alert(error.toString())
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async iterate(inputs, f, concurrency = 1, print_indices = false) {
|
|
69
|
-
let index = 0
|
|
70
|
-
let iterators = []
|
|
71
|
-
for (let i = 0; i < concurrency; i++) {
|
|
72
|
-
iterators.push((async () => {
|
|
73
|
-
while (index < inputs.length) {
|
|
74
|
-
index += 1
|
|
75
|
-
if (print_indices) {
|
|
76
|
-
console.log(i + ":" + (index - 1) + "/" + inputs.length)
|
|
77
|
-
}
|
|
78
|
-
await this.safe_run(() => f(inputs[index - 1]))
|
|
79
|
-
}
|
|
80
|
-
})())
|
|
81
|
-
}
|
|
82
|
-
await Promise.all(iterators)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
async sha256(input) {
|
|
86
|
-
const input_buffer = this.text_encoder.encode(input);
|
|
87
|
-
|
|
88
|
-
const hash_buffer = await crypto.subtle.digest("SHA-256", input_buffer)
|
|
89
|
-
|
|
90
|
-
const hash_array = Array.from(new Uint8Array(hash_buffer))
|
|
91
|
-
|
|
92
|
-
const hash = hash_array.map(b => b.toString(16).padStart(2, "0")).join("")
|
|
93
|
-
return hash
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
encrypt(text) {
|
|
97
|
-
const iv = crypto.randomBytes(16)
|
|
98
|
-
const cipher = crypto.createCipheriv("aes-256-cbc", Buffer.from(this.config.secret_key, "hex"), iv)
|
|
99
|
-
let ciphertext = cipher.update(text, "utf8", "hex")
|
|
100
|
-
ciphertext += cipher.final("hex")
|
|
101
|
-
return {
|
|
102
|
-
iv: iv.toString("hex"),
|
|
103
|
-
ciphertext: ciphertext
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
decrypt(encryption) {
|
|
108
|
-
const iv = encryption.iv
|
|
109
|
-
const ciphertext = encryption.ciphertext
|
|
110
|
-
const decipher = crypto.createDecipheriv("aes-256-cbc", Buffer.from(this.config.secret_key, "hex"), Buffer.from(iv, "hex"))
|
|
111
|
-
let text = decipher.update(ciphertext, "hex", "utf8")
|
|
112
|
-
text += decipher.final("utf8")
|
|
113
|
-
return text
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
get_secret_hash(username) {
|
|
117
|
-
const secret_hash = crypto.createHmac("sha256", this.config.cognito_client_secret)
|
|
118
|
-
.update(username + this.config.cognito_client_id)
|
|
119
|
-
.digest("base64")
|
|
120
|
-
return secret_hash
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
get_election_id(year, office, state, district) {
|
|
124
|
-
if (year === undefined || office === undefined || state === undefined || office === "P") {
|
|
125
|
-
return undefined
|
|
126
|
-
}
|
|
127
|
-
if (office === "H" && (district === undefined || district.length !== 2)) {
|
|
128
|
-
return undefined
|
|
129
|
-
}
|
|
130
|
-
if (year.length !== 4 || office.length !== 1 || state.length !== 2) {
|
|
131
|
-
return undefined
|
|
132
|
-
}
|
|
133
|
-
const office_name = { "H" : "house", "S" : "sen", "P" : "pres" }[office]
|
|
134
|
-
const election_id = year + "-" + office_name + "-" + state.toLowerCase() + (office === "H" ? ("-" + district.toLowerCase()) : "") + "-election"
|
|
135
|
-
if (!election_ids.has(election_id)) {
|
|
136
|
-
return undefined
|
|
137
|
-
}
|
|
138
|
-
return election_id
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
get_chunk_indices(text_length, max_length = 2500, overlap = 50) {
|
|
142
|
-
const num_chunks = Math.ceil((text_length + overlap) / max_length)
|
|
143
|
-
const chunk_length = Math.ceil((text_length - overlap) / num_chunks + overlap)
|
|
144
|
-
const chunk_indices = []
|
|
145
|
-
for (let i = 0; i < num_chunks; i++) {
|
|
146
|
-
chunk_indices.push([
|
|
147
|
-
(chunk_length - overlap) * i,
|
|
148
|
-
(chunk_length - overlap) * i + chunk_length
|
|
149
|
-
])
|
|
150
|
-
}
|
|
151
|
-
return chunk_indices
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
chunkify(text, max_length = 2500, overlap = 50) {
|
|
155
|
-
const chunk_indices = this.get_chunk_indices(text.length, max_length, overlap)
|
|
156
|
-
return chunk_indices.map(chunk_index => ({
|
|
157
|
-
chunk_index : chunk_index,
|
|
158
|
-
chunk_text : text.substring(...chunk_index)
|
|
159
|
-
}))
|
|
160
|
-
}
|
|
161
|
-
}
|