@kkuffour/solid-moderation-plugin 0.1.0
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/CONFIG-GUIDE.md +49 -0
- package/DEVELOPMENT.md +129 -0
- package/ENV-VARIABLES.md +137 -0
- package/INSTALLATION.md +90 -0
- package/LICENSE +21 -0
- package/MIGRATION.md +81 -0
- package/PRODUCTION.md +186 -0
- package/PUBLISHING.md +104 -0
- package/README.md +53 -0
- package/TESTING.md +64 -0
- package/components/components.jsonld +17 -0
- package/components/context.jsonld +211 -0
- package/config/context.jsonld +15 -0
- package/config/default.json +80 -0
- package/dist/ModerationConfig.d.ts +16 -0
- package/dist/ModerationConfig.d.ts.map +1 -0
- package/dist/ModerationConfig.js +18 -0
- package/dist/ModerationConfig.js.map +1 -0
- package/dist/ModerationConfig.jsonld +66 -0
- package/dist/ModerationMixin.d.ts +13 -0
- package/dist/ModerationMixin.d.ts.map +1 -0
- package/dist/ModerationMixin.js +136 -0
- package/dist/ModerationMixin.js.map +1 -0
- package/dist/ModerationMixin.jsonld +180 -0
- package/dist/ModerationOperationHandler.d.ts +16 -0
- package/dist/ModerationOperationHandler.d.ts.map +1 -0
- package/dist/ModerationOperationHandler.js +45 -0
- package/dist/ModerationOperationHandler.js.map +1 -0
- package/dist/ModerationOperationHandler.jsonld +140 -0
- package/dist/ModerationRecord.d.ts +20 -0
- package/dist/ModerationRecord.d.ts.map +1 -0
- package/dist/ModerationRecord.js +3 -0
- package/dist/ModerationRecord.js.map +1 -0
- package/dist/ModerationRecord.jsonld +59 -0
- package/dist/ModerationStore.d.ts +12 -0
- package/dist/ModerationStore.d.ts.map +1 -0
- package/dist/ModerationStore.js +37 -0
- package/dist/ModerationStore.js.map +1 -0
- package/dist/ModerationStore.jsonld +59 -0
- package/dist/components/components.jsonld +17 -0
- package/dist/components/context.jsonld +211 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/SightEngineProvider.d.ts +52 -0
- package/dist/providers/SightEngineProvider.d.ts.map +1 -0
- package/dist/providers/SightEngineProvider.js +302 -0
- package/dist/providers/SightEngineProvider.js.map +1 -0
- package/dist/providers/SightEngineProvider.jsonld +209 -0
- package/dist/util/GuardedStream.d.ts +33 -0
- package/dist/util/GuardedStream.d.ts.map +1 -0
- package/dist/util/GuardedStream.js +89 -0
- package/dist/util/GuardedStream.js.map +1 -0
- package/package.json +40 -0
- package/simple-test.json +7 -0
- package/src/ModerationConfig.ts +29 -0
- package/src/ModerationMixin.ts +153 -0
- package/src/ModerationOperationHandler.ts +64 -0
- package/src/ModerationRecord.ts +19 -0
- package/src/ModerationStore.ts +41 -0
- package/src/index.ts +6 -0
- package/src/providers/SightEngineProvider.ts +367 -0
- package/src/util/GuardedStream.ts +101 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.SightEngineProvider = void 0;
|
|
37
|
+
const node_fs_1 = require("node:fs");
|
|
38
|
+
const community_server_1 = require("@solid/community-server");
|
|
39
|
+
/**
|
|
40
|
+
* SightEngine implementation of content moderation provider.
|
|
41
|
+
*/
|
|
42
|
+
class SightEngineProvider {
|
|
43
|
+
constructor(apiUser, apiSecret) {
|
|
44
|
+
this.logger = (0, community_server_1.getLoggerFor)(this);
|
|
45
|
+
this.apiUser = apiUser;
|
|
46
|
+
this.apiSecret = apiSecret;
|
|
47
|
+
}
|
|
48
|
+
async analyzeImage(filePath) {
|
|
49
|
+
this.logger.info(`SIGHTENGINE: Starting analysis for ${filePath}`);
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention -- External module class name
|
|
51
|
+
const FormData = (await Promise.resolve().then(() => __importStar(require('form-data')))).default;
|
|
52
|
+
this.logger.info(`SIGHTENGINE: Creating form data for ${filePath}`);
|
|
53
|
+
const form = new FormData();
|
|
54
|
+
form.append('media', (0, node_fs_1.createReadStream)(filePath));
|
|
55
|
+
form.append('models', 'nudity-2.1,violence,gore,weapon,alcohol,offensive,self-harm,gambling');
|
|
56
|
+
form.append('api_user', this.apiUser);
|
|
57
|
+
form.append('api_secret', this.apiSecret);
|
|
58
|
+
this.logger.info(`SIGHTENGINE: Sending request to API for ${filePath}`);
|
|
59
|
+
const startTime = Date.now();
|
|
60
|
+
const result = await new Promise((resolve, reject) => {
|
|
61
|
+
form.submit('https://api.sightengine.com/1.0/check.json', (err, res) => {
|
|
62
|
+
if (err) {
|
|
63
|
+
reject(err);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
let data = '';
|
|
67
|
+
res.on('data', (chunk) => {
|
|
68
|
+
data += chunk.toString();
|
|
69
|
+
});
|
|
70
|
+
res.on('end', () => {
|
|
71
|
+
const requestTime = Date.now() - startTime;
|
|
72
|
+
this.logger.info(`SIGHTENGINE: API response received in ${requestTime}ms for ${filePath}`);
|
|
73
|
+
if (res.statusCode !== 200) {
|
|
74
|
+
this.logger.error(`SIGHTENGINE: API error ${res.statusCode} ${data} for ${filePath}`);
|
|
75
|
+
reject(new Error(`SightEngine API error: ${res.statusCode} ${data}`));
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
this.logger.info(`SIGHTENGINE: Parsing JSON response for ${filePath}`);
|
|
79
|
+
try {
|
|
80
|
+
resolve(JSON.parse(data));
|
|
81
|
+
}
|
|
82
|
+
catch (parseErr) {
|
|
83
|
+
reject(new Error(`Failed to parse response: ${String(parseErr)}`));
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
const analysisResult = {
|
|
89
|
+
nudity: result.nudity,
|
|
90
|
+
violence: result.violence && typeof result.violence === 'object' ?
|
|
91
|
+
result.violence.prob ?? 0 :
|
|
92
|
+
result.violence ?? 0,
|
|
93
|
+
gore: result.gore && typeof result.gore === 'object' ?
|
|
94
|
+
result.gore.prob ?? 0 :
|
|
95
|
+
result.gore ?? 0,
|
|
96
|
+
weapon: typeof result.weapon === 'object' && result.weapon ?
|
|
97
|
+
result.weapon.prob ?? 0 :
|
|
98
|
+
result.weapon ?? 0,
|
|
99
|
+
alcohol: result.alcohol && typeof result.alcohol === 'object' ?
|
|
100
|
+
result.alcohol.prob ?? 0 :
|
|
101
|
+
result.alcohol ?? 0,
|
|
102
|
+
drugs: 0,
|
|
103
|
+
offensive: result.offensive && typeof result.offensive === 'object' ?
|
|
104
|
+
result.offensive.prob ?? 0 :
|
|
105
|
+
result.offensive ?? 0,
|
|
106
|
+
selfharm: result['self-harm'] && typeof result['self-harm'] === 'object' ?
|
|
107
|
+
result['self-harm'].prob ?? 0 :
|
|
108
|
+
result['self-harm'] ?? 0,
|
|
109
|
+
gambling: result.gambling && typeof result.gambling === 'object' ?
|
|
110
|
+
result.gambling.prob ?? 0 :
|
|
111
|
+
result.gambling ?? 0,
|
|
112
|
+
profanity: 0,
|
|
113
|
+
personalInfo: 0,
|
|
114
|
+
};
|
|
115
|
+
this.logger.info(`SIGHTENGINE: Analysis complete for ${filePath}`);
|
|
116
|
+
const logMsg = `SIGHTENGINE: Results - Nudity: ${analysisResult.nudity?.raw ?? 0}, ` +
|
|
117
|
+
`Violence: ${analysisResult.violence}, Gore: ${analysisResult.gore}, ` +
|
|
118
|
+
`Weapon: ${analysisResult.weapon}, Alcohol: ${analysisResult.alcohol}, ` +
|
|
119
|
+
`Drugs: ${analysisResult.drugs}, Offensive: ${analysisResult.offensive}, ` +
|
|
120
|
+
`Self-harm: ${analysisResult.selfharm}, Gambling: ${analysisResult.gambling}, ` +
|
|
121
|
+
`Profanity: ${analysisResult.profanity}, Personal Info: ${analysisResult.personalInfo}`;
|
|
122
|
+
this.logger.info(logMsg);
|
|
123
|
+
return analysisResult;
|
|
124
|
+
}
|
|
125
|
+
async analyzeText(text) {
|
|
126
|
+
this.logger.info('SIGHTENGINE: Starting text analysis');
|
|
127
|
+
// Skip analysis for empty or very short text
|
|
128
|
+
if (!text || text.trim().length < 3) {
|
|
129
|
+
this.logger.info(`SIGHTENGINE: Skipping analysis for empty/short text (length: ${text?.length ?? 0})`);
|
|
130
|
+
return {
|
|
131
|
+
sexual: 0,
|
|
132
|
+
discriminatory: 0,
|
|
133
|
+
insulting: 0,
|
|
134
|
+
violent: 0,
|
|
135
|
+
toxic: 0,
|
|
136
|
+
selfharm: 0,
|
|
137
|
+
personalInfo: 0,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
const params = new URLSearchParams();
|
|
141
|
+
params.append('text', text);
|
|
142
|
+
params.append('models', 'text-content,personal-info');
|
|
143
|
+
params.append('mode', 'standard');
|
|
144
|
+
params.append('lang', 'en,es,fr,de,it,pt,nl,pl,ru');
|
|
145
|
+
params.append('api_user', this.apiUser);
|
|
146
|
+
params.append('api_secret', this.apiSecret);
|
|
147
|
+
this.logger.info('SIGHTENGINE: Sending text request to API');
|
|
148
|
+
const startTime = Date.now();
|
|
149
|
+
const response = await fetch('https://api.sightengine.com/1.0/text/check.json', {
|
|
150
|
+
method: 'POST',
|
|
151
|
+
headers: {
|
|
152
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention -- HTTP header name
|
|
153
|
+
'content-type': 'application/x-www-form-urlencoded',
|
|
154
|
+
},
|
|
155
|
+
body: params,
|
|
156
|
+
});
|
|
157
|
+
const requestTime = Date.now() - startTime;
|
|
158
|
+
this.logger.info(`SIGHTENGINE: Text API response received in ${requestTime}ms`);
|
|
159
|
+
if (!response.ok) {
|
|
160
|
+
const errorText = await response.text();
|
|
161
|
+
this.logger.error(`SIGHTENGINE: Text API error ${response.status} ${errorText}`);
|
|
162
|
+
throw new Error(`SightEngine Text API error: ${response.status} ${errorText}`);
|
|
163
|
+
}
|
|
164
|
+
this.logger.info('SIGHTENGINE: Parsing text JSON response');
|
|
165
|
+
const result = await response.json();
|
|
166
|
+
// Log the raw API response for debugging
|
|
167
|
+
this.logger.debug(`SIGHTENGINE: Raw API response: ${JSON.stringify(result)}`);
|
|
168
|
+
const analysisResult = {
|
|
169
|
+
sexual: this.getMatchScore(result.profanity?.matches ?? [], 'sexual'),
|
|
170
|
+
discriminatory: this.getMatchScore(result.profanity?.matches ?? [], 'discriminatory'),
|
|
171
|
+
insulting: this.getMatchScore(result.profanity?.matches ?? [], 'insulting'),
|
|
172
|
+
violent: this.getMatchScore(result.profanity?.matches ?? [], 'violent'),
|
|
173
|
+
toxic: this.getMatchScore(result.profanity?.matches ?? [], 'toxic'),
|
|
174
|
+
selfharm: this.getMatchScore(result.profanity?.matches ?? [], 'self-harm'),
|
|
175
|
+
personalInfo: result.personal?.matches && result.personal.matches.length > 0 ? 1 : 0,
|
|
176
|
+
};
|
|
177
|
+
// If all scores are 0, log a warning
|
|
178
|
+
let totalScore = 0;
|
|
179
|
+
for (const score of Object.values(analysisResult)) {
|
|
180
|
+
totalScore += score;
|
|
181
|
+
}
|
|
182
|
+
if (totalScore === 0) {
|
|
183
|
+
this.logger.warn('SIGHTENGINE: All moderation scores are 0 - this may indicate an API issue');
|
|
184
|
+
}
|
|
185
|
+
this.logger.info('SIGHTENGINE: Text analysis complete');
|
|
186
|
+
const logMsg = `SIGHTENGINE: Text Results - Sexual: ${analysisResult.sexual}, ` +
|
|
187
|
+
`Discriminatory: ${analysisResult.discriminatory}, Insulting: ${analysisResult.insulting}, ` +
|
|
188
|
+
`Violent: ${analysisResult.violent}, Toxic: ${analysisResult.toxic}, ` +
|
|
189
|
+
`Self-harm: ${analysisResult.selfharm}, Personal Info: ${analysisResult.personalInfo}`;
|
|
190
|
+
this.logger.info(logMsg);
|
|
191
|
+
return analysisResult;
|
|
192
|
+
}
|
|
193
|
+
getMatchScore(matches, type) {
|
|
194
|
+
if (!matches || matches.length === 0) {
|
|
195
|
+
return 0;
|
|
196
|
+
}
|
|
197
|
+
const typeMatches = matches.filter((match) => match.type === type);
|
|
198
|
+
if (typeMatches.length === 0) {
|
|
199
|
+
return 0;
|
|
200
|
+
}
|
|
201
|
+
// Convert intensity to score: high=1.0, medium=0.7, low=0.4
|
|
202
|
+
let maxIntensity = 0;
|
|
203
|
+
for (const match of typeMatches) {
|
|
204
|
+
let score;
|
|
205
|
+
if (match.intensity === 'high') {
|
|
206
|
+
score = 1;
|
|
207
|
+
}
|
|
208
|
+
else if (match.intensity === 'medium') {
|
|
209
|
+
score = 0.7;
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
score = 0.4;
|
|
213
|
+
}
|
|
214
|
+
maxIntensity = Math.max(maxIntensity, score);
|
|
215
|
+
}
|
|
216
|
+
return maxIntensity;
|
|
217
|
+
}
|
|
218
|
+
async analyzeVideo(filePath) {
|
|
219
|
+
this.logger.info(`SIGHTENGINE: Starting video analysis for ${filePath}`);
|
|
220
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention -- External module class name
|
|
221
|
+
const FormData = (await Promise.resolve().then(() => __importStar(require('form-data')))).default;
|
|
222
|
+
this.logger.info(`SIGHTENGINE: Creating form data for video ${filePath}`);
|
|
223
|
+
const form = new FormData();
|
|
224
|
+
form.append('media', (0, node_fs_1.createReadStream)(filePath));
|
|
225
|
+
const models = 'nudity-2.1,violence,gore-2.0,weapon,alcohol,offensive,self-harm,' +
|
|
226
|
+
'gambling,recreational_drug,tobacco';
|
|
227
|
+
form.append('models', models);
|
|
228
|
+
form.append('api_user', this.apiUser);
|
|
229
|
+
form.append('api_secret', this.apiSecret);
|
|
230
|
+
this.logger.info(`SIGHTENGINE: Sending video request to API for ${filePath}`);
|
|
231
|
+
const startTime = Date.now();
|
|
232
|
+
const result = await new Promise((resolve, reject) => {
|
|
233
|
+
form.submit('https://api.sightengine.com/1.0/video/check.json', (err, res) => {
|
|
234
|
+
if (err) {
|
|
235
|
+
reject(err);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
let data = '';
|
|
239
|
+
res.on('data', (chunk) => {
|
|
240
|
+
data += chunk.toString();
|
|
241
|
+
});
|
|
242
|
+
res.on('end', () => {
|
|
243
|
+
const requestTime = Date.now() - startTime;
|
|
244
|
+
this.logger.info(`SIGHTENGINE: Video API response received in ${requestTime}ms for ${filePath}`);
|
|
245
|
+
if (res.statusCode !== 200) {
|
|
246
|
+
this.logger.error(`SIGHTENGINE: Video API error ${res.statusCode} ${data} for ${filePath}`);
|
|
247
|
+
reject(new Error(`SightEngine Video API error: ${res.statusCode} ${data}`));
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
this.logger.info(`SIGHTENGINE: Parsing video JSON response for ${filePath}`);
|
|
251
|
+
try {
|
|
252
|
+
resolve(JSON.parse(data));
|
|
253
|
+
}
|
|
254
|
+
catch (parseErr) {
|
|
255
|
+
reject(new Error(`Failed to parse response: ${String(parseErr)}`));
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
const analysisResult = {
|
|
261
|
+
nudity: result.nudity,
|
|
262
|
+
violence: result.violence && typeof result.violence === 'object' ?
|
|
263
|
+
result.violence.prob ?? 0 :
|
|
264
|
+
result.violence ?? 0,
|
|
265
|
+
gore: result.gore && typeof result.gore === 'object' ?
|
|
266
|
+
result.gore.prob ?? 0 :
|
|
267
|
+
result.gore ?? 0,
|
|
268
|
+
weapon: typeof result.weapon === 'object' && result.weapon ?
|
|
269
|
+
result.weapon.prob ?? 0 :
|
|
270
|
+
result.weapon ?? 0,
|
|
271
|
+
alcohol: result.alcohol && typeof result.alcohol === 'object' ?
|
|
272
|
+
result.alcohol.prob ?? 0 :
|
|
273
|
+
result.alcohol ?? 0,
|
|
274
|
+
offensive: result.offensive && typeof result.offensive === 'object' ?
|
|
275
|
+
result.offensive.prob ?? 0 :
|
|
276
|
+
result.offensive ?? 0,
|
|
277
|
+
selfharm: result['self-harm'] && typeof result['self-harm'] === 'object' ?
|
|
278
|
+
result['self-harm'].prob ?? 0 :
|
|
279
|
+
result['self-harm'] ?? 0,
|
|
280
|
+
gambling: result.gambling && typeof result.gambling === 'object' ?
|
|
281
|
+
result.gambling.prob ?? 0 :
|
|
282
|
+
result.gambling ?? 0,
|
|
283
|
+
drugs: result.recreational_drug && typeof result.recreational_drug === 'object' ?
|
|
284
|
+
result.recreational_drug.prob ?? 0 :
|
|
285
|
+
result.recreational_drug ?? 0,
|
|
286
|
+
tobacco: result.tobacco && typeof result.tobacco === 'object' ?
|
|
287
|
+
result.tobacco.prob ?? 0 :
|
|
288
|
+
result.tobacco ?? 0,
|
|
289
|
+
};
|
|
290
|
+
this.logger.info(`SIGHTENGINE: Video analysis complete for ${filePath}`);
|
|
291
|
+
const logMsg = `SIGHTENGINE: Video Results - Nudity: ${analysisResult.nudity?.raw ?? 0}, ` +
|
|
292
|
+
`Violence: ${analysisResult.violence}, Gore: ${analysisResult.gore}, ` +
|
|
293
|
+
`Weapon: ${analysisResult.weapon}, Alcohol: ${analysisResult.alcohol}, ` +
|
|
294
|
+
`Offensive: ${analysisResult.offensive}, Self-harm: ${analysisResult.selfharm}, ` +
|
|
295
|
+
`Gambling: ${analysisResult.gambling}, Drugs: ${analysisResult.drugs}, ` +
|
|
296
|
+
`Tobacco: ${analysisResult.tobacco}`;
|
|
297
|
+
this.logger.info(logMsg);
|
|
298
|
+
return analysisResult;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
exports.SightEngineProvider = SightEngineProvider;
|
|
302
|
+
//# sourceMappingURL=SightEngineProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SightEngineProvider.js","sourceRoot":"","sources":["../../src/providers/SightEngineProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
{
|
|
2
|
+
"@context": [
|
|
3
|
+
"https://linkedsoftwaredependencies.org/bundles/npm/@kkuffour/solid-moderation-plugin/^0.1.0/components/context.jsonld",
|
|
4
|
+
"https://linkedsoftwaredependencies.org/bundles/npm/@kkuffour/solid-moderation-plugin/^0.1.0/config/context.jsonld"
|
|
5
|
+
],
|
|
6
|
+
"@id": "npmd:@kkuffour/solid-moderation-plugin",
|
|
7
|
+
"components": [
|
|
8
|
+
{
|
|
9
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineProvider",
|
|
10
|
+
"@type": "Class",
|
|
11
|
+
"requireElement": "SightEngineProvider",
|
|
12
|
+
"comment": "SightEngine implementation of content moderation provider.",
|
|
13
|
+
"parameters": [
|
|
14
|
+
{
|
|
15
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineProvider_apiUser",
|
|
16
|
+
"range": "xsd:string"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineProvider_apiSecret",
|
|
20
|
+
"range": "xsd:string"
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"memberFields": [
|
|
24
|
+
{
|
|
25
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineProvider__member_logger",
|
|
26
|
+
"memberFieldName": "logger",
|
|
27
|
+
"range": {
|
|
28
|
+
"@type": "ParameterRangeWildcard"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineProvider__member_apiUser",
|
|
33
|
+
"memberFieldName": "apiUser"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineProvider__member_apiSecret",
|
|
37
|
+
"memberFieldName": "apiSecret"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineProvider__member_constructor",
|
|
41
|
+
"memberFieldName": "constructor"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineProvider__member_analyzeImage",
|
|
45
|
+
"memberFieldName": "analyzeImage"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineProvider__member_analyzeText",
|
|
49
|
+
"memberFieldName": "analyzeText"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineProvider__member_getMatchScore",
|
|
53
|
+
"memberFieldName": "getMatchScore"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineProvider__member_analyzeVideo",
|
|
57
|
+
"memberFieldName": "analyzeVideo"
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
"constructorArguments": [
|
|
61
|
+
{
|
|
62
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineProvider_apiUser"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineProvider_apiSecret"
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineResult",
|
|
71
|
+
"@type": "AbstractClass",
|
|
72
|
+
"requireElement": "SightEngineResult",
|
|
73
|
+
"parameters": [],
|
|
74
|
+
"memberFields": [
|
|
75
|
+
{
|
|
76
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineResult__member_nudity",
|
|
77
|
+
"memberFieldName": "nudity"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineResult__member_violence",
|
|
81
|
+
"memberFieldName": "violence"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineResult__member_gore",
|
|
85
|
+
"memberFieldName": "gore"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineResult__member_weapon",
|
|
89
|
+
"memberFieldName": "weapon"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineResult__member_alcohol",
|
|
93
|
+
"memberFieldName": "alcohol"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineResult__member_drugs",
|
|
97
|
+
"memberFieldName": "drugs"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineResult__member_offensive",
|
|
101
|
+
"memberFieldName": "offensive"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineResult__member_selfharm",
|
|
105
|
+
"memberFieldName": "selfharm"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineResult__member_gambling",
|
|
109
|
+
"memberFieldName": "gambling"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineResult__member_profanity",
|
|
113
|
+
"memberFieldName": "profanity"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineResult__member_personalInfo",
|
|
117
|
+
"memberFieldName": "personalInfo"
|
|
118
|
+
}
|
|
119
|
+
],
|
|
120
|
+
"constructorArguments": []
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineTextResult",
|
|
124
|
+
"@type": "AbstractClass",
|
|
125
|
+
"requireElement": "SightEngineTextResult",
|
|
126
|
+
"parameters": [],
|
|
127
|
+
"memberFields": [
|
|
128
|
+
{
|
|
129
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineTextResult__member_sexual",
|
|
130
|
+
"memberFieldName": "sexual"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineTextResult__member_discriminatory",
|
|
134
|
+
"memberFieldName": "discriminatory"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineTextResult__member_insulting",
|
|
138
|
+
"memberFieldName": "insulting"
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineTextResult__member_violent",
|
|
142
|
+
"memberFieldName": "violent"
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineTextResult__member_toxic",
|
|
146
|
+
"memberFieldName": "toxic"
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineTextResult__member_selfharm",
|
|
150
|
+
"memberFieldName": "selfharm"
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineTextResult__member_personalInfo",
|
|
154
|
+
"memberFieldName": "personalInfo"
|
|
155
|
+
}
|
|
156
|
+
],
|
|
157
|
+
"constructorArguments": []
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineVideoResult",
|
|
161
|
+
"@type": "AbstractClass",
|
|
162
|
+
"requireElement": "SightEngineVideoResult",
|
|
163
|
+
"parameters": [],
|
|
164
|
+
"memberFields": [
|
|
165
|
+
{
|
|
166
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineVideoResult__member_nudity",
|
|
167
|
+
"memberFieldName": "nudity"
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineVideoResult__member_violence",
|
|
171
|
+
"memberFieldName": "violence"
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineVideoResult__member_gore",
|
|
175
|
+
"memberFieldName": "gore"
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineVideoResult__member_weapon",
|
|
179
|
+
"memberFieldName": "weapon"
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineVideoResult__member_alcohol",
|
|
183
|
+
"memberFieldName": "alcohol"
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineVideoResult__member_offensive",
|
|
187
|
+
"memberFieldName": "offensive"
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineVideoResult__member_selfharm",
|
|
191
|
+
"memberFieldName": "selfharm"
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineVideoResult__member_gambling",
|
|
195
|
+
"memberFieldName": "gambling"
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineVideoResult__member_drugs",
|
|
199
|
+
"memberFieldName": "drugs"
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"@id": "ksmp:dist/providers/SightEngineProvider.jsonld#SightEngineVideoResult__member_tobacco",
|
|
203
|
+
"memberFieldName": "tobacco"
|
|
204
|
+
}
|
|
205
|
+
],
|
|
206
|
+
"constructorArguments": []
|
|
207
|
+
}
|
|
208
|
+
]
|
|
209
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
declare const guardedErrors: unique symbol;
|
|
2
|
+
declare const guardedTimeout: unique symbol;
|
|
3
|
+
declare class Guard {
|
|
4
|
+
private [guardedErrors];
|
|
5
|
+
private [guardedTimeout]?;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* A stream that is guarded from emitting errors when there are no listeners.
|
|
9
|
+
* If an error occurs while no listener is attached,
|
|
10
|
+
* it will store the error and emit it once a listener is added (or a timeout occurs).
|
|
11
|
+
*/
|
|
12
|
+
export type Guarded<T extends NodeJS.EventEmitter = NodeJS.EventEmitter> = T & Guard;
|
|
13
|
+
/**
|
|
14
|
+
* Determines whether the stream is guarded against emitting errors.
|
|
15
|
+
*/
|
|
16
|
+
export declare function isGuarded<T extends NodeJS.EventEmitter>(stream: T): stream is Guarded<T>;
|
|
17
|
+
/**
|
|
18
|
+
* Makes sure that listeners always receive the error event of a stream,
|
|
19
|
+
* even if it was thrown before the listener was attached.
|
|
20
|
+
*
|
|
21
|
+
* When guarding a stream it is assumed that error listeners already attached should be ignored,
|
|
22
|
+
* only error listeners attached after the stream is guarded will prevent an error from being logged.
|
|
23
|
+
*
|
|
24
|
+
* If the input is already guarded the guard will be reset,
|
|
25
|
+
* which means ignoring error listeners already attached.
|
|
26
|
+
*
|
|
27
|
+
* @param stream - Stream that can potentially throw an error.
|
|
28
|
+
*
|
|
29
|
+
* @returns The stream.
|
|
30
|
+
*/
|
|
31
|
+
export declare function guardStream<T extends NodeJS.EventEmitter>(stream: T): Guarded<T>;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=GuardedStream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GuardedStream.d.ts","sourceRoot":"","sources":["../../src/util/GuardedStream.ts"],"names":[],"mappings":"AAKA,QAAA,MAAM,aAAa,eAA0B,CAAC;AAC9C,QAAA,MAAM,cAAc,eAA2B,CAAC;AAGhD,cAAM,KAAK;IAET,QAAgB,CAAC,aAAa,CAAC,CAAU;IACzC,OAAO,CAAC,CAAC,cAAc,CAAC,CAAC,CAAiB;CAC3C;AAED;;;;GAIG;AACH,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,CAAC,GAAG,KAAK,CAAC;AAErF;;GAEG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,CAExF;AA+CD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAYhF"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isGuarded = isGuarded;
|
|
4
|
+
exports.guardStream = guardStream;
|
|
5
|
+
const community_server_1 = require("@solid/community-server");
|
|
6
|
+
const logger = (0, community_server_1.getLoggerFor)('GuardedStream');
|
|
7
|
+
// Using symbols to make sure we don't override existing parameters
|
|
8
|
+
const guardedErrors = Symbol('guardedErrors');
|
|
9
|
+
const guardedTimeout = Symbol('guardedTimeout');
|
|
10
|
+
// Private fields for guarded streams
|
|
11
|
+
class Guard {
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Determines whether the stream is guarded against emitting errors.
|
|
15
|
+
*/
|
|
16
|
+
function isGuarded(stream) {
|
|
17
|
+
return typeof stream[guardedErrors] === 'object';
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Callback that is used when a stream emits an error and no other error listener is attached.
|
|
21
|
+
* Used to store the error and start the logger timer.
|
|
22
|
+
*
|
|
23
|
+
* It is important that this listener always remains attached for edge cases where an error listener gets removed
|
|
24
|
+
* and the number of error listeners is checked immediately afterwards.
|
|
25
|
+
* See https://github.com/CommunitySolidServer/CommunitySolidServer/pull/462#issuecomment-758013492 .
|
|
26
|
+
*/
|
|
27
|
+
function guardingErrorListener(error) {
|
|
28
|
+
// Only fall back to this if no new listeners are attached since guarding started.
|
|
29
|
+
const errorListeners = this.listeners('error');
|
|
30
|
+
if (errorListeners.at(-1) === guardingErrorListener) {
|
|
31
|
+
this[guardedErrors].push(error);
|
|
32
|
+
if (!this[guardedTimeout]) {
|
|
33
|
+
this[guardedTimeout] = setTimeout(() => {
|
|
34
|
+
logger.error(`No error listener was attached but error was thrown: ${error.message}`);
|
|
35
|
+
}, 1000);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Callback that is used when a new listener is attached and there are errors that were not emitted yet.
|
|
41
|
+
*/
|
|
42
|
+
function emitStoredErrors(event, func) {
|
|
43
|
+
if (event === 'error' && func !== guardingErrorListener) {
|
|
44
|
+
// Cancel an error timeout
|
|
45
|
+
if (this[guardedTimeout]) {
|
|
46
|
+
clearTimeout(this[guardedTimeout]);
|
|
47
|
+
this[guardedTimeout] = undefined;
|
|
48
|
+
}
|
|
49
|
+
// Emit any errors that were guarded
|
|
50
|
+
const errors = this[guardedErrors];
|
|
51
|
+
if (errors.length > 0) {
|
|
52
|
+
this[guardedErrors] = [];
|
|
53
|
+
setImmediate(() => {
|
|
54
|
+
for (const error of errors) {
|
|
55
|
+
this.emit('error', error);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Makes sure that listeners always receive the error event of a stream,
|
|
63
|
+
* even if it was thrown before the listener was attached.
|
|
64
|
+
*
|
|
65
|
+
* When guarding a stream it is assumed that error listeners already attached should be ignored,
|
|
66
|
+
* only error listeners attached after the stream is guarded will prevent an error from being logged.
|
|
67
|
+
*
|
|
68
|
+
* If the input is already guarded the guard will be reset,
|
|
69
|
+
* which means ignoring error listeners already attached.
|
|
70
|
+
*
|
|
71
|
+
* @param stream - Stream that can potentially throw an error.
|
|
72
|
+
*
|
|
73
|
+
* @returns The stream.
|
|
74
|
+
*/
|
|
75
|
+
function guardStream(stream) {
|
|
76
|
+
const guarded = stream;
|
|
77
|
+
if (isGuarded(stream)) {
|
|
78
|
+
// This makes sure the guarding error listener is the last one in the list again
|
|
79
|
+
guarded.removeListener('error', guardingErrorListener);
|
|
80
|
+
guarded.on('error', guardingErrorListener);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
guarded[guardedErrors] = [];
|
|
84
|
+
guarded.on('error', guardingErrorListener);
|
|
85
|
+
guarded.on('newListener', emitStoredErrors);
|
|
86
|
+
}
|
|
87
|
+
return guarded;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=GuardedStream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GuardedStream.js","sourceRoot":"","sources":["../../src/util/GuardedStream.ts"],"names":[],"mappings":";;AAyBA,8BAEC;AA6DD,kCAYC;AApGD,8DAAuD;AAEvD,MAAM,MAAM,GAAG,IAAA,+BAAY,EAAC,eAAe,CAAC,CAAC;AAE7C,mEAAmE;AACnE,MAAM,aAAa,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;AAC9C,MAAM,cAAc,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAEhD,qCAAqC;AACrC,MAAM,KAAK;CAIV;AASD;;GAEG;AACH,SAAgB,SAAS,CAAgC,MAAS;IAChE,OAAO,OAAQ,MAA6B,CAAC,aAAa,CAAC,KAAK,QAAQ,CAAC;AAC3E,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,qBAAqB,CAAgB,KAAY;IACxD,kFAAkF;IAClF,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAC/C,IAAI,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,qBAAqB,EAAE,CAAC;QACpD,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,cAAc,CAAC,GAAG,UAAU,CAAC,GAAS,EAAE;gBAC3C,MAAM,CAAC,KAAK,CAAC,wDAAwD,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACxF,CAAC,EAAE,IAAI,CAAC,CAAC;QACX,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAgB,KAAa,EAAE,IAA4B;IAClF,IAAI,KAAK,KAAK,OAAO,IAAI,IAAI,KAAK,qBAAqB,EAAE,CAAC;QACxD,0BAA0B;QAC1B,IAAI,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;YACzB,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;YACnC,IAAI,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;QACnC,CAAC;QAED,oCAAoC;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;QACnC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC;YACzB,YAAY,CAAC,GAAS,EAAE;gBACtB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;oBAC3B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;gBAC5B,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAgB,WAAW,CAAgC,MAAS;IAClE,MAAM,OAAO,GAAG,MAAoB,CAAC;IACrC,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QACtB,gFAAgF;QAChF,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC;QACvD,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC;IAC7C,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC;QAC5B,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC;QAC3C,OAAO,CAAC,EAAE,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|