stated-protocol-parser 1.0.5 → 1.0.7

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,639 @@
1
+ /* eslint-disable no-useless-concat */
2
+ import { legalForms, UTCFormat, peopleCountBuckets } from './constants';
3
+ import { parsePollV3 } from './v3';
4
+ import { monthIndex, birthDateFormat } from './utils';
5
+ const fallBackVersion = 3;
6
+ const version = 4;
7
+ export * from './types';
8
+ export * from './constants';
9
+ export * from './utils';
10
+ export * from './v3';
11
+ export const buildStatement = ({ domain, author, time, tags, content, representative, supersededStatement }) => {
12
+ if (content.match(/\nPublishing domain: /))
13
+ throw (new Error("Statement must not contain 'Publishing domain: ', as this marks the beginning of a new statement."));
14
+ if (content.match(/\n\n/))
15
+ throw (new Error("Statement must not contain two line breaks in a row, as this is used for separating statements."));
16
+ if (typeof time !== 'object' || !time.toUTCString)
17
+ throw (new Error("Time must be a Date object."));
18
+ if (!domain)
19
+ throw (new Error("Publishing domain missing."));
20
+ const statement = "Publishing domain: " + domain + "\n" +
21
+ "Author: " + (author || "") + "\n" +
22
+ (representative && representative?.length > 0 ? "Authorized signing representative: " + (representative || "") + "\n" : '') +
23
+ "Time: " + time.toUTCString() + "\n" +
24
+ (tags && tags.length > 0 ? "Tags: " + tags.join(', ') + "\n" : '') +
25
+ (supersededStatement && supersededStatement?.length > 0 ? "Superseded statement: " + (supersededStatement || "") + "\n" : '') +
26
+ "Format version: " + version + "\n" +
27
+ "Statement content: " + content + (content.match(/\n$/) ? '' : "\n");
28
+ if (statement.length > 3000)
29
+ throw (new Error("Statement must not be longer than 3,000 characters."));
30
+ return statement;
31
+ };
32
+ export const parseStatement = ({ statement: s, allowNoVersion = false }) => {
33
+ if (s.length > 3000)
34
+ throw (new Error("Statement must not be longer than 3,000 characters."));
35
+ if (s.match(/\n\n/))
36
+ throw new Error("Statements cannot contain two line breaks in a row, as this is used for separating statements.");
37
+ const statementRegex = new RegExp(''
38
+ + /^Publishing domain: (?<domain>[^\n]+?)\n/.source
39
+ + /Author: (?<author>[^\n]+?)\n/.source
40
+ + /(?:Authorized signing representative: (?<representative>[^\n]*?)\n)?/.source
41
+ + /Time: (?<time>[^\n]+?)\n/.source
42
+ + /(?:Tags: (?<tags>[^\n]*?)\n)?/.source
43
+ + /(?:Superseded statement: (?<supersededStatement>[^\n]*?)\n)?/.source
44
+ + /(?:Format version: (?<formatVersion>[^\n]*?)\n)?/.source
45
+ + /Statement content: (?:(?<typedContent>\n\tType: (?<type>[^\n]+?)\n[\s\S]+?\n$)|(?<content>[\s\S]+?\n$))/.source);
46
+ const match = s.match(statementRegex);
47
+ if (!match)
48
+ throw new Error("Invalid statement format:" + s);
49
+ const m = {
50
+ domain: match[1], author: match[2], representative: match[3], timeStr: match[4], tagsStr: match[5],
51
+ supersededStatement: match[6], formatVersion: match[7], content: match[8] || match[10],
52
+ type: match[9] ? match[9].toLowerCase().replace(' ', '_') : undefined
53
+ };
54
+ if (!(m['timeStr'].match(UTCFormat)))
55
+ throw new Error("Invalid statement format: time must be in UTC");
56
+ if (!m['domain'])
57
+ throw new Error("Invalid statement format: domain is required");
58
+ if (!m['author'])
59
+ throw new Error("Invalid statement format: author is required");
60
+ if (!m['content'])
61
+ throw new Error("Invalid statement format: statement content is required");
62
+ if (!allowNoVersion && !m['formatVersion'])
63
+ throw new Error("Invalid statement format: format version is required");
64
+ const tags = m['tagsStr']?.split(', ');
65
+ const time = new Date(m['timeStr']);
66
+ return {
67
+ domain: m['domain'],
68
+ author: m['author'],
69
+ representative: m['representative'],
70
+ time,
71
+ tags: (tags && tags.length > 0) ? tags : undefined,
72
+ supersededStatement: m['supersededStatement'],
73
+ formatVersion: m['formatVersion'] || ('' + fallBackVersion),
74
+ content: m['content'],
75
+ type: m['type']?.toLowerCase().replace(' ', '_'),
76
+ };
77
+ };
78
+ export const buildQuotationContent = ({ originalAuthor, authorVerification, originalTime, source, quotation, paraphrasedStatement, picture, confidence }) => {
79
+ if (quotation && quotation.match(/\n/))
80
+ throw (new Error("Quotation must not contain line breaks."));
81
+ if (!paraphrasedStatement && !quotation)
82
+ throw (new Error("Quotation must contain either a quotation or a paraphrased statement."));
83
+ const content = "\n" +
84
+ "\t" + "Type: Quotation" + "\n" +
85
+ "\t" + "Original author: " + originalAuthor + "\n" +
86
+ "\t" + "Author verification: " + authorVerification + "\n" +
87
+ (originalTime && originalTime?.length > 0 ? "\t" + "Original publication time: " + originalTime + "\n" : "") +
88
+ (source && source?.length > 0 ? "\t" + "Source: " + (source || "") + "\n" : '') +
89
+ (picture && picture.length > 0 ? "\t" + "Picture proof: " + (picture || "") + "\n" : '') +
90
+ (confidence && confidence?.length > 0 ? "\t" + "Confidence: " + (confidence || "") + "\n" : '') +
91
+ (quotation && quotation?.length > 0 ? "\t" + "Quotation: " + (quotation || "") + "\n" : '') +
92
+ (paraphrasedStatement && paraphrasedStatement?.length > 0 ? "\t" + "Paraphrased statement: " +
93
+ (paraphrasedStatement || "").replace(/\n\t([^\t])/, '\n\t\t($1)') + "\n" : '') +
94
+ "";
95
+ return content;
96
+ };
97
+ export const parseQuotation = (s) => {
98
+ const voteRegex = new RegExp(''
99
+ + /^\n\tType: Quotation\n/.source
100
+ + /\tOriginal author: (?<originalAuthor>[^\n]+?)\n/.source
101
+ + /\tAuthor verification: (?<authorVerification>[^\n]+?)\n/.source
102
+ + /(?:\tOriginal publication time: (?<originalTime>[^\n]+?)\n)?/.source
103
+ + /(?:\tSource: (?<source>[^\n]+?)\n)?/.source
104
+ + /(?:\tPicture proof: (?<picture>[^\n]+?)\n)?/.source
105
+ + /(?:\tConfidence: (?<confidence>[^\n]+?)\n)?/.source
106
+ + /(?:\tQuotation: (?<quotation>[^\n]+?)\n)?/.source
107
+ + /(?:\tParaphrased statement: (?:(?<paraphrasedTypedStatement>\n\t\tType: (?<type>[^\n]+?)\n[\s\S]+?)|(?<paraphrasedStatement>[\s\S]+?)))/.source
108
+ + /$/.source);
109
+ let match = s.match(voteRegex);
110
+ if (!match)
111
+ throw new Error("Invalid quotation format: " + s);
112
+ let m = {};
113
+ m = {
114
+ originalAuthor: match[1], authorVerification: match[2], originalTime: match[3], source: match[4],
115
+ picture: match[5], confidence: match[6], quotation: match[7], paraphrasedStatement: match[8] || match[10],
116
+ type: match[9] ? match[9].toLowerCase().replace(' ', '_') : undefined
117
+ };
118
+ return {
119
+ originalAuthor: m['originalAuthor'],
120
+ authorVerification: m['authorVerification'],
121
+ originalTime: m['originalTime'],
122
+ source: m['source'],
123
+ picture: m['picture'],
124
+ confidence: m['confidence'],
125
+ quotation: m['quotation'],
126
+ paraphrasedStatement: (m['paraphrasedStatement']?.replace(/\n\t\t/g, "\n\t")),
127
+ type: m['type']?.toLowerCase().replace(' ', '_'),
128
+ };
129
+ };
130
+ export const buildPollContent = ({ country, city, legalEntity, domainScope, judges, deadline, poll, scopeDescription, scopeQueryLink, options, allowArbitraryVote, requiredProperty: propertyScope, requiredPropertyObserver: propertyScopeObserver }) => {
131
+ if (!poll)
132
+ throw (new Error("Poll must contain a poll question."));
133
+ const scopeContent = (scopeDescription ? "\t\t" + "Description: " + scopeDescription + "\n" : "") +
134
+ (country ? "\t\t" + "Country scope: " + country + "\n" : "") +
135
+ (city ? "\t\t" + "City scope: " + city + "\n" : "") +
136
+ (legalEntity ? "\t\t" + "Legal form scope: " + legalEntity + "\n" : "") +
137
+ (domainScope && domainScope?.length > 0 ? "\t\t" + "Domain scope: " + domainScope.join(', ') + "\n" : "") +
138
+ (propertyScope ? "\t\t" + "All entities with the following property: " + propertyScope + "\n" : "") +
139
+ (propertyScopeObserver ? "\t\t" + "As observed by: " + propertyScopeObserver + "\n" : "") +
140
+ (scopeQueryLink ? "\t\t" + "Link to query defining who can vote: " + scopeQueryLink + "\n" : "");
141
+ if (scopeContent.length > 0 && !scopeDescription)
142
+ throw (new Error("Poll must contain a description of who can vote."));
143
+ const content = "\n" +
144
+ "\t" + "Type: Poll" + "\n" +
145
+ (judges ? "\t" + "The poll outcome is finalized when the following nodes agree: " + judges + "\n" : "") +
146
+ (deadline ? "\t" + "Voting deadline: " + deadline.toUTCString() + "\n" : "") +
147
+ "\t" + "Poll: " + poll + "\n" +
148
+ (options.length > 0 && options[0] ? "\t" + "Option 1: " + options[0] + "\n" : "") +
149
+ (options.length > 1 && options[1] ? "\t" + "Option 2: " + options[1] + "\n" : "") +
150
+ (options.length > 2 && options[2] ? "\t" + "Option 3: " + options[2] + "\n" : "") +
151
+ (options.length > 3 && options[3] ? "\t" + "Option 4: " + options[3] + "\n" : "") +
152
+ (options.length > 4 && options[4] ? "\t" + "Option 5: " + options[4] + "\n" : "") +
153
+ ((allowArbitraryVote === true || allowArbitraryVote === false) ? ("\t" + "Allow free text votes: " + (allowArbitraryVote ? 'Yes' : 'No') + "\n") : "") +
154
+ (scopeContent ? "\t" + "Who can vote: \n" + scopeContent : "") +
155
+ "";
156
+ return content;
157
+ };
158
+ export const parsePoll = (s, version) => {
159
+ if (version && version === '3')
160
+ return parsePollV3(s);
161
+ if (version && version !== '4')
162
+ throw new Error("Invalid version " + version);
163
+ const pollRegex = new RegExp(''
164
+ + /^\n\tType: Poll\n/.source
165
+ + /(?:\tThe poll outcome is finalized when the following nodes agree: (?<judges>[^\n]+?)\n)?/.source
166
+ + /(?:\tVoting deadline: (?<deadline>[^\n]+?)\n)?/.source
167
+ + /\tPoll: (?<poll>[^\n]+?)\n/.source
168
+ + /(?:\tOption 1: (?<option1>[^\n]+?)\n)?/.source
169
+ + /(?:\tOption 2: (?<option2>[^\n]+?)\n)?/.source
170
+ + /(?:\tOption 3: (?<option3>[^\n]+?)\n)?/.source
171
+ + /(?:\tOption 4: (?<option4>[^\n]+?)\n)?/.source
172
+ + /(?:\tOption 5: (?<option5>[^\n]+?)\n)?/.source
173
+ + /(?:\tAllow free text votes: (?<allowArbitraryVote>Yes|No)\n)?/.source
174
+ + /(?:\tWho can vote: (?<whoCanVote>\n[\s\S]+?\n))?/.source
175
+ + /$/.source);
176
+ let m = s.match(pollRegex);
177
+ if (!m)
178
+ throw new Error("Invalid poll format: " + s);
179
+ m = {
180
+ judges: m[1], deadline: m[2], poll: m[3],
181
+ option1: m[4], option2: m[5], option3: m[6], option4: m[7], option5: m[8],
182
+ allowArbitraryVote: m[9],
183
+ whoCanVote: m[10]
184
+ };
185
+ const whoCanVoteParsed = {};
186
+ if (m.whoCanVote) {
187
+ const whoCanVoteRegex = new RegExp(''
188
+ + /^\n\t\tDescription: (?<scopeDescription>[^\n]+?)\n/.source
189
+ + /(?:\t\tCountry scope: (?<countryScope>[^\n]+?)\n)?/.source
190
+ + /(?:\t\tCity scope: (?<cityScope>[^\n]+?)\n)?/.source
191
+ + /(?:\t\tLegal form scope: (?<legalEntity>[^\n]+?)\n)?/.source
192
+ + /(?:\t\tDomain scope: (?<domainScope>[^\n]+?)\n)?/.source
193
+ + /(?:\t\tAll entities with the following property: (?<propertyScope>[^\n]+?)\n)?/.source
194
+ + /(?:\t\tAs observed by: (?<propertyScopeObserver>[^\n]+?)\n)?/.source
195
+ + /(?:\t\tLink to query defining who can vote: (?<scopeQueryLink>[^\n]+?)\n)?/.source
196
+ + /$/.source);
197
+ let m2 = m.whoCanVote.match(whoCanVoteRegex);
198
+ if (!m2)
199
+ throw new Error("Invalid who can vote section: " + m.whoCanVote);
200
+ whoCanVoteParsed['scopeDescription'] = m2[1];
201
+ whoCanVoteParsed['country'] = m2[2];
202
+ whoCanVoteParsed['city'] = m2[3];
203
+ whoCanVoteParsed['legalEntity'] = m2[4];
204
+ whoCanVoteParsed['domainScopeStr'] = m2[5];
205
+ whoCanVoteParsed['requiredProperty'] = m2[6];
206
+ whoCanVoteParsed['requiredPropertyObserver'] = m2[7];
207
+ whoCanVoteParsed['scopeQueryLink'] = m2[8];
208
+ }
209
+ const options = [m.option1, m.option2, m.option3, m.option4, m.option5].filter(o => o);
210
+ const domainScope = whoCanVoteParsed.domainScopeStr?.split(', ');
211
+ const allowArbitraryVote = (m['allowArbitraryVote'] === 'Yes' ? true :
212
+ (m['allowArbitraryVote'] === 'No' ? false : undefined));
213
+ const deadlineStr = m.deadline;
214
+ if (deadlineStr && !deadlineStr.match(UTCFormat))
215
+ throw new Error("Invalid poll, deadline must be in UTC: " + deadlineStr);
216
+ return {
217
+ judges: m['judges'],
218
+ deadline: deadlineStr ? new Date(deadlineStr) : undefined,
219
+ poll: m['poll'],
220
+ options,
221
+ allowArbitraryVote,
222
+ country: whoCanVoteParsed['country'],
223
+ scopeDescription: whoCanVoteParsed['scopeDescription'],
224
+ requiredProperty: whoCanVoteParsed['requiredProperty'],
225
+ requiredPropertyObserver: whoCanVoteParsed['requiredPropertyObserver'],
226
+ scopeQueryLink: whoCanVoteParsed['scopeQueryLink'],
227
+ city: whoCanVoteParsed['city'],
228
+ legalEntity: whoCanVoteParsed['legalEntity'],
229
+ domainScope: (domainScope && domainScope.length > 0) ? domainScope : undefined,
230
+ };
231
+ };
232
+ export const buildOrganisationVerificationContent = ({ name, englishName, country, city, province, legalForm, department, domain, foreignDomain, serialNumber, confidence, reliabilityPolicy, employeeCount, pictureHash, latitude, longitude, population }) => {
233
+ if (!name || !country || !legalForm || (!domain && !foreignDomain))
234
+ throw new Error("Missing required fields");
235
+ if (!Object.values(legalForms).includes(legalForm))
236
+ throw new Error("Invalid legal form " + legalForm);
237
+ if (employeeCount && !Object.values(peopleCountBuckets).includes(employeeCount))
238
+ throw new Error("Invalid employee count " + employeeCount);
239
+ if (population && !Object.values(peopleCountBuckets).includes(population))
240
+ throw new Error("Invalid population " + population);
241
+ if (confidence && !('' + confidence)?.match(/^[0-9.]+$/))
242
+ throw new Error("Invalid confidence " + confidence);
243
+ return "\n" +
244
+ "\t" + "Type: Organisation verification" + "\n" +
245
+ "\t" + "Description: We verified the following information about an organisation." + "\n" +
246
+ "\t" + "Name: " + name + "\n" +
247
+ (englishName ? "\t" + "English name: " + englishName + "\n" : "") +
248
+ "\t" + "Country: " + country + "\n" +
249
+ "\t" + "Legal form: " + legalForm + "\n" +
250
+ (domain ? "\t" + "Owner of the domain: " + domain + "\n" : "") +
251
+ (foreignDomain ? "\t" + "Foreign domain used for publishing statements: " + foreignDomain + "\n" : "") +
252
+ (department ? "\t" + "Department using the domain: " + department + "\n" : "") +
253
+ (province ? "\t" + "Province or state: " + province + "\n" : "") +
254
+ (serialNumber ? "\t" + "Business register number: " + serialNumber + "\n" : "") +
255
+ (city ? "\t" + "City: " + city + "\n" : "") +
256
+ (latitude ? "\t" + "Latitude: " + latitude + "\n" : "") +
257
+ (longitude ? "\t" + "Longitude: " + longitude + "\n" : "") +
258
+ (population ? "\t" + "Population: " + population + "\n" : "") +
259
+ (pictureHash ? "\t" + "Logo: " + pictureHash + "\n" : "") +
260
+ (employeeCount ? "\t" + "Employee count: " + employeeCount + "\n" : "") +
261
+ (reliabilityPolicy ? "\t" + "Reliability policy: " + reliabilityPolicy + "\n" : "") +
262
+ (confidence ? "\t" + "Confidence: " + confidence + "\n" : "") +
263
+ "";
264
+ };
265
+ export const parseOrganisationVerification = (s) => {
266
+ const organisationVerificationRegex = new RegExp(''
267
+ + /^\n\tType: Organisation verification\n/.source
268
+ + /\tDescription: We verified the following information about an organisation.\n/.source
269
+ + /\tName: (?<name>[^\n]+?)\n/.source
270
+ + /(?:\tEnglish name: (?<englishName>[^\n]+?)\n)?/.source
271
+ + /\tCountry: (?<country>[^\n]+?)\n/.source
272
+ + /\tLegal (?:form|entity): (?<legalForm>[^\n]+?)\n/.source
273
+ + /(?:\tOwner of the domain: (?<domain>[^\n]+?)\n)?/.source
274
+ + /(?:\tForeign domain used for publishing statements: (?<foreignDomain>[^\n]+?)\n)?/.source
275
+ + /(?:\tDepartment using the domain: (?<department>[^\n]+?)\n)?/.source
276
+ + /(?:\tProvince or state: (?<province>[^\n]+?)\n)?/.source
277
+ + /(?:\tBusiness register number: (?<serialNumber>[^\n]+?)\n)?/.source
278
+ + /(?:\tCity: (?<city>[^\n]+?)\n)?/.source
279
+ + /(?:\tLatitude: (?<latitude>[^\n]+?)\n)?/.source
280
+ + /(?:\tLongitude: (?<longitude>[^\n]+?)\n)?/.source
281
+ + /(?:\tPopulation: (?<population>[^\n]+?)\n)?/.source
282
+ + /(?:\tLogo: (?<pictureHash>[^\n]+?)\n)?/.source
283
+ + /(?:\tEmployee count: (?<employeeCount>[01,+-]+?)\n)?/.source
284
+ + /(?:\tReliability policy: (?<reliabilityPolicy>[^\n]+?)\n)?/.source
285
+ + /(?:\tConfidence: (?<confidence>[0-9.]+?)\n)?/.source
286
+ + /$/.source);
287
+ const m = s.match(organisationVerificationRegex);
288
+ if (!m)
289
+ throw new Error("Invalid organisation verification format: " + s);
290
+ return {
291
+ name: m[1],
292
+ englishName: m[2],
293
+ country: m[3],
294
+ legalForm: m[4],
295
+ domain: m[5],
296
+ foreignDomain: m[6],
297
+ department: m[7],
298
+ province: m[8],
299
+ serialNumber: m[9],
300
+ city: m[10],
301
+ latitude: m[11] ? parseFloat(m[11]) : undefined,
302
+ longitude: m[12] ? parseFloat(m[12]) : undefined,
303
+ population: m[13],
304
+ pictureHash: m[14],
305
+ employeeCount: m[15],
306
+ reliabilityPolicy: m[16],
307
+ confidence: m[17] ? parseFloat(m[17]) : undefined,
308
+ };
309
+ };
310
+ export const buildPersonVerificationContent = ({ name, countryOfBirth, cityOfBirth, ownDomain, foreignDomain, dateOfBirth, jobTitle, employer, verificationMethod, confidence, picture, reliabilityPolicy }) => {
311
+ if (!name || !countryOfBirth || !cityOfBirth || !dateOfBirth || (!ownDomain && !foreignDomain)) {
312
+ console.log("Missing required fields: ", { name, countryOfBirth, cityOfBirth, dateOfBirth, ownDomain, foreignDomain });
313
+ return "";
314
+ }
315
+ const [day, month, year] = dateOfBirth.toUTCString().split(' ').filter((i, j) => [1, 2, 3].includes(j));
316
+ let content = "\n" +
317
+ "\t" + "Type: Person verification" + "\n" +
318
+ "\t" + "Description: We verified the following information about a person." + "\n" +
319
+ "\t" + "Name: " + name + "\n" +
320
+ "\t" + "Date of birth: " + [day.replace(/$0/, ''), month, year].join(' ') + "\n" +
321
+ "\t" + "City of birth: " + cityOfBirth + "\n" +
322
+ "\t" + "Country of birth: " + countryOfBirth + "\n" +
323
+ (jobTitle ? "\t" + "Job title: " + jobTitle + "\n" : "") +
324
+ (employer ? "\t" + "Employer: " + employer + "\n" : "") +
325
+ (ownDomain ? "\t" + "Owner of the domain: " + ownDomain + "\n" : "") +
326
+ (foreignDomain ? "\t" + "Foreign domain used for publishing statements: " + foreignDomain + "\n" : "") +
327
+ (picture ? "\t" + "Picture: " + picture + "\n" : "") +
328
+ (verificationMethod ? "\t" + "Verification method: " + verificationMethod + "\n" : "") +
329
+ (confidence ? "\t" + "Confidence: " + confidence + "\n" : "") +
330
+ (reliabilityPolicy ? "\t" + "Reliability policy: " + reliabilityPolicy + "\n" : "") +
331
+ "";
332
+ return content;
333
+ };
334
+ export const parsePersonVerification = (s) => {
335
+ const domainVerificationRegex = new RegExp(''
336
+ + /^\n\tType: Person verification\n/.source
337
+ + /\tDescription: We verified the following information about a person.\n/.source
338
+ + /\tName: (?<name>[^\n]+?)\n/.source
339
+ + /\tDate of birth: (?<dateOfBirth>[^\n]+?)\n/.source
340
+ + /\tCity of birth: (?<cityOfBirth>[^\n]+?)\n/.source
341
+ + /\tCountry of birth: (?<countryOfBirth>[^\n]+?)\n/.source
342
+ + /(?:\tJob title: (?<jobTitle>[^\n]+?)\n)?/.source
343
+ + /(?:\tEmployer: (?<employer>[^\n]+?)\n)?/.source
344
+ + /(?:\tOwner of the domain: (?<domain>[^\n]+?)\n)?/.source
345
+ + /(?:\tForeign domain used for publishing statements: (?<foreignDomain>[^\n]+?)\n)?/.source
346
+ + /(?:\tPicture: (?<picture>[^\n]+?)\n)?/.source
347
+ + /(?:\tVerification method: (?<verificationMethod>[^\n]+?)\n)?/.source
348
+ + /(?:\tConfidence: (?<confidence>[^\n]+?)\n)?/.source
349
+ + /(?:\tReliability policy: (?<reliabilityPolicy>[^\n]+?)\n)?/.source
350
+ + /$/.source);
351
+ const m = s.match(domainVerificationRegex);
352
+ if (!m)
353
+ throw new Error("Invalid person verification format: " + s);
354
+ if (m[2] && !m[2].match(birthDateFormat))
355
+ throw new Error("Invalid birth date format: " + m[2]);
356
+ let { d, month, y } = m[2].match(birthDateFormat)?.groups || {};
357
+ if (!d || !month || !y)
358
+ throw new Error("Invalid birth date format: " + m[2]);
359
+ return {
360
+ name: m[1],
361
+ dateOfBirth: new Date(Date.UTC(parseInt(y), monthIndex(month), parseInt(d))),
362
+ cityOfBirth: m[3],
363
+ countryOfBirth: m[4],
364
+ jobTitle: m[5],
365
+ employer: m[6],
366
+ ownDomain: m[7],
367
+ foreignDomain: m[8],
368
+ picture: m[9],
369
+ verificationMethod: m[10],
370
+ confidence: m[11] ? parseFloat(m[11]) : undefined,
371
+ reliabilityPolicy: m[12]
372
+ };
373
+ };
374
+ export const buildVoteContent = ({ pollHash, poll, vote }) => {
375
+ const content = "\n" +
376
+ "\t" + "Type: Vote" + "\n" +
377
+ "\t" + "Poll id: " + pollHash + "\n" +
378
+ "\t" + "Poll: " + poll + "\n" +
379
+ "\t" + "Option: " + vote + "\n" +
380
+ "";
381
+ return content;
382
+ };
383
+ export const parseVote = (s) => {
384
+ const voteRegex = new RegExp(''
385
+ + /^\n\tType: Vote\n/.source
386
+ + /\tPoll id: (?<pollHash>[^\n]+?)\n/.source
387
+ + /\tPoll: (?<poll>[^\n]+?)\n/.source
388
+ + /\tOption: (?<vote>[^\n]+?)\n/.source
389
+ + /$/.source);
390
+ const m = s.match(voteRegex);
391
+ if (!m)
392
+ throw new Error("Invalid vote format: " + s);
393
+ return {
394
+ pollHash: m[1],
395
+ poll: m[2],
396
+ vote: m[3]
397
+ };
398
+ };
399
+ export const buildDisputeAuthenticityContent = ({ hash, confidence, reliabilityPolicy }) => {
400
+ const content = "\n" +
401
+ "\t" + "Type: Dispute statement authenticity" + "\n" +
402
+ "\t" + "Description: We think that the referenced statement is not authentic.\n" +
403
+ "\t" + "Hash of referenced statement: " + hash + "\n" +
404
+ (confidence ? "\t" + "Confidence: " + confidence + "\n" : "") +
405
+ (reliabilityPolicy ? "\t" + "Reliability policy: " + reliabilityPolicy + "\n" : "") +
406
+ "";
407
+ return content;
408
+ };
409
+ export const parseDisputeAuthenticity = (s) => {
410
+ const disputeRegex = new RegExp(''
411
+ + /^\n\tType: Dispute statement authenticity\n/.source
412
+ + /\tDescription: We think that the referenced statement is not authentic.\n/.source
413
+ + /\tHash of referenced statement: (?<hash>[^\n]+?)\n/.source
414
+ + /(?:\tConfidence: (?<confidence>[^\n]*?)\n)?/.source
415
+ + /(?:\tReliability policy: (?<reliabilityPolicy>[^\n]+?)\n)?/.source
416
+ + /$/.source);
417
+ const m = s.match(disputeRegex);
418
+ if (!m)
419
+ throw new Error("Invalid dispute authenticity format: " + s);
420
+ return {
421
+ hash: m[1],
422
+ confidence: m[2] ? parseFloat(m[2]) : undefined,
423
+ reliabilityPolicy: m[3]
424
+ };
425
+ };
426
+ export const buildDisputeContentContent = ({ hash, confidence, reliabilityPolicy }) => {
427
+ const content = "\n" +
428
+ "\t" + "Type: Dispute statement content" + "\n" +
429
+ "\t" + "Description: We think that the content of the referenced statement is false.\n" +
430
+ "\t" + "Hash of referenced statement: " + hash + "\n" +
431
+ (confidence ? "\t" + "Confidence: " + confidence + "\n" : "") +
432
+ (reliabilityPolicy ? "\t" + "Reliability policy: " + reliabilityPolicy + "\n" : "") +
433
+ "";
434
+ return content;
435
+ };
436
+ export const parseDisputeContent = (s) => {
437
+ const disputeRegex = new RegExp(''
438
+ + /^\n\tType: Dispute statement content\n/.source
439
+ + /\tDescription: We think that the content of the referenced statement is false.\n/.source
440
+ + /\tHash of referenced statement: (?<hash>[^\n]+?)\n/.source
441
+ + /(?:\tConfidence: (?<confidence>[^\n]*?)\n)?/.source
442
+ + /(?:\tReliability policy: (?<reliabilityPolicy>[^\n]+?)\n)?/.source
443
+ + /$/.source);
444
+ const m = s.match(disputeRegex);
445
+ if (!m)
446
+ throw new Error("Invalid dispute content format: " + s);
447
+ return {
448
+ hash: m[1],
449
+ confidence: m[2] ? parseFloat(m[2]) : undefined,
450
+ reliabilityPolicy: m[3]
451
+ };
452
+ };
453
+ export const buildResponseContent = ({ hash, response }) => {
454
+ const content = "\n" +
455
+ "\t" + "Type: Response" + "\n" +
456
+ "\t" + "Hash of referenced statement: " + hash + "\n" +
457
+ "\t" + "Response: " + response + "\n" +
458
+ "";
459
+ return content;
460
+ };
461
+ export const parseResponseContent = (s) => {
462
+ const disputeRegex = new RegExp(''
463
+ + /^\n\tType: Response\n/.source
464
+ + /\tHash of referenced statement: (?<hash>[^\n]+?)\n/.source
465
+ + /\tResponse: (?<response>[^\n]*?)\n/.source
466
+ + /$/.source);
467
+ const m = s.match(disputeRegex);
468
+ if (!m)
469
+ throw new Error("Invalid response content format: " + s);
470
+ return {
471
+ hash: m[1],
472
+ response: m[2]
473
+ };
474
+ };
475
+ export const buildPDFSigningContent = ({ hash }) => {
476
+ const content = "\n" +
477
+ "\t" + "Type: Sign PDF" + "\n" +
478
+ "\t" + "Description: We hereby digitally sign the referenced PDF file.\n" +
479
+ "\t" + "PDF file hash: " + hash + "\n" +
480
+ "";
481
+ return content;
482
+ };
483
+ export const parsePDFSigning = (s) => {
484
+ const signingRegex = new RegExp(''
485
+ + /^\n\tType: Sign PDF\n/.source
486
+ + /\tDescription: We hereby digitally sign the referenced PDF file.\n/.source
487
+ + /\tPDF file hash: (?<hash>[^\n]+?)\n/.source
488
+ + /$/.source);
489
+ const m = s.match(signingRegex);
490
+ if (!m)
491
+ throw new Error("Invalid PDF signing format: " + s);
492
+ return {
493
+ hash: m[1]
494
+ };
495
+ };
496
+ export const buildRating = ({ subjectName, subjectType, subjectReference, documentFileHash, rating, quality, comment }) => {
497
+ if (![1, 2, 3, 4, 5].includes(rating))
498
+ throw new Error("Invalid rating: " + rating);
499
+ const content = "\n" +
500
+ "\t" + "Type: Rating" + "\n" +
501
+ (subjectType ? "\t" + "Subject type: " + subjectType + "\n" : "") +
502
+ "\t" + "Subject name: " + subjectName + "\n" +
503
+ (subjectReference ? "\t" + "URL that identifies the subject: " + subjectReference + "\n" : "") +
504
+ (documentFileHash ? "\t" + "Document file hash: " + documentFileHash + "\n" : "") +
505
+ (quality ? "\t" + "Rated quality: " + quality + "\n" : "") +
506
+ "\t" + "Our rating: " + rating + "/5 Stars\n" +
507
+ (comment ? "\t" + "Comment: " + comment + "\n" : "") +
508
+ "";
509
+ return content;
510
+ };
511
+ export const parseRating = (s) => {
512
+ const ratingRegex = new RegExp(''
513
+ + /^\n\tType: Rating\n/.source
514
+ + /(?:\tSubject type: (?<subjectType>[^\n]*?)\n)?/.source
515
+ + /\tSubject name: (?<subjectName>[^\n]*?)\n/.source
516
+ + /(?:\tURL that identifies the subject: (?<subjectReference>[^\n]*?)\n)?/.source
517
+ + /(?:\tDocument file hash: (?<documentFileHash>[^\n]*?)\n)?/.source
518
+ + /(?:\tRated quality: (?<quality>[^\n]*?)\n)?/.source
519
+ + /\tOur rating: (?<rating>[1-5])\/5 Stars\n/.source
520
+ + /(?:\tComment: (?<comment>[\s\S]+?)\n)?/.source
521
+ + /$/.source);
522
+ const m = s.match(ratingRegex);
523
+ if (!m)
524
+ throw new Error("Invalid rating format: " + s);
525
+ const rating = parseInt(m[6]);
526
+ if (![1, 2, 3, 4, 5].includes(rating))
527
+ throw new Error("Invalid rating: " + m[6]);
528
+ if (m[1] && !['Organisation', 'Policy proposal', 'Regulation',
529
+ 'Treaty draft', 'Product', 'Research publication'].includes(m[1]))
530
+ throw new Error("Invalid subject type: " + m[1]);
531
+ if (!m[2])
532
+ throw new Error("Missing subject name");
533
+ return {
534
+ subjectType: m[1],
535
+ subjectName: m[2],
536
+ subjectReference: m[3],
537
+ documentFileHash: m[4],
538
+ quality: m[5],
539
+ rating,
540
+ comment: m[7]
541
+ };
542
+ };
543
+ export const buildBounty = ({ motivation, bounty, reward, judge, judgePay }) => {
544
+ const content = "\n" +
545
+ "\t" + "Type: Bounty" + "\n" +
546
+ (motivation ? "\t" + "In order to: " + motivation + "\n" : "") +
547
+ "\t" + "We will reward any entity that: " + bounty + "\n" +
548
+ "\t" + "The reward is: " + reward + "\n" +
549
+ "\t" + "In case of dispute, bounty claims are judged by: " + judge + "\n" +
550
+ (judgePay ? "\t" + "The judge will be paid per investigated case with a maxium of: " + judgePay + "\n" : "") +
551
+ "";
552
+ return content;
553
+ };
554
+ export const parseBounty = (s) => {
555
+ const bountyRegex = new RegExp(''
556
+ + /^\n\tType: Bounty\n/.source
557
+ + /(?:\tIn order to: (?<motivation>[^\n]*?)\n)?/.source
558
+ + /\tWe will reward any entity that: (?<bounty>[^\n]*?)\n/.source
559
+ + /\tThe reward is: (?<reward>[^\n]*?)\n/.source
560
+ + /\tIn case of dispute, bounty claims are judged by: (?<judge>[^\n]*?)\n/.source
561
+ + /(?:\tThe judge will be paid per investigated case with a maxium of: (?<judgePay>[^\n]*?)\n)?/.source
562
+ + /$/.source);
563
+ const m = s.match(bountyRegex);
564
+ if (!m)
565
+ throw new Error("Invalid bounty format: " + s);
566
+ return {
567
+ motivation: m[1],
568
+ bounty: m[2],
569
+ reward: m[3],
570
+ judge: m[4],
571
+ judgePay: m[5]
572
+ };
573
+ };
574
+ export const buildObservation = ({ approach, confidence, reliabilityPolicy, subject, subjectReference, observationReference, property, value }) => {
575
+ const content = "\n" +
576
+ "\t" + "Type: Observation" + "\n" +
577
+ (approach ? "\t" + "Approach: " + approach + "\n" : "") +
578
+ (confidence ? "\t" + "Confidence: " + confidence + "\n" : "") +
579
+ (reliabilityPolicy ? "\t" + "Reliability policy: " + reliabilityPolicy + "\n" : "") +
580
+ "\t" + "Subject: " + subject + "\n" +
581
+ (subjectReference ? "\t" + "Subject identity reference: " + subjectReference + "\n" : "") +
582
+ (observationReference ? "\t" + "Observation reference: " + observationReference + "\n" : "") +
583
+ "\t" + "Observed property: " + property + "\n" +
584
+ (value ? "\t" + "Observed value: " + value + "\n" : "") +
585
+ "";
586
+ return content;
587
+ };
588
+ export const parseObservation = (s) => {
589
+ const observationRegex = new RegExp(''
590
+ + /^\n\tType: Observation\n/.source
591
+ + /(?:\tApproach: (?<approach>[^\n]*?)\n)?/.source
592
+ + /(?:\tConfidence: (?<confidence>[^\n]*?)\n)?/.source
593
+ + /(?:\tReliability policy: (?<reliabilityPolicy>[^\n]+?)\n)?/.source
594
+ + /\tSubject: (?<subject>[^\n]*?)\n/.source
595
+ + /(?:\tSubject identity reference: (?<subjectReference>[^\n]*?)\n)?/.source
596
+ + /(?:\tObservation reference: (?<observationReference>[^\n]*?)\n)?/.source
597
+ + /\tObserved property: (?<property>[^\n]*?)\n/.source
598
+ + /(?:\tObserved value: (?<value>[\s\S]+?)\n)?/.source
599
+ + /$/.source);
600
+ const m = s.match(observationRegex);
601
+ if (!m)
602
+ throw new Error("Invalid observation format: " + s);
603
+ return {
604
+ approach: m[1],
605
+ confidence: m[2] ? parseFloat(m[2]) : undefined,
606
+ reliabilityPolicy: m[3],
607
+ subject: m[4],
608
+ subjectReference: m[5],
609
+ observationReference: m[6],
610
+ property: m[7],
611
+ value: m[8]
612
+ };
613
+ };
614
+ export const buildBoycott = ({ description, subject, subjectReference }) => {
615
+ const content = "\n" +
616
+ "\t" + "Type: Boycott" + "\n" +
617
+ (description ? "\t" + "Description: " + description + "\n" : "") +
618
+ "\t" + "Subject: " + subject + "\n" +
619
+ (subjectReference ? "\t" + "Subject identity reference: " + subjectReference + "\n" : "") +
620
+ "";
621
+ return content;
622
+ };
623
+ export const parseBoycott = (s) => {
624
+ const observationRegex = new RegExp(''
625
+ + /^\n\tType: Boycott\n/.source
626
+ + /(?:\tDescription: (?<description>[^\n]*?)\n)?/.source
627
+ + /\tSubject: (?<subject>[^\n]*?)\n/.source
628
+ + /(?:\tSubject identity reference: (?<subjectReference>[^\n]*?)\n)?/.source
629
+ + /$/.source);
630
+ const m = s.match(observationRegex);
631
+ if (!m)
632
+ throw new Error("Invalid observation format: " + s);
633
+ return {
634
+ description: m[1],
635
+ subject: m[2],
636
+ subjectReference: m[3],
637
+ };
638
+ };
639
+ //# sourceMappingURL=protocol.js.map