@owlmeans/bot 0.0.0-stage → 0.1.18-rc.2
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/README.md +85 -2
- package/agent-meta/manifest.json +16 -0
- package/agent-meta/skills/bot/SKILL.md +187 -0
- package/build/consts.d.ts +132 -0
- package/build/consts.d.ts.map +1 -0
- package/build/consts.js +197 -0
- package/build/consts.js.map +1 -0
- package/build/consts.local.d.ts +13 -0
- package/build/consts.local.d.ts.map +1 -0
- package/build/consts.local.js +13 -0
- package/build/consts.local.js.map +1 -0
- package/build/errors.d.ts +43 -0
- package/build/errors.d.ts.map +1 -0
- package/build/errors.js +66 -0
- package/build/errors.js.map +1 -0
- package/build/helpers/command/types.d.ts +14 -0
- package/build/helpers/command/types.d.ts.map +1 -0
- package/build/helpers/command/types.js +2 -0
- package/build/helpers/command/types.js.map +1 -0
- package/build/helpers/command.d.ts +4 -0
- package/build/helpers/command.d.ts.map +1 -0
- package/build/helpers/command.js +21 -0
- package/build/helpers/command.js.map +1 -0
- package/build/helpers/index.d.ts +7 -0
- package/build/helpers/index.d.ts.map +1 -0
- package/build/helpers/index.js +4 -0
- package/build/helpers/index.js.map +1 -0
- package/build/helpers/platform/types.d.ts +12 -0
- package/build/helpers/platform/types.d.ts.map +1 -0
- package/build/helpers/platform/types.js +2 -0
- package/build/helpers/platform/types.js.map +1 -0
- package/build/helpers/platform.d.ts +4 -0
- package/build/helpers/platform.d.ts.map +1 -0
- package/build/helpers/platform.js +17 -0
- package/build/helpers/platform.js.map +1 -0
- package/build/helpers/rule/types.d.ts +26 -0
- package/build/helpers/rule/types.d.ts.map +1 -0
- package/build/helpers/rule/types.js +2 -0
- package/build/helpers/rule/types.js.map +1 -0
- package/build/helpers/rule.d.ts +4 -0
- package/build/helpers/rule.d.ts.map +1 -0
- package/build/helpers/rule.js +71 -0
- package/build/helpers/rule.js.map +1 -0
- package/build/index.d.ts +8 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +6 -0
- package/build/index.js.map +1 -0
- package/build/protocols/types.d.ts +115 -0
- package/build/protocols/types.d.ts.map +1 -0
- package/build/protocols/types.js +2 -0
- package/build/protocols/types.js.map +1 -0
- package/build/protocols.d.ts +21 -0
- package/build/protocols.d.ts.map +1 -0
- package/build/protocols.js +70 -0
- package/build/protocols.js.map +1 -0
- package/build/schemas.d.ts +17 -0
- package/build/schemas.d.ts.map +1 -0
- package/build/schemas.js +140 -0
- package/build/schemas.js.map +1 -0
- package/build/types.d.ts +215 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +2 -0
- package/build/types.js.map +1 -0
- package/build/utils/aliases/types.d.ts +30 -0
- package/build/utils/aliases/types.d.ts.map +1 -0
- package/build/utils/aliases/types.js +2 -0
- package/build/utils/aliases/types.js.map +1 -0
- package/build/utils/aliases.d.ts +4 -0
- package/build/utils/aliases.d.ts.map +1 -0
- package/build/utils/aliases.js +26 -0
- package/build/utils/aliases.js.map +1 -0
- package/package.json +42 -4
- package/src/consts.local.ts +14 -0
- package/src/consts.ts +214 -0
- package/src/errors.ts +78 -0
- package/src/helpers/command/types.ts +14 -0
- package/src/helpers/command.ts +26 -0
- package/src/helpers/index.ts +6 -0
- package/src/helpers/platform/types.ts +12 -0
- package/src/helpers/platform.ts +23 -0
- package/src/helpers/rule/types.ts +26 -0
- package/src/helpers/rule.ts +89 -0
- package/src/index.ts +7 -0
- package/src/protocols/types.ts +107 -0
- package/src/protocols.ts +121 -0
- package/src/schemas.ts +159 -0
- package/src/types.ts +228 -0
- package/src/utils/aliases/types.ts +25 -0
- package/src/utils/aliases.ts +30 -0
- package/tests/command.spec.ts +23 -0
- package/tests/context.ts +13 -0
- package/tests/errors.spec.ts +41 -0
- package/tests/platforms.spec.ts +60 -0
- package/tests/protocols.spec.ts +80 -0
- package/tests/rule.spec.ts +129 -0
- package/tests/schemas.spec.ts +102 -0
- package/tests/tsconfig.json +12 -0
- package/tests/update.spec.ts +38 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.local.d.ts","sourceRoot":"","sources":["../src/consts.local.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,iBAAiB,QAA0B,CAAA;AAExD,0GAA0G;AAC1G,eAAO,MAAM,iBAAiB,QAAU,CAAA;AAExC;;;GAGG;AACH,eAAO,MAAM,mBAAmB,QAA6E,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One token of `word` matching: letters, combining marks, digits and `_`. Marks are part of the word
|
|
3
|
+
* (Devanagari vowel signs, a decomposed accent left after folding), so a word never splits on one.
|
|
4
|
+
*/
|
|
5
|
+
export const BOT_TOKEN_PATTERN = /[\p{L}\p{M}\p{N}_]+/gu;
|
|
6
|
+
/** Any whitespace run — collapsed to one space before a `contains` comparison and in a stored keyword. */
|
|
7
|
+
export const BOT_SPACE_PATTERN = /\s+/gu;
|
|
8
|
+
/**
|
|
9
|
+
* A `/command`, optionally addressed `@ToBot`, ending at whitespace or at the end of the text, then
|
|
10
|
+
* its arguments.
|
|
11
|
+
*/
|
|
12
|
+
export const BOT_COMMAND_PATTERN = /^\/([\p{L}\p{N}_-]{1,64})(?:@([\p{L}\p{N}_.]{1,64}))?(?:\s+([\s\S]*))?$/u;
|
|
13
|
+
//# sourceMappingURL=consts.local.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.local.js","sourceRoot":"","sources":["../src/consts.local.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,uBAAuB,CAAA;AAExD,0GAA0G;AAC1G,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAO,CAAA;AAExC;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,0EAA0E,CAAA"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ResilientError } from '@owlmeans/error';
|
|
2
|
+
/**
|
|
3
|
+
* The bot refusal family.
|
|
4
|
+
*
|
|
5
|
+
* Every message starts with `bot:` and the class's own marker (`connection-not-found:` …) — the
|
|
6
|
+
* marker survives a hop where the class is not registered, so it is part of the contract. The family
|
|
7
|
+
* base declares no status: a fault of the platform or the store answers 500.
|
|
8
|
+
*/
|
|
9
|
+
export declare class BotError extends ResilientError {
|
|
10
|
+
static typeName: string;
|
|
11
|
+
constructor(message?: string);
|
|
12
|
+
}
|
|
13
|
+
/** The connection does not exist — or is another scope's, which is deliberately the same answer. */
|
|
14
|
+
export declare class BotConnectionNotFound extends BotError {
|
|
15
|
+
static typeName: string;
|
|
16
|
+
static httpStatus: number;
|
|
17
|
+
constructor(message?: string);
|
|
18
|
+
}
|
|
19
|
+
/** The platform refused the credentials (or a required one is missing) at verification. */
|
|
20
|
+
export declare class BotCredentialsRejected extends BotError {
|
|
21
|
+
static typeName: string;
|
|
22
|
+
static httpStatus: number;
|
|
23
|
+
constructor(message?: string);
|
|
24
|
+
}
|
|
25
|
+
/** An inbound hook whose signature (or verify token) does not prove it came from the platform. */
|
|
26
|
+
export declare class BotSignatureRejected extends BotError {
|
|
27
|
+
static typeName: string;
|
|
28
|
+
static httpStatus: number;
|
|
29
|
+
constructor(message?: string);
|
|
30
|
+
}
|
|
31
|
+
/** The request needs the other transport — `simulate` on a live connection. */
|
|
32
|
+
export declare class BotTransportMismatch extends BotError {
|
|
33
|
+
static typeName: string;
|
|
34
|
+
static httpStatus: number;
|
|
35
|
+
constructor(message?: string);
|
|
36
|
+
}
|
|
37
|
+
/** The platform (or the connection's credentials) cannot perform the requested action. */
|
|
38
|
+
export declare class BotUnsupportedAction extends BotError {
|
|
39
|
+
static typeName: string;
|
|
40
|
+
static httpStatus: number;
|
|
41
|
+
constructor(message?: string);
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD;;;;;;GAMG;AACH,qBAAa,QAAS,SAAQ,cAAc;IAC1C,OAAuB,QAAQ,EAAE,MAAM,CAAa;IAEpD,YAAY,OAAO,GAAE,MAAgB,EAEpC;CACF;AAED,oGAAoG;AACpG,qBAAa,qBAAsB,SAAQ,QAAQ;IACjD,OAAuB,QAAQ,EAAE,MAAM,CAA2C;IAClF,OAAc,UAAU,SAAM;IAE9B,YAAY,OAAO,GAAE,MAAgB,EAGpC;CACF;AAED,2FAA2F;AAC3F,qBAAa,sBAAuB,SAAQ,QAAQ;IAClD,OAAuB,QAAQ,EAAE,MAAM,CAA4C;IACnF,OAAc,UAAU,SAAM;IAE9B,YAAY,OAAO,GAAE,MAAgB,EAGpC;CACF;AAED,kGAAkG;AAClG,qBAAa,oBAAqB,SAAQ,QAAQ;IAChD,OAAuB,QAAQ,EAAE,MAAM,CAA0C;IACjF,OAAc,UAAU,SAAM;IAE9B,YAAY,OAAO,GAAE,MAAgB,EAGpC;CACF;AAED,+EAA+E;AAC/E,qBAAa,oBAAqB,SAAQ,QAAQ;IAChD,OAAuB,QAAQ,EAAE,MAAM,CAA0C;IACjF,OAAc,UAAU,SAAM;IAE9B,YAAY,OAAO,GAAE,MAAgB,EAGpC;CACF;AAED,0FAA0F;AAC1F,qBAAa,oBAAqB,SAAQ,QAAQ;IAChD,OAAuB,QAAQ,EAAE,MAAM,CAA0C;IACjF,OAAc,UAAU,SAAM;IAE9B,YAAY,OAAO,GAAE,MAAgB,EAGpC;CACF"}
|
package/build/errors.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { ResilientError } from '@owlmeans/error';
|
|
2
|
+
/**
|
|
3
|
+
* The bot refusal family.
|
|
4
|
+
*
|
|
5
|
+
* Every message starts with `bot:` and the class's own marker (`connection-not-found:` …) — the
|
|
6
|
+
* marker survives a hop where the class is not registered, so it is part of the contract. The family
|
|
7
|
+
* base declares no status: a fault of the platform or the store answers 500.
|
|
8
|
+
*/
|
|
9
|
+
export class BotError extends ResilientError {
|
|
10
|
+
static typeName = 'BotError';
|
|
11
|
+
constructor(message = 'error') {
|
|
12
|
+
super(BotError.typeName, `bot:${message}`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/** The connection does not exist — or is another scope's, which is deliberately the same answer. */
|
|
16
|
+
export class BotConnectionNotFound extends BotError {
|
|
17
|
+
static typeName = `${BotError.typeName}ConnectionNotFound`;
|
|
18
|
+
static httpStatus = 404;
|
|
19
|
+
constructor(message = 'error') {
|
|
20
|
+
super(`connection-not-found:${message}`);
|
|
21
|
+
this.type = BotConnectionNotFound.typeName;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/** The platform refused the credentials (or a required one is missing) at verification. */
|
|
25
|
+
export class BotCredentialsRejected extends BotError {
|
|
26
|
+
static typeName = `${BotError.typeName}CredentialsRejected`;
|
|
27
|
+
static httpStatus = 422;
|
|
28
|
+
constructor(message = 'error') {
|
|
29
|
+
super(`credentials-rejected:${message}`);
|
|
30
|
+
this.type = BotCredentialsRejected.typeName;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** An inbound hook whose signature (or verify token) does not prove it came from the platform. */
|
|
34
|
+
export class BotSignatureRejected extends BotError {
|
|
35
|
+
static typeName = `${BotError.typeName}SignatureRejected`;
|
|
36
|
+
static httpStatus = 401;
|
|
37
|
+
constructor(message = 'error') {
|
|
38
|
+
super(`signature-rejected:${message}`);
|
|
39
|
+
this.type = BotSignatureRejected.typeName;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/** The request needs the other transport — `simulate` on a live connection. */
|
|
43
|
+
export class BotTransportMismatch extends BotError {
|
|
44
|
+
static typeName = `${BotError.typeName}TransportMismatch`;
|
|
45
|
+
static httpStatus = 409;
|
|
46
|
+
constructor(message = 'error') {
|
|
47
|
+
super(`transport-mismatch:${message}`);
|
|
48
|
+
this.type = BotTransportMismatch.typeName;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** The platform (or the connection's credentials) cannot perform the requested action. */
|
|
52
|
+
export class BotUnsupportedAction extends BotError {
|
|
53
|
+
static typeName = `${BotError.typeName}UnsupportedAction`;
|
|
54
|
+
static httpStatus = 422;
|
|
55
|
+
constructor(message = 'error') {
|
|
56
|
+
super(`unsupported-action:${message}`);
|
|
57
|
+
this.type = BotUnsupportedAction.typeName;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
ResilientError.registerErrorClass(BotError);
|
|
61
|
+
ResilientError.registerErrorClass(BotConnectionNotFound);
|
|
62
|
+
ResilientError.registerErrorClass(BotCredentialsRejected);
|
|
63
|
+
ResilientError.registerErrorClass(BotSignatureRejected);
|
|
64
|
+
ResilientError.registerErrorClass(BotTransportMismatch);
|
|
65
|
+
ResilientError.registerErrorClass(BotUnsupportedAction);
|
|
66
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD;;;;;;GAMG;AACH,MAAM,OAAO,QAAS,SAAQ,cAAc;IACnC,MAAM,CAAU,QAAQ,GAAW,UAAU,CAAA;IAEpD,YAAY,OAAO,GAAW,OAAO;QACnC,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,OAAO,EAAE,CAAC,CAAA;IAC5C,CAAC;CACF;AAED,oGAAoG;AACpG,MAAM,OAAO,qBAAsB,SAAQ,QAAQ;IAC1C,MAAM,CAAU,QAAQ,GAAW,GAAG,QAAQ,CAAC,QAAQ,oBAAoB,CAAA;IAC3E,MAAM,CAAC,UAAU,GAAG,GAAG,CAAA;IAE9B,YAAY,OAAO,GAAW,OAAO;QACnC,KAAK,CAAC,wBAAwB,OAAO,EAAE,CAAC,CAAA;QACxC,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC,QAAQ,CAAA;IAC5C,CAAC;CACF;AAED,2FAA2F;AAC3F,MAAM,OAAO,sBAAuB,SAAQ,QAAQ;IAC3C,MAAM,CAAU,QAAQ,GAAW,GAAG,QAAQ,CAAC,QAAQ,qBAAqB,CAAA;IAC5E,MAAM,CAAC,UAAU,GAAG,GAAG,CAAA;IAE9B,YAAY,OAAO,GAAW,OAAO;QACnC,KAAK,CAAC,wBAAwB,OAAO,EAAE,CAAC,CAAA;QACxC,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC,QAAQ,CAAA;IAC7C,CAAC;CACF;AAED,kGAAkG;AAClG,MAAM,OAAO,oBAAqB,SAAQ,QAAQ;IACzC,MAAM,CAAU,QAAQ,GAAW,GAAG,QAAQ,CAAC,QAAQ,mBAAmB,CAAA;IAC1E,MAAM,CAAC,UAAU,GAAG,GAAG,CAAA;IAE9B,YAAY,OAAO,GAAW,OAAO;QACnC,KAAK,CAAC,sBAAsB,OAAO,EAAE,CAAC,CAAA;QACtC,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC,QAAQ,CAAA;IAC3C,CAAC;CACF;AAED,+EAA+E;AAC/E,MAAM,OAAO,oBAAqB,SAAQ,QAAQ;IACzC,MAAM,CAAU,QAAQ,GAAW,GAAG,QAAQ,CAAC,QAAQ,mBAAmB,CAAA;IAC1E,MAAM,CAAC,UAAU,GAAG,GAAG,CAAA;IAE9B,YAAY,OAAO,GAAW,OAAO;QACnC,KAAK,CAAC,sBAAsB,OAAO,EAAE,CAAC,CAAA;QACtC,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC,QAAQ,CAAA;IAC3C,CAAC;CACF;AAED,0FAA0F;AAC1F,MAAM,OAAO,oBAAqB,SAAQ,QAAQ;IACzC,MAAM,CAAU,QAAQ,GAAW,GAAG,QAAQ,CAAC,QAAQ,mBAAmB,CAAA;IAC1E,MAAM,CAAC,UAAU,GAAG,GAAG,CAAA;IAE9B,YAAY,OAAO,GAAW,OAAO;QACnC,KAAK,CAAC,sBAAsB,OAAO,EAAE,CAAC,CAAA;QACtC,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC,QAAQ,CAAA;IAC3C,CAAC;CACF;AAED,cAAc,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAA;AAC3C,cAAc,CAAC,kBAAkB,CAAC,qBAAqB,CAAC,CAAA;AACxD,cAAc,CAAC,kBAAkB,CAAC,sBAAsB,CAAC,CAAA;AACzD,cAAc,CAAC,kBAAkB,CAAC,oBAAoB,CAAC,CAAA;AACvD,cAAc,CAAC,kBAAkB,CAAC,oBAAoB,CAAC,CAAA;AACvD,cAAc,CAAC,kBAAkB,CAAC,oBAAoB,CAAC,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { BotCommand } from '../../types.js';
|
|
2
|
+
export interface BotCommandHelper {
|
|
3
|
+
/**
|
|
4
|
+
* Read a `/command` off the start of a message: `/report@MyBot some args` →
|
|
5
|
+
* `{ name: 'report', args: 'some args' }`.
|
|
6
|
+
*
|
|
7
|
+
* The name is lower-cased and must end at whitespace or at the end of the text (`/usr/bin` is not a
|
|
8
|
+
* command); `args` is the trimmed rest, `''` when none. A command addressed to ANOTHER bot
|
|
9
|
+
* (`@OtherBot`, compared case-insensitively, a leading `@` of `botUsername` ignored) answers `null`
|
|
10
|
+
* — when `botUsername` is not given, any address is accepted. Not a command answers `null`.
|
|
11
|
+
*/
|
|
12
|
+
parse: (text: string, botUsername?: string) => BotCommand | null;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/helpers/command/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAEhD,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;OAQG;IACH,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,UAAU,GAAG,IAAI,CAAA;CACjE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/helpers/command/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/helpers/command.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAE1D,eAAO,MAAM,sBAAsB,QAAO,gBAmBzC,CAAA;AAED,eAAO,MAAM,gBAAgB,kBAA2B,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BOT_COMMAND_PATTERN } from '../consts.local.js';
|
|
2
|
+
export const createBotCommandHelper = () => {
|
|
3
|
+
const parse = (text, botUsername) => {
|
|
4
|
+
if (typeof text !== 'string') {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
const found = BOT_COMMAND_PATTERN.exec(text.trimStart());
|
|
8
|
+
if (found == null) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
const [, name, addressee, args] = found;
|
|
12
|
+
const own = botUsername?.replace(/^@/, '').trim().toLowerCase();
|
|
13
|
+
if (addressee != null && own != null && own !== '' && addressee.toLowerCase() !== own) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
return { name: name.toLowerCase(), args: (args ?? '').trim() };
|
|
17
|
+
};
|
|
18
|
+
return { parse };
|
|
19
|
+
};
|
|
20
|
+
export const botCommandHelper = createBotCommandHelper();
|
|
21
|
+
//# sourceMappingURL=command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.js","sourceRoot":"","sources":["../../src/helpers/command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAIxD,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAqB,EAAE;IAC3D,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,WAAoB,EAAqB,EAAE;QACtE,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAA;QACb,CAAC;QACD,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAA;QACxD,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,OAAO,IAAI,CAAA;QACb,CAAC;QACD,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,KAAK,CAAA;QACvC,MAAM,GAAG,GAAG,WAAW,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;QAC/D,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,KAAK,EAAE,IAAI,SAAS,CAAC,WAAW,EAAE,KAAK,GAAG,EAAE,CAAC;YACtF,OAAO,IAAI,CAAA;QACb,CAAC;QAED,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAA;IAChE,CAAC,CAAA;IAED,OAAO,EAAE,KAAK,EAAE,CAAA;AAClB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,sBAAsB,EAAE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/helpers/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,iBAAiB,CAAA;AACpC,mBAAmB,oBAAoB,CAAA;AACvC,mBAAmB,qBAAqB,CAAA;AACxC,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/helpers/index.ts"],"names":[],"mappings":"AAGA,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { BotActionKind, BotPlatform } from '../../consts.js';
|
|
2
|
+
/** What a connection on a platform can do, given which of its credentials hold a value. */
|
|
3
|
+
export interface BotPlatformHelper {
|
|
4
|
+
/**
|
|
5
|
+
* The descriptor's actions, plus those an optional credential `enables` when its key is in
|
|
6
|
+
* `credentialsSet` (Slack's `userToken` → `delete`), plus `note`, which every connection supports.
|
|
7
|
+
*/
|
|
8
|
+
actionsOf: (platform: BotPlatform, credentialsSet?: readonly string[]) => BotActionKind[];
|
|
9
|
+
/** Whether {@link BotPlatformHelper.actionsOf} includes `kind`. */
|
|
10
|
+
supports: (platform: BotPlatform, kind: BotActionKind, credentialsSet?: readonly string[]) => boolean;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/helpers/platform/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAEjE,2FAA2F;AAC3F,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,SAAS,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,KAAK,aAAa,EAAE,CAAA;IACzF,mEAAmE;IACnE,QAAQ,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,aAAa,EAAE,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAA;CACtG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/helpers/platform/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/helpers/platform.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAE5D,eAAO,MAAM,uBAAuB,QAAO,iBAiB1C,CAAA;AAED,eAAO,MAAM,iBAAiB,mBAA4B,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BOT_PLATFORMS, BotActionKind } from '../consts.js';
|
|
2
|
+
export const createBotPlatformHelper = () => {
|
|
3
|
+
const actionsOf = (platform, credentialsSet = []) => {
|
|
4
|
+
const descriptor = BOT_PLATFORMS[platform];
|
|
5
|
+
if (descriptor == null) {
|
|
6
|
+
return [BotActionKind.Note];
|
|
7
|
+
}
|
|
8
|
+
const enabled = descriptor.credentials
|
|
9
|
+
.filter(field => field.enables != null && credentialsSet.includes(field.key))
|
|
10
|
+
.flatMap(field => field.enables ?? []);
|
|
11
|
+
return [...new Set([...descriptor.actions, ...enabled, BotActionKind.Note])];
|
|
12
|
+
};
|
|
13
|
+
const supports = (platform, kind, credentialsSet) => actionsOf(platform, credentialsSet).includes(kind);
|
|
14
|
+
return { actionsOf, supports };
|
|
15
|
+
};
|
|
16
|
+
export const botPlatformHelper = createBotPlatformHelper();
|
|
17
|
+
//# sourceMappingURL=platform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/helpers/platform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAoB,MAAM,cAAc,CAAA;AAG7E,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAsB,EAAE;IAC7D,MAAM,SAAS,GAAG,CAAC,QAAqB,EAAE,cAAc,GAAsB,EAAE,EAAmB,EAAE;QACnG,MAAM,UAAU,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAA;QAC1C,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;YACvB,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAA;QAC7B,CAAC;QACD,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW;aACnC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,IAAI,IAAI,IAAI,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;aAC5E,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAA;QAExC,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,OAAO,EAAE,GAAG,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAC9E,CAAC,CAAA;IAED,MAAM,QAAQ,GAAG,CAAC,QAAqB,EAAE,IAAmB,EAAE,cAAkC,EAAW,EAAE,CAC3G,SAAS,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IAEpD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAA;AAChC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,uBAAuB,EAAE,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { BotMatch, BotRule } from '../../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* How a message is matched against keyword groups — the ONE implementation the server's dispatch,
|
|
4
|
+
* the panels and the tests share, so a rule means the same thing everywhere.
|
|
5
|
+
*/
|
|
6
|
+
export interface BotRuleHelper {
|
|
7
|
+
/**
|
|
8
|
+
* The enabled rules whose keywords the text matches, ordered by `order` (ties keep the given
|
|
9
|
+
* order), each with the keywords (as stored) that matched.
|
|
10
|
+
*
|
|
11
|
+
* Both sides are folded the same way: NFKC, then case-folded (`ß` ≡ `ss`, `Ё` ≡ `ё`), accents
|
|
12
|
+
* kept. `word` compares whole tokens — runs of letters, combining marks, digits and `_` — and a
|
|
13
|
+
* multi-word keyword is a PHRASE that must appear as consecutive tokens; `contains` is a substring
|
|
14
|
+
* of the folded text with whitespace runs collapsed. Disabled rules never match.
|
|
15
|
+
*/
|
|
16
|
+
match: (text: string, rules: readonly BotRule[]) => BotMatch[];
|
|
17
|
+
/**
|
|
18
|
+
* A keyword list as it is stored: each trimmed with inner whitespace collapsed, cut to
|
|
19
|
+
* `BOT_KEYWORD_MAX` code points, empties dropped, duplicates (by their folded form) dropped keeping
|
|
20
|
+
* the first spelling, at most `BOT_KEYWORDS_MAX` kept.
|
|
21
|
+
*/
|
|
22
|
+
normalizeKeywords: (list: readonly string[]) => string[];
|
|
23
|
+
/** Whether a rule applies to a connection: its own, or a scope-wide one (`connection` null/absent). */
|
|
24
|
+
appliesTo: (rule: Pick<BotRule, 'connection'>, connection: string) => boolean;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/helpers/rule/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAEvD;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;;;;OAQG;IACH,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,OAAO,EAAE,KAAK,QAAQ,EAAE,CAAA;IAC9D;;;;OAIG;IACH,iBAAiB,EAAE,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,MAAM,EAAE,CAAA;IACxD,uGAAuG;IACvG,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAA;CAC9E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/helpers/rule/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule.d.ts","sourceRoot":"","sources":["../../src/helpers/rule.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAEpD,eAAO,MAAM,mBAAmB,QAAO,aAiFtC,CAAA;AAED,eAAO,MAAM,aAAa,eAAwB,CAAA"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { BOT_KEYWORD_MAX, BOT_KEYWORDS_MAX, BotMatchMode } from '../consts.js';
|
|
2
|
+
import { BOT_SPACE_PATTERN, BOT_TOKEN_PATTERN } from '../consts.local.js';
|
|
3
|
+
export const createBotRuleHelper = () => {
|
|
4
|
+
/**
|
|
5
|
+
* NFKC, then a case fold: upper-casing first maps what lower-casing alone keeps apart (`ß` → `SS`
|
|
6
|
+
* → `ss`, final `ς` → `Σ` → `σ`), and NFKC again recomposes what the case mapping decomposed.
|
|
7
|
+
*/
|
|
8
|
+
const fold = (text) => text.normalize('NFKC').toUpperCase().toLowerCase().normalize('NFKC');
|
|
9
|
+
const tokensOf = (text) => fold(text).match(BOT_TOKEN_PATTERN) ?? [];
|
|
10
|
+
const spacedOf = (text) => fold(text).replace(BOT_SPACE_PATTERN, ' ').trim();
|
|
11
|
+
const hasPhrase = (tokens, phrase) => {
|
|
12
|
+
for (let at = 0; at + phrase.length <= tokens.length; at++) {
|
|
13
|
+
if (phrase.every((token, offset) => tokens[at + offset] === token)) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return false;
|
|
18
|
+
};
|
|
19
|
+
const match = (text, rules) => {
|
|
20
|
+
if (typeof text !== 'string' || text.trim() === '') {
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
// Folded once per message, never per rule.
|
|
24
|
+
let tokens;
|
|
25
|
+
let spaced;
|
|
26
|
+
const matchesKeyword = (mode, keyword) => {
|
|
27
|
+
if (mode === BotMatchMode.Contains) {
|
|
28
|
+
const needle = spacedOf(keyword);
|
|
29
|
+
spaced ??= spacedOf(text);
|
|
30
|
+
return needle !== '' && spaced.includes(needle);
|
|
31
|
+
}
|
|
32
|
+
const phrase = tokensOf(keyword);
|
|
33
|
+
tokens ??= tokensOf(text);
|
|
34
|
+
return phrase.length > 0 && hasPhrase(tokens, phrase);
|
|
35
|
+
};
|
|
36
|
+
return rules
|
|
37
|
+
.filter(rule => rule.enabled)
|
|
38
|
+
.map((rule) => ({
|
|
39
|
+
rule,
|
|
40
|
+
keywords: [...new Set(rule.keywords.filter(keyword => typeof keyword === 'string' && matchesKeyword(rule.mode ?? BotMatchMode.Word, keyword)))],
|
|
41
|
+
}))
|
|
42
|
+
.filter(found => found.keywords.length > 0)
|
|
43
|
+
// Array#sort is stable: rules of equal order keep the order they were given in.
|
|
44
|
+
.sort((left, right) => (left.rule.order ?? 0) - (right.rule.order ?? 0));
|
|
45
|
+
};
|
|
46
|
+
const normalizeKeywords = (list) => {
|
|
47
|
+
const seen = new Set();
|
|
48
|
+
const result = [];
|
|
49
|
+
for (const raw of list ?? []) {
|
|
50
|
+
if (typeof raw !== 'string') {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
const keyword = Array.from(raw.replace(BOT_SPACE_PATTERN, ' ').trim())
|
|
54
|
+
.slice(0, BOT_KEYWORD_MAX).join('').trim();
|
|
55
|
+
const key = spacedOf(keyword);
|
|
56
|
+
if (keyword === '' || seen.has(key)) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
seen.add(key);
|
|
60
|
+
result.push(keyword);
|
|
61
|
+
if (result.length >= BOT_KEYWORDS_MAX) {
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
};
|
|
67
|
+
const appliesTo = (rule, connection) => rule.connection == null || rule.connection === connection;
|
|
68
|
+
return { match, normalizeKeywords, appliesTo };
|
|
69
|
+
};
|
|
70
|
+
export const botRuleHelper = createBotRuleHelper();
|
|
71
|
+
//# sourceMappingURL=rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule.js","sourceRoot":"","sources":["../../src/helpers/rule.ts"],"names":[],"mappings":"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"}
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type * from './types.js';
|
|
2
|
+
export type * from './protocols/types.js';
|
|
3
|
+
export * from './consts.js';
|
|
4
|
+
export * from './schemas.js';
|
|
5
|
+
export * from './errors.js';
|
|
6
|
+
export * from './protocols.js';
|
|
7
|
+
export * from './helpers/index.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,YAAY,CAAA;AAC/B,mBAAmB,sBAAsB,CAAA;AACzC,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,oBAAoB,CAAA"}
|
package/build/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,oBAAoB,CAAA"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type { EntrypointProtocol, OpenRequest, OpenValue } from '@owlmeans/entrypoint';
|
|
2
|
+
import type { RouteParent } from '@owlmeans/route';
|
|
3
|
+
import type { BotPlatform } from '../consts.js';
|
|
4
|
+
import type { BotActivity, BotConnection, BotConnectionInput, BotRule, BotRuleInput, BotSimulateInput, BotSimulateResult } from '../types.js';
|
|
5
|
+
/** Where a bot tree mounts. Every leaf alias derives from `alias` (`<alias>:connection:list` …). */
|
|
6
|
+
export interface BotBaseOptions {
|
|
7
|
+
alias: string;
|
|
8
|
+
/** The base path — `/bot/operator`, `/bot/member`, `/bot/hook`. */
|
|
9
|
+
path: string;
|
|
10
|
+
parent?: RouteParent;
|
|
11
|
+
service?: string;
|
|
12
|
+
}
|
|
13
|
+
/** The access gate the managing base carries — `EntrypointOptions['gate']`. */
|
|
14
|
+
export interface BotGateOptions {
|
|
15
|
+
alias: string;
|
|
16
|
+
params?: string | readonly string[];
|
|
17
|
+
}
|
|
18
|
+
export interface BotProtocolOptions {
|
|
19
|
+
base: BotBaseOptions;
|
|
20
|
+
/** The guard(s) the base carries; every leaf inherits them. */
|
|
21
|
+
guards?: string | readonly string[];
|
|
22
|
+
/** The ONE gate the base carries (a protocol has one gate); every leaf inherits it. */
|
|
23
|
+
gates?: BotGateOptions;
|
|
24
|
+
}
|
|
25
|
+
export interface BotHookProtocolOptions {
|
|
26
|
+
base: BotBaseOptions;
|
|
27
|
+
}
|
|
28
|
+
/** `:id` of a connection or a rule. */
|
|
29
|
+
export interface BotIdParams {
|
|
30
|
+
id: string;
|
|
31
|
+
}
|
|
32
|
+
export interface BotRemoveResult {
|
|
33
|
+
id: string;
|
|
34
|
+
}
|
|
35
|
+
export interface BotRuleListQuery {
|
|
36
|
+
/** Rules of this connection plus the scope-wide ones; every rule of the scope when absent. */
|
|
37
|
+
connection?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface BotActivityQuery {
|
|
40
|
+
connection?: string;
|
|
41
|
+
/** 1 … `BOT_ACTIVITY_LIMIT_MAX`; `BOT_ACTIVITY_LIMIT_DEFAULT` when absent. */
|
|
42
|
+
limit?: number;
|
|
43
|
+
}
|
|
44
|
+
/** The hook address: `/:platform/:connection`. */
|
|
45
|
+
export interface BotHookParams {
|
|
46
|
+
platform: BotPlatform;
|
|
47
|
+
connection: string;
|
|
48
|
+
}
|
|
49
|
+
/** The platform's NATIVE payload — authenticated and normalized by the server, never by a schema. */
|
|
50
|
+
export interface BotHookPayload {
|
|
51
|
+
[key: string]: unknown;
|
|
52
|
+
}
|
|
53
|
+
/** What the receive hook answers: 200 at once, or a handshake's challenge (Slack `url_verification`). */
|
|
54
|
+
export interface BotHookReply {
|
|
55
|
+
ok?: boolean;
|
|
56
|
+
challenge?: string;
|
|
57
|
+
}
|
|
58
|
+
/** The subscription handshake WhatsApp sends as a GET (`hub.*`); answered with `hub.challenge`. */
|
|
59
|
+
export interface BotChallengeQuery {
|
|
60
|
+
'hub.mode'?: string;
|
|
61
|
+
'hub.verify_token'?: string;
|
|
62
|
+
'hub.challenge'?: string;
|
|
63
|
+
}
|
|
64
|
+
/** The managing surface of one mount (operator or member). */
|
|
65
|
+
export interface BotProtocols {
|
|
66
|
+
/** Carries the guards and the gate; every leaf hangs under it. */
|
|
67
|
+
base: EntrypointProtocol<OpenRequest, OpenValue>;
|
|
68
|
+
connection: {
|
|
69
|
+
list: EntrypointProtocol<{}, BotConnection[]>;
|
|
70
|
+
save: EntrypointProtocol<{
|
|
71
|
+
body: BotConnectionInput;
|
|
72
|
+
}, BotConnection>;
|
|
73
|
+
verify: EntrypointProtocol<{
|
|
74
|
+
params: BotIdParams;
|
|
75
|
+
}, BotConnection>;
|
|
76
|
+
remove: EntrypointProtocol<{
|
|
77
|
+
params: BotIdParams;
|
|
78
|
+
}, BotRemoveResult>;
|
|
79
|
+
/** Mock transport only — a live connection answers `BotTransportMismatch` (409). */
|
|
80
|
+
simulate: EntrypointProtocol<{
|
|
81
|
+
params: BotIdParams;
|
|
82
|
+
body: BotSimulateInput;
|
|
83
|
+
}, BotSimulateResult>;
|
|
84
|
+
};
|
|
85
|
+
rule: {
|
|
86
|
+
list: EntrypointProtocol<{
|
|
87
|
+
query: BotRuleListQuery;
|
|
88
|
+
}, BotRule[]>;
|
|
89
|
+
save: EntrypointProtocol<{
|
|
90
|
+
body: BotRuleInput;
|
|
91
|
+
}, BotRule>;
|
|
92
|
+
remove: EntrypointProtocol<{
|
|
93
|
+
params: BotIdParams;
|
|
94
|
+
}, BotRemoveResult>;
|
|
95
|
+
};
|
|
96
|
+
activity: {
|
|
97
|
+
/** Newest first. */
|
|
98
|
+
list: EntrypointProtocol<{
|
|
99
|
+
query: BotActivityQuery;
|
|
100
|
+
}, BotActivity[]>;
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/** The platforms' inbound surface — no guard: the platform signs. */
|
|
104
|
+
export interface BotHookProtocols {
|
|
105
|
+
base: EntrypointProtocol<OpenRequest, OpenValue>;
|
|
106
|
+
receive: EntrypointProtocol<{
|
|
107
|
+
params: BotHookParams;
|
|
108
|
+
body: BotHookPayload;
|
|
109
|
+
}, BotHookReply>;
|
|
110
|
+
challenge: EntrypointProtocol<{
|
|
111
|
+
params: BotHookParams;
|
|
112
|
+
query: BotChallengeQuery;
|
|
113
|
+
}, string>;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/protocols/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AACtF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EACV,WAAW,EAAE,aAAa,EAAE,kBAAkB,EAAE,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAC3G,MAAM,aAAa,CAAA;AAEpB,oGAAoG;AACpG,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,+EAA+E;AAC/E,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAA;CACpC;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,cAAc,CAAA;IACpB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAA;IACnC,uFAAuF;IACvF,KAAK,CAAC,EAAE,cAAc,CAAA;CACvB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,cAAc,CAAA;CACrB;AAED,uCAAuC;AACvC,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;CACX;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;CACX;AAED,MAAM,WAAW,gBAAgB;IAC/B,8FAA8F;IAC9F,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,WAAW,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,qGAAqG;AACrG,MAAM,WAAW,cAAc;IAC7B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,yGAAyG;AACzG,MAAM,WAAW,YAAY;IAC3B,EAAE,CAAC,EAAE,OAAO,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,mGAAmG;AACnG,MAAM,WAAW,iBAAiB;IAChC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,8DAA8D;AAC9D,MAAM,WAAW,YAAY;IAC3B,kEAAkE;IAClE,IAAI,EAAE,kBAAkB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;IAChD,UAAU,EAAE;QACV,IAAI,EAAE,kBAAkB,CAAC,EAAE,EAAE,aAAa,EAAE,CAAC,CAAA;QAC7C,IAAI,EAAE,kBAAkB,CAAC;YAAE,IAAI,EAAE,kBAAkB,CAAA;SAAE,EAAE,aAAa,CAAC,CAAA;QACrE,MAAM,EAAE,kBAAkB,CAAC;YAAE,MAAM,EAAE,WAAW,CAAA;SAAE,EAAE,aAAa,CAAC,CAAA;QAClE,MAAM,EAAE,kBAAkB,CAAC;YAAE,MAAM,EAAE,WAAW,CAAA;SAAE,EAAE,eAAe,CAAC,CAAA;QACpE,oFAAoF;QACpF,QAAQ,EAAE,kBAAkB,CAAC;YAAE,MAAM,EAAE,WAAW,CAAC;YAAC,IAAI,EAAE,gBAAgB,CAAA;SAAE,EAAE,iBAAiB,CAAC,CAAA;KACjG,CAAA;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,kBAAkB,CAAC;YAAE,KAAK,EAAE,gBAAgB,CAAA;SAAE,EAAE,OAAO,EAAE,CAAC,CAAA;QAChE,IAAI,EAAE,kBAAkB,CAAC;YAAE,IAAI,EAAE,YAAY,CAAA;SAAE,EAAE,OAAO,CAAC,CAAA;QACzD,MAAM,EAAE,kBAAkB,CAAC;YAAE,MAAM,EAAE,WAAW,CAAA;SAAE,EAAE,eAAe,CAAC,CAAA;KACrE,CAAA;IACD,QAAQ,EAAE;QACR,oBAAoB;QACpB,IAAI,EAAE,kBAAkB,CAAC;YAAE,KAAK,EAAE,gBAAgB,CAAA;SAAE,EAAE,WAAW,EAAE,CAAC,CAAA;KACrE,CAAA;CACF;AAED,qEAAqE;AACrE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,kBAAkB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;IAChD,OAAO,EAAE,kBAAkB,CAAC;QAAE,MAAM,EAAE,aAAa,CAAC;QAAC,IAAI,EAAE,cAAc,CAAA;KAAE,EAAE,YAAY,CAAC,CAAA;IAC1F,SAAS,EAAE,kBAAkB,CAAC;QAAE,MAAM,EAAE,aAAa,CAAC;QAAC,KAAK,EAAE,iBAAiB,CAAA;KAAE,EAAE,MAAM,CAAC,CAAA;CAC3F"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/protocols/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { BotHookProtocolOptions, BotHookProtocols, BotProtocolOptions, BotProtocols } from './protocols/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Declare one managing surface of the bot — connections, rules, activity — as an immutable tree a
|
|
4
|
+
* server binds and a client calls.
|
|
5
|
+
*
|
|
6
|
+
* Every leaf hangs under ONE base that carries the guards and the gate, so they cannot drift apart;
|
|
7
|
+
* aliases derive from `opts.base.alias` (`<alias>:connection:list` …). A target declares one tree per
|
|
8
|
+
* area that runs bots (`api:bot:operator`, `api:bot:member`) — the same leaves, another gate.
|
|
9
|
+
*/
|
|
10
|
+
export declare const makeBotProtocols: (opts: BotProtocolOptions) => BotProtocols;
|
|
11
|
+
/**
|
|
12
|
+
* Declare the platforms' inbound surface: `receive` (POST) and `challenge` (GET) at
|
|
13
|
+
* `/:platform/:connection` under the base.
|
|
14
|
+
*
|
|
15
|
+
* NO guard and no gate, by design: the caller is the platform, and it proves itself by signing the
|
|
16
|
+
* request (Telegram's secret token, WhatsApp's app-secret HMAC, Slack's signing secret), which the
|
|
17
|
+
* server verifies against the connection's credentials. The body carries no schema — the signature
|
|
18
|
+
* covers the raw bytes, and the payload is the platform's own.
|
|
19
|
+
*/
|
|
20
|
+
export declare const makeBotHookProtocols: (opts: BotHookProtocolOptions) => BotHookProtocols;
|
|
21
|
+
//# sourceMappingURL=protocols.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocols.d.ts","sourceRoot":"","sources":["../src/protocols.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAC0E,sBAAsB,EAC1G,gBAAgB,EAA6B,kBAAkB,EAAE,YAAY,EAC9E,MAAM,sBAAsB,CAAA;AAU7B;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,SAAU,kBAAkB,KAAG,YA4D3D,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,SAAU,sBAAsB,KAAG,gBAqBnE,CAAA"}
|