@linkforty/core 1.44.3 → 1.45.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/dist/index.d.ts +14 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -7
- package/dist/index.js.map +1 -1
- package/dist/lib/scanner-detection.d.ts +3 -2
- package/dist/lib/scanner-detection.d.ts.map +1 -1
- package/dist/lib/scanner-detection.js +23 -7
- package/dist/lib/scanner-detection.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { DatabaseOptions } from './lib/database.js';
|
|
|
3
3
|
import { type RedirectRouteOptions } from './routes/redirect.js';
|
|
4
4
|
import { type SdkRouteOptions } from './routes/sdk.js';
|
|
5
5
|
import type { LinkFortyConfig } from './lib/config.js';
|
|
6
|
+
import { type AsnLookup } from './lib/scanner-detection.js';
|
|
6
7
|
/**
|
|
7
8
|
* Configuration options for creating a LinkForty server instance.
|
|
8
9
|
*/
|
|
@@ -21,12 +22,21 @@ export interface ServerOptions {
|
|
|
21
22
|
redirect?: RedirectRouteOptions;
|
|
22
23
|
/** Options for the SDK routes: install match scoping. */
|
|
23
24
|
sdk?: SdkRouteOptions;
|
|
24
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* Click classification options. All optional: with none of them the email
|
|
27
|
+
* security scanner rule (lib/scanner-detection.ts) is off and everything else
|
|
28
|
+
* works as usual.
|
|
29
|
+
*/
|
|
25
30
|
botDetection?: {
|
|
26
31
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
32
|
+
* Your own IP-to-ASN source: an in-house table, any database format, or API
|
|
33
|
+
* results kept in memory (it is synchronous). Takes precedence over
|
|
34
|
+
* `asnDatabasePath`. If it throws, the click counts as not a scanner.
|
|
35
|
+
*/
|
|
36
|
+
asnLookup?: AsnLookup;
|
|
37
|
+
/**
|
|
38
|
+
* Path to an ASN database in MMDB format, such as DB-IP's IP to ASN Lite. A
|
|
39
|
+
* file that can't be opened is logged and the rule stays off.
|
|
30
40
|
*/
|
|
31
41
|
asnDatabasePath?: string;
|
|
32
42
|
};
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAGnD,OAAO,EAAsB,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAkB,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAGjF,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAMlE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAGnD,OAAO,EAAsB,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAkB,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAGjF,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAMlE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAmD,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAE7G;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,KAAK,CAAC,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,IAAI,CAAC,EAAE;QACL,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;KAC3B,CAAC;IACF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,oJAAoJ;IACpJ,UAAU,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC9B,gFAAgF;IAChF,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,yDAAyD;IACzD,GAAG,CAAC,EAAE,eAAe,CAAC;IACtB;;;;OAIG;IACH,YAAY,CAAC,EAAE;QACb;;;;WAIG;QACH,SAAS,CAAC,EAAE,SAAS,CAAC;QACtB;;;WAGG;QACH,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF;;;OAGG;IACH,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAAC,OAAO,GAAE,aAAkB,kTAsD7D;AAGD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,kBAAkB,CAAC;AACjC,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,eAAe,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import { templateRoutes } from './routes/templates.js';
|
|
|
11
11
|
import { qrRoutes } from './routes/qr.js';
|
|
12
12
|
import { wellKnownRoutes } from './routes/well-known.js';
|
|
13
13
|
import { healthRoutes } from './routes/health.js';
|
|
14
|
-
import { loadScannerDetection } from './lib/scanner-detection.js';
|
|
14
|
+
import { configureScannerDetection, loadScannerDetection } from './lib/scanner-detection.js';
|
|
15
15
|
/**
|
|
16
16
|
* Create and configure a LinkForty Fastify server instance.
|
|
17
17
|
*
|
|
@@ -38,13 +38,21 @@ export async function createServer(options = {}) {
|
|
|
38
38
|
}
|
|
39
39
|
// Database
|
|
40
40
|
await initializeDatabase(options.database);
|
|
41
|
-
// Email security scanner detection (optional
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (scannerDetection)
|
|
41
|
+
// Email security scanner detection (optional). With no source configured this
|
|
42
|
+
// leaves any lookup the host already set with configureScannerDetection() alone.
|
|
43
|
+
const scannerAsns = options.config?.botDetection?.emailScannerAsns;
|
|
44
|
+
if (options.botDetection?.asnLookup) {
|
|
45
|
+
configureScannerDetection({ lookup: options.botDetection.asnLookup, asns: scannerAsns });
|
|
47
46
|
fastify.log.info('Email scanner detection is on');
|
|
47
|
+
}
|
|
48
|
+
else if (options.botDetection?.asnDatabasePath) {
|
|
49
|
+
const on = loadScannerDetection(options.botDetection.asnDatabasePath, {
|
|
50
|
+
asns: scannerAsns,
|
|
51
|
+
log: (message) => fastify.log.warn(message),
|
|
52
|
+
});
|
|
53
|
+
if (on)
|
|
54
|
+
fastify.log.info('Email scanner detection is on');
|
|
55
|
+
}
|
|
48
56
|
// Routes
|
|
49
57
|
await fastify.register(healthRoutes);
|
|
50
58
|
await fastify.register(wellKnownRoutes);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAA4B,MAAM,SAAS,CAAC;AACnD,OAAO,IAAI,MAAM,eAAe,CAAC;AACjC,OAAO,KAAK,MAAM,gBAAgB,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAmB,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAE,cAAc,EAA6B,MAAM,sBAAsB,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAwB,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,10 +23,11 @@ export declare function configureScannerDetection(options: {
|
|
|
23
23
|
/** Whether the email scanner rule is active. */
|
|
24
24
|
export declare function isScannerDetectionEnabled(): boolean;
|
|
25
25
|
/**
|
|
26
|
-
* Open
|
|
26
|
+
* Open an ASN database (`.mmdb` with `autonomous_system_number` records, as
|
|
27
|
+
* DB-IP and MaxMind publish) and return a lookup over it. Reads the
|
|
27
28
|
* file once; lookups are in memory.
|
|
28
29
|
*
|
|
29
|
-
* @throws when the file can't be read or isn't
|
|
30
|
+
* @throws when the file can't be read or isn't an MMDB database.
|
|
30
31
|
*/
|
|
31
32
|
export declare function openAsnDatabase(path: string): AsnLookup;
|
|
32
33
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanner-detection.d.ts","sourceRoot":"","sources":["../../src/lib/scanner-detection.ts"],"names":[],"mappings":"AAsBA;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,
|
|
1
|
+
{"version":3,"file":"scanner-detection.d.ts","sourceRoot":"","sources":["../../src/lib/scanner-detection.ts"],"names":[],"mappings":"AAsBA;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAOjD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,SAAS,MAAM,EAMvC,CAAC;AAEF,gEAAgE;AAChE,MAAM,MAAM,SAAS,GAAG,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;AAUtD;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE;IAAE,MAAM,EAAE,SAAS,GAAG,IAAI,CAAC;IAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CAI/G;AAED,gDAAgD;AAChD,wBAAgB,yBAAyB,IAAI,OAAO,CAEnD;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAUvD;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CAAO,GAC1E,OAAO,CAeT;AAQD,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAgB7F"}
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
* of the cloud networks below *and* the user agent is a desktop browser. Mobile
|
|
14
14
|
* browsers and app HTTP clients from those networks are left alone.
|
|
15
15
|
*
|
|
16
|
-
* The ASN comes from
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* The ASN comes from an MMDB-format ASN database that the instance supplies,
|
|
17
|
+
* such as DB-IP's IP to ASN Lite (CC BY 4.0, attribution required). Without one
|
|
18
|
+
* the rule is simply off and classification works as before.
|
|
19
19
|
*/
|
|
20
20
|
import { readFileSync } from 'fs';
|
|
21
21
|
import { Reader } from 'maxmind';
|
|
@@ -25,6 +25,7 @@ import { Reader } from 'maxmind';
|
|
|
25
25
|
*/
|
|
26
26
|
export const DEFAULT_SCANNER_ASNS = [
|
|
27
27
|
8075, // Microsoft (Azure; Defender for Office 365 Safe Links)
|
|
28
|
+
8070, // Microsoft
|
|
28
29
|
16509, // Amazon (AWS)
|
|
29
30
|
14618, // Amazon (AWS us-east-1)
|
|
30
31
|
15169, // Google
|
|
@@ -43,6 +44,7 @@ export const RELAY_ASNS = [
|
|
|
43
44
|
54113, // Fastly
|
|
44
45
|
];
|
|
45
46
|
let state = null;
|
|
47
|
+
let lookupFailureLogged = false;
|
|
46
48
|
/**
|
|
47
49
|
* Turn the email scanner rule on (or off, with `lookup: null`).
|
|
48
50
|
*
|
|
@@ -51,16 +53,18 @@ let state = null;
|
|
|
51
53
|
export function configureScannerDetection(options) {
|
|
52
54
|
const asns = new Set(options.asns ?? DEFAULT_SCANNER_ASNS);
|
|
53
55
|
state = options.lookup && asns.size > 0 ? { lookup: options.lookup, asns } : null;
|
|
56
|
+
lookupFailureLogged = false;
|
|
54
57
|
}
|
|
55
58
|
/** Whether the email scanner rule is active. */
|
|
56
59
|
export function isScannerDetectionEnabled() {
|
|
57
60
|
return state !== null;
|
|
58
61
|
}
|
|
59
62
|
/**
|
|
60
|
-
* Open
|
|
63
|
+
* Open an ASN database (`.mmdb` with `autonomous_system_number` records, as
|
|
64
|
+
* DB-IP and MaxMind publish) and return a lookup over it. Reads the
|
|
61
65
|
* file once; lookups are in memory.
|
|
62
66
|
*
|
|
63
|
-
* @throws when the file can't be read or isn't
|
|
67
|
+
* @throws when the file can't be read or isn't an MMDB database.
|
|
64
68
|
*/
|
|
65
69
|
export function openAsnDatabase(path) {
|
|
66
70
|
const reader = new Reader(readFileSync(path));
|
|
@@ -108,7 +112,19 @@ export function isEmailScanner(userAgent, ip) {
|
|
|
108
112
|
return false;
|
|
109
113
|
if (!DESKTOP_BROWSER_UA.test(userAgent))
|
|
110
114
|
return false;
|
|
111
|
-
|
|
112
|
-
|
|
115
|
+
try {
|
|
116
|
+
const asn = state.lookup(ip);
|
|
117
|
+
return asn !== null && state.asns.has(asn);
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
// A failing lookup must never cost the click its record: the caller writes
|
|
121
|
+
// the row after classifying, so count it as not a scanner and carry on.
|
|
122
|
+
if (!lookupFailureLogged) {
|
|
123
|
+
lookupFailureLogged = true;
|
|
124
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
125
|
+
console.warn(`Email scanner detection: the ASN lookup failed; treating these clicks as not scanners (${reason})`);
|
|
126
|
+
}
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
113
129
|
}
|
|
114
130
|
//# sourceMappingURL=scanner-detection.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanner-detection.js","sourceRoot":"","sources":["../../src/lib/scanner-detection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,MAAM,EAAoB,MAAM,SAAS,CAAC;AAEnD;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAsB;IACrD,IAAI,EAAE,wDAAwD;IAC9D,KAAK,EAAE,eAAe;IACtB,KAAK,EAAE,yBAAyB;IAChC,KAAK,EAAE,SAAS;IAChB,MAAM,EAAE,eAAe;CACxB,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAsB;IAC3C,GAAG,EAAE,QAAQ;IACb,KAAK,EAAE,aAAa;IACpB,KAAK,EAAE,SAAS;IAChB,KAAK,EAAE,yBAAyB;IAChC,KAAK,EAAE,SAAS;CACjB,CAAC;AAUF,IAAI,KAAK,GAAiC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"scanner-detection.js","sourceRoot":"","sources":["../../src/lib/scanner-detection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,MAAM,EAAoB,MAAM,SAAS,CAAC;AAEnD;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAsB;IACrD,IAAI,EAAE,wDAAwD;IAC9D,IAAI,EAAE,YAAY;IAClB,KAAK,EAAE,eAAe;IACtB,KAAK,EAAE,yBAAyB;IAChC,KAAK,EAAE,SAAS;IAChB,MAAM,EAAE,eAAe;CACxB,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAsB;IAC3C,GAAG,EAAE,QAAQ;IACb,KAAK,EAAE,aAAa;IACpB,KAAK,EAAE,SAAS;IAChB,KAAK,EAAE,yBAAyB;IAChC,KAAK,EAAE,SAAS;CACjB,CAAC;AAUF,IAAI,KAAK,GAAiC,IAAI,CAAC;AAC/C,IAAI,mBAAmB,GAAG,KAAK,CAAC;AAEhC;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAA+D;IACvG,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,oBAAoB,CAAC,CAAC;IAC3D,KAAK,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAClF,mBAAmB,GAAG,KAAK,CAAC;AAC9B,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,yBAAyB;IACvC,OAAO,KAAK,KAAK,IAAI,CAAC;AACxB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,MAAM,GAAG,IAAI,MAAM,CAAc,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3D,OAAO,CAAC,EAAE,EAAE,EAAE;QACZ,IAAI,CAAC;YACH,OAAO,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,wBAAwB,IAAI,IAAI,CAAC;QAC1D,CAAC;QAAC,MAAM,CAAC;YACP,wEAAwE;YACxE,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAwB,EACxB,UAAyE,EAAE;IAE3E,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,OAAe,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACxE,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,yBAAyB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,CAAC;QACH,yBAAyB,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACnF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,yBAAyB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtE,GAAG,CAAC,sEAAsE,IAAI,KAAK,MAAM,GAAG,CAAC,CAAC;QAC9F,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,yBAAyB,EAAE,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,MAAM,kBAAkB,GAAG,oDAAoD,CAAC;AAEhF,gFAAgF;AAChF,MAAM,UAAU,cAAc,CAAC,SAA6B,EAAE,EAAsB;IAClF,IAAI,CAAC,KAAK,IAAI,CAAC,EAAE,IAAI,CAAC,SAAS;QAAE,OAAO,KAAK,CAAC;IAC9C,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,OAAO,KAAK,CAAC;IACtD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC7B,OAAO,GAAG,KAAK,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,2EAA2E;QAC3E,wEAAwE;QACxE,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACzB,mBAAmB,GAAG,IAAI,CAAC;YAC3B,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACtE,OAAO,CAAC,IAAI,CAAC,0FAA0F,MAAM,GAAG,CAAC,CAAC;QACpH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|