@messenger-box/platform-server 10.0.3-alpha.196 → 10.0.3-alpha.201
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/lib/channels/ack-reactions.d.ts +46 -0
- package/lib/channels/ack-reactions.js +48 -0
- package/lib/channels/ack-reactions.js.map +1 -0
- package/lib/channels/allowlist-match.d.ts +38 -0
- package/lib/channels/allowlist-match.js +67 -0
- package/lib/channels/allowlist-match.js.map +1 -0
- package/lib/channels/channel-config.d.ts +46 -0
- package/lib/channels/channel-config.js +63 -0
- package/lib/channels/channel-config.js.map +1 -0
- package/lib/channels/command-gating.d.ts +47 -0
- package/lib/channels/command-gating.js +52 -0
- package/lib/channels/command-gating.js.map +1 -0
- package/lib/channels/conversation-label.d.ts +23 -0
- package/lib/channels/conversation-label.js +43 -0
- package/lib/channels/conversation-label.js.map +1 -0
- package/lib/channels/index.d.ts +18 -0
- package/lib/channels/mention-gating.d.ts +50 -0
- package/lib/channels/mention-gating.js +72 -0
- package/lib/channels/mention-gating.js.map +1 -0
- package/lib/channels/registry.d.ts +23 -0
- package/lib/channels/registry.js +282 -0
- package/lib/channels/registry.js.map +1 -0
- package/lib/channels/sender-identity.d.ts +11 -0
- package/lib/channels/sender-identity.js +48 -0
- package/lib/channels/sender-identity.js.map +1 -0
- package/lib/channels/session.d.ts +63 -0
- package/lib/channels/session.js +29 -0
- package/lib/channels/session.js.map +1 -0
- package/lib/channels/types.d.ts +147 -0
- package/lib/channels/types.js +28 -0
- package/lib/channels/types.js.map +1 -0
- package/lib/channels/typing.d.ts +62 -0
- package/lib/channels/typing.js +37 -0
- package/lib/channels/typing.js.map +1 -0
- package/lib/channels/typing.test.d.ts +1 -0
- package/lib/constants/default-channel-props.d.ts +11 -0
- package/lib/constants/default-channel-props.js +32 -0
- package/lib/constants/default-channel-props.js.map +1 -0
- package/lib/constants/index.d.ts +1 -0
- package/lib/containers/containers.js +5 -1
- package/lib/containers/containers.js.map +1 -1
- package/lib/containers/context-services-from-container.js +3 -3
- package/lib/containers/context-services-from-container.js.map +1 -1
- package/lib/gateway/channel-registry.d.ts +10 -0
- package/lib/gateway/gateway-service.d.ts +23 -0
- package/lib/gateway/index.d.ts +4 -0
- package/lib/gateway/message-router.d.ts +20 -0
- package/lib/gateway/types.d.ts +270 -0
- package/lib/graphql/resolvers/channel-capabilities.d.ts +13 -0
- package/lib/graphql/resolvers/channel-capabilities.js +179 -0
- package/lib/graphql/resolvers/channel-capabilities.js.map +1 -0
- package/lib/graphql/resolvers/channel.js +15 -6
- package/lib/graphql/resolvers/channel.js.map +1 -1
- package/lib/graphql/resolvers/chat-configuration.d.ts +59 -0
- package/lib/graphql/resolvers/chat-configuration.js +89 -0
- package/lib/graphql/resolvers/chat-configuration.js.map +1 -0
- package/lib/graphql/resolvers/gateway.d.ts +18 -0
- package/lib/graphql/resolvers/index.d.ts +52 -1
- package/lib/graphql/resolvers/index.js +1 -1
- package/lib/graphql/resolvers/index.js.map +1 -1
- package/lib/graphql/resolvers/post.js +5 -2
- package/lib/graphql/resolvers/post.js.map +1 -1
- package/lib/graphql/resolvers/streaming.d.ts +20 -0
- package/lib/graphql/resolvers/streaming.js +147 -0
- package/lib/graphql/resolvers/streaming.js.map +1 -0
- package/lib/graphql/schema/channel-capabilities.graphql +492 -0
- package/lib/graphql/schema/channel-capabilities.graphql.js +1 -0
- package/lib/graphql/schema/channel-capabilities.graphql.js.map +1 -0
- package/lib/graphql/schema/channel.graphql +14 -2
- package/lib/graphql/schema/channel.graphql.js +1 -1
- package/lib/graphql/schema/chat-configuration.graphql +77 -0
- package/lib/graphql/schema/chat-configuration.graphql.js +1 -0
- package/lib/graphql/schema/chat-configuration.graphql.js.map +1 -0
- package/lib/graphql/schema/gateway.graphql +363 -0
- package/lib/graphql/schema/index.js +2 -2
- package/lib/graphql/schema/index.js.map +1 -1
- package/lib/graphql/schema/preferences.graphql +190 -3
- package/lib/graphql/schema/preferences.graphql.js +1 -1
- package/lib/graphql/schema/streaming.graphql +224 -0
- package/lib/graphql/schema/streaming.graphql.js +1 -0
- package/lib/graphql/schema/streaming.graphql.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/migrations/dbMigrations/AddChannelConfigurationsMigration.d.ts +42 -0
- package/lib/migrations/dbMigrations/AddChannelConfigurationsMigration.js +60 -0
- package/lib/migrations/dbMigrations/AddChannelConfigurationsMigration.js.map +1 -0
- package/lib/migrations/dbMigrations/AddChatConfigurationsMigration.d.ts +21 -0
- package/lib/migrations/dbMigrations/AddChatConfigurationsMigration.js +30 -0
- package/lib/migrations/dbMigrations/AddChatConfigurationsMigration.js.map +1 -0
- package/lib/migrations/dbMigrations/AddPostsConfigurationsMigration.js +1 -1
- package/lib/migrations/dbMigrations/index.d.ts +2 -0
- package/lib/preferences/settings/channel-settings.d.ts +39 -0
- package/lib/preferences/settings/channel-settings.js +180 -0
- package/lib/preferences/settings/channel-settings.js.map +1 -0
- package/lib/preferences/settings/chat-settings.d.ts +248 -0
- package/lib/preferences/settings/chat-settings.js +1152 -0
- package/lib/preferences/settings/chat-settings.js.map +1 -0
- package/lib/preferences/settings/index.d.ts +3 -0
- package/lib/preferences/settings/messenger-channels-contribution.d.ts +39 -0
- package/lib/preferences/settings/messenger-channels-contribution.js +355 -0
- package/lib/preferences/settings/messenger-channels-contribution.js.map +1 -0
- package/lib/preferences/settings/post-settings.d.ts +14 -0
- package/lib/preferences/settings/post-settings.js +59 -1
- package/lib/preferences/settings/post-settings.js.map +1 -1
- package/lib/services/channel-service.js +46 -5
- package/lib/services/channel-service.js.map +1 -1
- package/lib/services/post-service.d.ts +23 -0
- package/lib/services/post-service.js +77 -1
- package/lib/services/post-service.js.map +1 -1
- package/lib/store/models/channel.js +21 -2
- package/lib/store/models/channel.js.map +1 -1
- package/lib/store/models/post.js.map +1 -1
- package/lib/streaming/block-chunker.d.ts +40 -0
- package/lib/streaming/block-chunker.js +103 -0
- package/lib/streaming/block-chunker.js.map +1 -0
- package/lib/streaming/block-chunker.test.d.ts +1 -0
- package/lib/streaming/index.d.ts +4 -0
- package/lib/streaming/stream-service.d.ts +71 -0
- package/lib/streaming/stream-service.js +325 -0
- package/lib/streaming/stream-service.js.map +1 -0
- package/lib/streaming/stream-service.test.d.ts +16 -0
- package/lib/streaming/streaming-post.integration.test.d.ts +10 -0
- package/lib/streaming/types.d.ts +33 -0
- package/lib/streaming/types.js +37 -0
- package/lib/streaming/types.js.map +1 -0
- package/lib/templates/constants/CONTRIBUTION_POINTS.ts.template +78 -0
- package/lib/templates/constants/SERVER_TYPES.ts.template +1 -0
- package/lib/templates/services/MessengerStreamService.ts.template +131 -0
- package/lib/templates/services/PostService.ts.template +12 -0
- package/package.json +4 -3
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ack Reactions system - inspired by openclaw's ack-reactions,
|
|
3
|
+
* adapted to messenger-box's Props architecture.
|
|
4
|
+
*
|
|
5
|
+
* Provides scoped acknowledgement reactions for posts/messages,
|
|
6
|
+
* supporting different behaviors for direct messages, groups,
|
|
7
|
+
* and mention-based triggers.
|
|
8
|
+
*/
|
|
9
|
+
export type AckReactionScope = 'all' | 'direct' | 'group-all' | 'group-mentions' | 'off' | 'none';
|
|
10
|
+
export interface IAckReactionProps {
|
|
11
|
+
/** Whether ack reactions are enabled */
|
|
12
|
+
enabled: boolean;
|
|
13
|
+
/** Default emoji for acknowledgement */
|
|
14
|
+
defaultEmoji: string;
|
|
15
|
+
/** Scope of ack reactions */
|
|
16
|
+
scope: AckReactionScope;
|
|
17
|
+
/** Whether to remove the ack reaction after reply */
|
|
18
|
+
removeAfterReply: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare const DEFAULT_ACK_REACTION_PROPS: IAckReactionProps;
|
|
21
|
+
export interface IAckReactionGateParams {
|
|
22
|
+
scope: AckReactionScope | undefined;
|
|
23
|
+
isDirect: boolean;
|
|
24
|
+
isGroup: boolean;
|
|
25
|
+
isMentionableGroup: boolean;
|
|
26
|
+
requireMention: boolean;
|
|
27
|
+
canDetectMention: boolean;
|
|
28
|
+
effectiveWasMentioned: boolean;
|
|
29
|
+
shouldBypassMention?: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Determines whether an ack reaction should be sent based on scope and context
|
|
33
|
+
* (mirrors openclaw's shouldAckReaction)
|
|
34
|
+
*/
|
|
35
|
+
export declare function shouldAckReaction(params: IAckReactionGateParams): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Handles removing an ack reaction after a reply has been sent
|
|
38
|
+
* (mirrors openclaw's removeAckReactionAfterReply)
|
|
39
|
+
*/
|
|
40
|
+
export declare function removeAckReactionAfterReply(params: {
|
|
41
|
+
removeAfterReply: boolean;
|
|
42
|
+
ackReactionPromise: Promise<boolean> | null;
|
|
43
|
+
ackReactionValue: string | null;
|
|
44
|
+
remove: () => Promise<void>;
|
|
45
|
+
onError?: (err: unknown) => void;
|
|
46
|
+
}): void;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ack Reactions system - inspired by openclaw's ack-reactions,
|
|
3
|
+
* adapted to messenger-box's Props architecture.
|
|
4
|
+
*
|
|
5
|
+
* Provides scoped acknowledgement reactions for posts/messages,
|
|
6
|
+
* supporting different behaviors for direct messages, groups,
|
|
7
|
+
* and mention-based triggers.
|
|
8
|
+
*/
|
|
9
|
+
const DEFAULT_ACK_REACTION_PROPS = {
|
|
10
|
+
enabled: false,
|
|
11
|
+
defaultEmoji: '👀',
|
|
12
|
+
scope: 'group-mentions',
|
|
13
|
+
removeAfterReply: true
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Determines whether an ack reaction should be sent based on scope and context
|
|
17
|
+
* (mirrors openclaw's shouldAckReaction)
|
|
18
|
+
*/
|
|
19
|
+
function shouldAckReaction(params) {
|
|
20
|
+
const scope = params.scope ?? 'group-mentions';
|
|
21
|
+
if (scope === 'off' || scope === 'none') return false;
|
|
22
|
+
if (scope === 'all') return true;
|
|
23
|
+
if (scope === 'direct') return params.isDirect;
|
|
24
|
+
if (scope === 'group-all') return params.isGroup;
|
|
25
|
+
if (scope === 'group-mentions') {
|
|
26
|
+
if (!params.isMentionableGroup) return false;
|
|
27
|
+
if (!params.requireMention) return false;
|
|
28
|
+
if (!params.canDetectMention) return false;
|
|
29
|
+
return params.effectiveWasMentioned || params.shouldBypassMention === true;
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
// Ack Reaction Lifecycle
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
/**
|
|
37
|
+
* Handles removing an ack reaction after a reply has been sent
|
|
38
|
+
* (mirrors openclaw's removeAckReactionAfterReply)
|
|
39
|
+
*/
|
|
40
|
+
function removeAckReactionAfterReply(params) {
|
|
41
|
+
if (!params.removeAfterReply) return;
|
|
42
|
+
if (!params.ackReactionPromise) return;
|
|
43
|
+
if (!params.ackReactionValue) return;
|
|
44
|
+
void params.ackReactionPromise.then(didAck => {
|
|
45
|
+
if (!didAck) return;
|
|
46
|
+
params.remove().catch(err => params.onError?.(err));
|
|
47
|
+
});
|
|
48
|
+
}export{DEFAULT_ACK_REACTION_PROPS,removeAckReactionAfterReply,shouldAckReaction};//# sourceMappingURL=ack-reactions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ack-reactions.js","sources":["../../src/channels/ack-reactions.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA;;;;;;;AAOG;AAmBI,MAAM,0BAA0B,GAAsB;AACzD,EAAA,OAAA,EAAO,KAAE;AACT,EAAA,YAAA,EAAY,IAAE;AACd,EAAA,KAAA,EAAK,gBAAE;AACP,EAAA,gBAAA,EAAgB;;AAkBpB;;;AAGG;AACG,SAAU,iBAAiB,CAAC,MAA8B,EAAA;AAC5D,EAAA,MAAA,QAAW,MAAG,CAAA,KAAO,IAAK;AAC1B,EAAA,IAAA,UAAS,KAAK,IAAK,KAAI,WAAU,EAAM,OAAA,KAAA;AAAE,EAAA,IAAA,KAAA,UAAa,EAAA,OAAA,IAAA;MACtD,KAAI,aAAe,EAAA,OAAA,MAAA,CAAA,QAAA;AAAE,EAAA,IAAA,KAAA,gBAAY,EAAA,OAAA,MAAA,CAAA,OAAA;MACjC,KAAI,qBAAkB,EAAA;QAAE,CAAA,MAAO,CAAA,kBAAgB,EAAA,OAAA,KAAA;IAC/C,IAAI,CAAA,qBAAqB,EAAA,OAAA,KAAA;QAAE,CAAA,MAAO,CAAA,gBAAe,EAAA,OAAA,KAAA;AACjD,IAAA,OAAI,MAAK,CAAK,qBAAmB,IAAA,MAAA,CAAA,mBAAA,KAAA,IAAA;;AACG,EAAA,OAAA,KAAA;;AACJ;;AACE;;;AAGlC;AACJ;AAEA,SAAA,2BAAA,CAAA,MAAA,EAAA;AACA,EAAA,IAAA,CAAA,MAAA,CAAA,gBAAyB,EAAA;AACzB,EAAA,IAAA,CAAA,MAAA,CAAA,kBAAA,EAAA;AAEA,EAAA,IAAA,CAAA,MAAA,CAAA,gBAAA,EAAA;;;AAGG,IAAA,MAAA,CAAA,MAAA,EAAA,CAAA,KAAA,CAAA,GAAA,IAAA,MAAA,CAAA,OAAA,GAAA,GAAA,CAAA,CAAA;AACH,EAAA,CAAA,CAAA;"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Allowlist matching - inspired by openclaw's allowlist-match,
|
|
3
|
+
* adapted to messenger-box's Props architecture.
|
|
4
|
+
*
|
|
5
|
+
* Provides user/sender allowlists for channels, enabling
|
|
6
|
+
* per-channel access control with wildcard, ID, name, and
|
|
7
|
+
* username-based matching.
|
|
8
|
+
*/
|
|
9
|
+
export type AllowlistMatchSource = 'wildcard' | 'id' | 'name' | 'tag' | 'username' | 'email' | 'prefixed-id' | 'prefixed-user' | 'prefixed-name';
|
|
10
|
+
export interface IAllowlistMatch<TSource extends string = AllowlistMatchSource> {
|
|
11
|
+
allowed: boolean;
|
|
12
|
+
matchKey?: string;
|
|
13
|
+
matchSource?: TSource;
|
|
14
|
+
}
|
|
15
|
+
export interface IAllowlistProps {
|
|
16
|
+
/** Whether allowlist is enabled */
|
|
17
|
+
enabled: boolean;
|
|
18
|
+
/** List of allowed senders (IDs, names, emails, or '*' for wildcard) */
|
|
19
|
+
allowFrom: Array<string | number>;
|
|
20
|
+
/** Whether to block messages from unknown senders */
|
|
21
|
+
blockUnknown: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare const DEFAULT_ALLOWLIST_PROPS: IAllowlistProps;
|
|
24
|
+
export declare function formatAllowlistMatchMeta(match?: {
|
|
25
|
+
matchKey?: string;
|
|
26
|
+
matchSource?: string;
|
|
27
|
+
} | null): string;
|
|
28
|
+
/**
|
|
29
|
+
* Resolves whether a sender is allowed based on the allowlist
|
|
30
|
+
* (mirrors openclaw's resolveAllowlistMatchSimple)
|
|
31
|
+
*/
|
|
32
|
+
export declare function resolveAllowlistMatch(params: {
|
|
33
|
+
allowFrom: Array<string | number>;
|
|
34
|
+
senderId: string;
|
|
35
|
+
senderName?: string | null;
|
|
36
|
+
senderEmail?: string | null;
|
|
37
|
+
senderUsername?: string | null;
|
|
38
|
+
}): IAllowlistMatch<'wildcard' | 'id' | 'name' | 'email' | 'username'>;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Allowlist matching - inspired by openclaw's allowlist-match,
|
|
3
|
+
* adapted to messenger-box's Props architecture.
|
|
4
|
+
*
|
|
5
|
+
* Provides user/sender allowlists for channels, enabling
|
|
6
|
+
* per-channel access control with wildcard, ID, name, and
|
|
7
|
+
* username-based matching.
|
|
8
|
+
*/
|
|
9
|
+
const DEFAULT_ALLOWLIST_PROPS = {
|
|
10
|
+
enabled: false,
|
|
11
|
+
allowFrom: [],
|
|
12
|
+
blockUnknown: false
|
|
13
|
+
};
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Match Resolution (mirrors openclaw's resolveAllowlistMatchSimple)
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
function formatAllowlistMatchMeta(match) {
|
|
18
|
+
return `matchKey=${match?.matchKey ?? 'none'} matchSource=${match?.matchSource ?? 'none'}`;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Resolves whether a sender is allowed based on the allowlist
|
|
22
|
+
* (mirrors openclaw's resolveAllowlistMatchSimple)
|
|
23
|
+
*/
|
|
24
|
+
function resolveAllowlistMatch(params) {
|
|
25
|
+
const allowFrom = params.allowFrom.map(entry => String(entry).trim().toLowerCase()).filter(Boolean);
|
|
26
|
+
if (allowFrom.length === 0) return {
|
|
27
|
+
allowed: false
|
|
28
|
+
};
|
|
29
|
+
if (allowFrom.includes('*')) return {
|
|
30
|
+
allowed: true,
|
|
31
|
+
matchKey: '*',
|
|
32
|
+
matchSource: 'wildcard'
|
|
33
|
+
};
|
|
34
|
+
const senderId = params.senderId.toLowerCase();
|
|
35
|
+
if (allowFrom.includes(senderId)) return {
|
|
36
|
+
allowed: true,
|
|
37
|
+
matchKey: senderId,
|
|
38
|
+
matchSource: 'id'
|
|
39
|
+
};
|
|
40
|
+
const senderName = params.senderName?.toLowerCase();
|
|
41
|
+
if (senderName && allowFrom.includes(senderName)) {
|
|
42
|
+
return {
|
|
43
|
+
allowed: true,
|
|
44
|
+
matchKey: senderName,
|
|
45
|
+
matchSource: 'name'
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
const senderEmail = params.senderEmail?.toLowerCase();
|
|
49
|
+
if (senderEmail && allowFrom.includes(senderEmail)) {
|
|
50
|
+
return {
|
|
51
|
+
allowed: true,
|
|
52
|
+
matchKey: senderEmail,
|
|
53
|
+
matchSource: 'email'
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const senderUsername = params.senderUsername?.toLowerCase();
|
|
57
|
+
if (senderUsername && allowFrom.includes(senderUsername)) {
|
|
58
|
+
return {
|
|
59
|
+
allowed: true,
|
|
60
|
+
matchKey: senderUsername,
|
|
61
|
+
matchSource: 'username'
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
allowed: false
|
|
66
|
+
};
|
|
67
|
+
}export{DEFAULT_ALLOWLIST_PROPS,formatAllowlistMatchMeta,resolveAllowlistMatch};//# sourceMappingURL=allowlist-match.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"allowlist-match.js","sources":["../../src/channels/allowlist-match.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA;;;;;;;AAOG;AAoCI,MAAM,uBAAuB,GAAoB;AACpD,EAAA,OAAA,EAAO,KAAE;AACT,EAAA,SAAA,EAAS,EAAE;AACX,EAAA,YAAA,EAAY;;AAGhB;AACA;AACA;AAEM,SAAU,wBAAwB,CAAC,KAA0D,EAAA;AAC/F,EAAA,OAAA,CAAA,SAAO,EAAA,KAAY,EAAK,QAAE,IAAQ,MAAI,CAAA,aAAM,EAAA,KAAgB,EAAK,WAAE,IAAW,MAAI,CAAA,CAAM;AAC5F;AAEA;;;AAGG;AACG,SAAU,qBAAqB,CAAC,MAMrC,EAAA;AACG,EAAA,MAAA,SAAM,GAAS,MAAG,CAAA,SAAO,CAAA,GAAU,CAAA,KAAK,IAAK,MAAK,CAAA,KAAO,CAAA,CAAA,IAAO,EAAA,CAAA,WAAO,EAAA,CAAA,CAAW,MAAI,CAAA,OAAO,CAAA;AAE7F,EAAA,IAAA,SAAI,CAAA,MAAU,KAAM,CAAA,EAAM,OAAA;AAAE,IAAA,OAAA,EAAA;AAC5B,GAAA;AAA6B,EAAA,IAAA,SAAO,CAAA,QAAS,CAAA,GAAE,CAAA,EAAI,OAAE;IAErD,OAAM,EAAA,IAAA;AACN,IAAA,QAAI,EAAA,GAAS;AAAqB,IAAA,WAAO,EAAE;;QAGvC,QAAA,SAAc,CAAA,oBAAmB,EAAA;AACjC,EAAA,IAAA,SAAO,CAAA,QAAS,CAAA,QAAQ,CAAA,EAAA,OAAU;IACtC,OAAC,EAAA,IAAA;IAED,QAAM,EAAA;IACN,WAAI,EAAA;AACA,GAAA;QACH,UAAA,GAAA,MAAA,CAAA,UAAA,EAAA,WAAA,EAAA;MAED,UAAM,IAAA,SAAiB,CAAA,mBAAqB,CAAE,EAAA;IAC9C,OAAI;AACA,MAAA,OAAA,EAAO,IAAE;MACZ,QAAA,EAAA,UAAA;AAED,MAAA,WAAS,EAAA;AACb,KAAC;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Channel configuration - inspired by openclaw's channel-config,
|
|
3
|
+
* adapted to messenger-box's Props architecture.
|
|
4
|
+
*
|
|
5
|
+
* Provides channel configuration matching, slug normalization,
|
|
6
|
+
* and entry resolution for per-channel settings.
|
|
7
|
+
*/
|
|
8
|
+
export type ChannelMatchSource = 'direct' | 'parent' | 'wildcard';
|
|
9
|
+
export interface IChannelEntryMatch<T> {
|
|
10
|
+
entry?: T;
|
|
11
|
+
key?: string;
|
|
12
|
+
wildcardEntry?: T;
|
|
13
|
+
wildcardKey?: string;
|
|
14
|
+
parentEntry?: T;
|
|
15
|
+
parentKey?: string;
|
|
16
|
+
matchKey?: string;
|
|
17
|
+
matchSource?: ChannelMatchSource;
|
|
18
|
+
}
|
|
19
|
+
export interface IChannelConfigProps {
|
|
20
|
+
/** Channel-level notification settings override */
|
|
21
|
+
notifyOverride?: 'default' | 'all' | 'mentions' | 'none';
|
|
22
|
+
/** Whether to auto-join the channel */
|
|
23
|
+
autoJoin?: boolean;
|
|
24
|
+
/** Channel priority (higher = more prominent) */
|
|
25
|
+
priority?: number;
|
|
26
|
+
/** Custom channel category */
|
|
27
|
+
category?: string;
|
|
28
|
+
/** Whether channel is archived */
|
|
29
|
+
archived?: boolean;
|
|
30
|
+
/** Whether channel is muted */
|
|
31
|
+
muted?: boolean;
|
|
32
|
+
/** Custom theme for the channel */
|
|
33
|
+
theme?: string;
|
|
34
|
+
}
|
|
35
|
+
export declare const DEFAULT_CHANNEL_CONFIG_PROPS: IChannelConfigProps;
|
|
36
|
+
export declare function normalizeChannelSlug(value: string): string;
|
|
37
|
+
export declare function buildChannelKeyCandidates(...keys: Array<string | undefined | null>): string[];
|
|
38
|
+
export declare function resolveChannelEntryMatch<T>(params: {
|
|
39
|
+
entries?: Record<string, T>;
|
|
40
|
+
keys: string[];
|
|
41
|
+
wildcardKey?: string;
|
|
42
|
+
}): IChannelEntryMatch<T>;
|
|
43
|
+
export declare function applyChannelMatchMeta<TResult extends {
|
|
44
|
+
matchKey?: string;
|
|
45
|
+
matchSource?: ChannelMatchSource;
|
|
46
|
+
}>(result: TResult, match: IChannelEntryMatch<unknown>): TResult;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Channel configuration - inspired by openclaw's channel-config,
|
|
3
|
+
* adapted to messenger-box's Props architecture.
|
|
4
|
+
*
|
|
5
|
+
* Provides channel configuration matching, slug normalization,
|
|
6
|
+
* and entry resolution for per-channel settings.
|
|
7
|
+
*/
|
|
8
|
+
const DEFAULT_CHANNEL_CONFIG_PROPS = {
|
|
9
|
+
notifyOverride: 'default',
|
|
10
|
+
autoJoin: false,
|
|
11
|
+
priority: 0,
|
|
12
|
+
archived: false,
|
|
13
|
+
muted: false
|
|
14
|
+
};
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Channel Slug Normalization (mirrors openclaw's normalizeChannelSlug)
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
function normalizeChannelSlug(value) {
|
|
19
|
+
return value.trim().toLowerCase().replace(/^#/, '').replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
|
|
20
|
+
}
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Channel Key Candidates (mirrors openclaw's buildChannelKeyCandidates)
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
function buildChannelKeyCandidates(...keys) {
|
|
25
|
+
const seen = new Set();
|
|
26
|
+
const candidates = [];
|
|
27
|
+
for (const key of keys) {
|
|
28
|
+
if (typeof key !== 'string') continue;
|
|
29
|
+
const trimmed = key.trim();
|
|
30
|
+
if (!trimmed || seen.has(trimmed)) continue;
|
|
31
|
+
seen.add(trimmed);
|
|
32
|
+
candidates.push(trimmed);
|
|
33
|
+
}
|
|
34
|
+
return candidates;
|
|
35
|
+
}
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// Channel Entry Resolution (mirrors openclaw's resolveChannelEntryMatch)
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
function resolveChannelEntryMatch(params) {
|
|
40
|
+
const entries = params.entries ?? {};
|
|
41
|
+
const match = {};
|
|
42
|
+
for (const key of params.keys) {
|
|
43
|
+
if (!Object.prototype.hasOwnProperty.call(entries, key)) continue;
|
|
44
|
+
match.entry = entries[key];
|
|
45
|
+
match.key = key;
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
if (params.wildcardKey && Object.prototype.hasOwnProperty.call(entries, params.wildcardKey)) {
|
|
49
|
+
match.wildcardEntry = entries[params.wildcardKey];
|
|
50
|
+
match.wildcardKey = params.wildcardKey;
|
|
51
|
+
}
|
|
52
|
+
return match;
|
|
53
|
+
}
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// Match Metadata Application
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
function applyChannelMatchMeta(result, match) {
|
|
58
|
+
if (match.matchKey && match.matchSource) {
|
|
59
|
+
result.matchKey = match.matchKey;
|
|
60
|
+
result.matchSource = match.matchSource;
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
}export{DEFAULT_CHANNEL_CONFIG_PROPS,applyChannelMatchMeta,buildChannelKeyCandidates,normalizeChannelSlug,resolveChannelEntryMatch};//# sourceMappingURL=channel-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel-config.js","sources":["../../src/channels/channel-config.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA;;;;;;AAMG;AAwCI,MAAM,4BAA4B,GAAwB;AAC7D,EAAA,cAAA,EAAc,SAAE;AAChB,EAAA,QAAA,EAAQ,KAAE;AACV,EAAA,QAAA,EAAQ;AACR,EAAA,QAAA,EAAQ,KAAE;AACV,EAAA,KAAA,EAAK;;AAGT;AACA;AACA;AAEM,SAAU,oBAAoB,CAAC,KAAa,EAAA;AAC9C,EAAA,OAAA,KAAO,CAAA,IAAK,EAAA,CAAA,WAAA,EAAA,CAAA,OAAA,CAAA,IAAA,EAAA,EAAA,CAAA,CAAA,OAAA,CAAA,aAAA,EAAA,GAAA,CAAA,CAAA,OAAA,CAAA,UAAA,EAAA,EAAA,CAAA;AACP;AACA;AACA;AACA;AACA,SAAO,yBAAiB,CAAA,GAAA,IAAA,EAAA;AACjC,EAAC,MAAA,IAAA,GAAA,IAAA,GAAA,EAAA;AAED,EAAA,MAAA,UAAA,GAAA,EAAA;AACA,EAAA,KAAA,MAAA,GAAA,IAAA,IAAA,EAAA;AACA,IAAA,IAAA,OAAA,GAAA,KAAA,QAAA,EAAA;AAEA,IAAA,MAAM,OAAU,GAAA,GAAA,CAAA,IAAA,EAAA;AACZ,IAAA,IAAA,CAAA,OAAU,IAAG,IAAO,IAAW,CAAA,OAAA,CAAA,EAAA;IAC/B,IAAA,CAAA,GAAM,CAAA,OAAU,CAAA;AAChB,IAAA,UAAK,CAAM,IAAG,CAAA,QAAU;;mBACS;AAC7B;;;AAEA;AACA,SAAA,wBAAyB,CAAA,MAAA,EAAA;QAC5B,OAAA,GAAA,MAAA,CAAA,OAAA,IAAA,EAAA;AACD,EAAA,MAAA;AACJ,EAAC,KAAA,MAAA,GAAA,IAAA,MAAA,CAAA,IAAA,EAAA;AAED,IAAA,IAAA,CAAA,MAAA,CAAA,SAAA,CAAA,cAAA,CAAA,IAAA,CAAA,OAAA,EAAA,GAAA,CAAA,EAAA;AACA,IAAA,KAAA,CAAA,KAAA,GAAA,OAAA,CAAA,GAAA,CAAA;AACA,IAAA,KAAA,CAAA,GAAA,GAAA,GAAA;AAEA,IAAA;AAKI,EAAA;MACA,MAAM,CAAA,WAAkC,IAAA,MAAA,CAAA,SAAA,CAAA,cAAA,CAAA,IAAA,CAAA,OAAA,EAAA,MAAA,CAAA,WAAA,CAAA,EAAA;AAExC,IAAA,KAAK,wBAAwB,OAAG,CAAA,WAAA,CAAA;AAC5B,IAAA,KAAA,CAAA,WAAY,GAAA,MAAU,CAAA,WAAA;;AACtB,EAAA,OAAA,KAAM;AACN;;;AAIJ;8BACiC,CAAC,MAAM,EAAC,KAAA,EAAA;AACrC,EAAA,IAAA,KAAA,CAAA,QAAM,IAAA,KAAc,CAAA;IACxB,MAAC,CAAA,QAAA,GAAA,KAAA,CAAA,QAAA;AAED,IAAA,MAAA,CAAO,WAAM,GAAA,KAAA,CAAA,WAAA;AACjB,EAAC;AAED,EAAA,OAAA,MAAA;AACA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command gating - inspired by openclaw's command-gating,
|
|
3
|
+
* adapted to messenger-box's Props architecture.
|
|
4
|
+
*
|
|
5
|
+
* Provides access control for commands within channels, supporting
|
|
6
|
+
* access groups, per-user authorization, and text command filtering.
|
|
7
|
+
*/
|
|
8
|
+
export interface ICommandAuthorizer {
|
|
9
|
+
configured: boolean;
|
|
10
|
+
allowed: boolean;
|
|
11
|
+
}
|
|
12
|
+
export type CommandGatingMode = 'allow' | 'deny' | 'configured';
|
|
13
|
+
export interface ICommandGatingProps {
|
|
14
|
+
/** Whether text commands are allowed */
|
|
15
|
+
allowTextCommands: boolean;
|
|
16
|
+
/** Whether access groups are used for authorization */
|
|
17
|
+
useAccessGroups: boolean;
|
|
18
|
+
/** Default mode when access groups are off */
|
|
19
|
+
modeWhenAccessGroupsOff: CommandGatingMode;
|
|
20
|
+
/** List of allowed command prefixes */
|
|
21
|
+
allowedPrefixes: string[];
|
|
22
|
+
/** List of blocked commands */
|
|
23
|
+
blockedCommands: string[];
|
|
24
|
+
}
|
|
25
|
+
export declare const DEFAULT_COMMAND_GATING_PROPS: ICommandGatingProps;
|
|
26
|
+
/**
|
|
27
|
+
* Resolves whether a command is authorized based on authorizers and config
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolveCommandAuthorized(params: {
|
|
30
|
+
useAccessGroups: boolean;
|
|
31
|
+
authorizers: ICommandAuthorizer[];
|
|
32
|
+
modeWhenAccessGroupsOff?: CommandGatingMode;
|
|
33
|
+
}): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Resolves whether a control command should be blocked
|
|
36
|
+
* (mirrors openclaw's resolveControlCommandGate)
|
|
37
|
+
*/
|
|
38
|
+
export declare function resolveControlCommandGate(params: {
|
|
39
|
+
useAccessGroups: boolean;
|
|
40
|
+
authorizers: ICommandAuthorizer[];
|
|
41
|
+
allowTextCommands: boolean;
|
|
42
|
+
hasControlCommand: boolean;
|
|
43
|
+
modeWhenAccessGroupsOff?: CommandGatingMode;
|
|
44
|
+
}): {
|
|
45
|
+
commandAuthorized: boolean;
|
|
46
|
+
shouldBlock: boolean;
|
|
47
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command gating - inspired by openclaw's command-gating,
|
|
3
|
+
* adapted to messenger-box's Props architecture.
|
|
4
|
+
*
|
|
5
|
+
* Provides access control for commands within channels, supporting
|
|
6
|
+
* access groups, per-user authorization, and text command filtering.
|
|
7
|
+
*/
|
|
8
|
+
const DEFAULT_COMMAND_GATING_PROPS = {
|
|
9
|
+
allowTextCommands: true,
|
|
10
|
+
useAccessGroups: false,
|
|
11
|
+
modeWhenAccessGroupsOff: 'allow',
|
|
12
|
+
allowedPrefixes: ['/'],
|
|
13
|
+
blockedCommands: []
|
|
14
|
+
};
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Authorization Resolution (mirrors openclaw's resolveCommandAuthorizedFromAuthorizers)
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
/**
|
|
19
|
+
* Resolves whether a command is authorized based on authorizers and config
|
|
20
|
+
*/
|
|
21
|
+
function resolveCommandAuthorized(params) {
|
|
22
|
+
const {
|
|
23
|
+
useAccessGroups,
|
|
24
|
+
authorizers
|
|
25
|
+
} = params;
|
|
26
|
+
const mode = params.modeWhenAccessGroupsOff ?? 'allow';
|
|
27
|
+
if (!useAccessGroups) {
|
|
28
|
+
if (mode === 'allow') return true;
|
|
29
|
+
if (mode === 'deny') return false;
|
|
30
|
+
// mode === 'configured'
|
|
31
|
+
const anyConfigured = authorizers.some(entry => entry.configured);
|
|
32
|
+
if (!anyConfigured) return true;
|
|
33
|
+
return authorizers.some(entry => entry.configured && entry.allowed);
|
|
34
|
+
}
|
|
35
|
+
return authorizers.some(entry => entry.configured && entry.allowed);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Resolves whether a control command should be blocked
|
|
39
|
+
* (mirrors openclaw's resolveControlCommandGate)
|
|
40
|
+
*/
|
|
41
|
+
function resolveControlCommandGate(params) {
|
|
42
|
+
const commandAuthorized = resolveCommandAuthorized({
|
|
43
|
+
useAccessGroups: params.useAccessGroups,
|
|
44
|
+
authorizers: params.authorizers,
|
|
45
|
+
modeWhenAccessGroupsOff: params.modeWhenAccessGroupsOff
|
|
46
|
+
});
|
|
47
|
+
const shouldBlock = params.allowTextCommands && params.hasControlCommand && !commandAuthorized;
|
|
48
|
+
return {
|
|
49
|
+
commandAuthorized,
|
|
50
|
+
shouldBlock
|
|
51
|
+
};
|
|
52
|
+
}export{DEFAULT_COMMAND_GATING_PROPS,resolveCommandAuthorized,resolveControlCommandGate};//# sourceMappingURL=command-gating.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-gating.js","sources":["../../src/channels/command-gating.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA;;;;;;AAMG;AA8BI,MAAM,4BAA4B,GAAwB;AAC7D,EAAA,iBAAA,EAAiB,IAAE;AACnB,EAAA,eAAA,EAAe,KAAE;AACjB,EAAA,uBAAA,EAAuB,OAAE;iBACzB,EAAe,CAAA,GAAG,CAAA;AAClB,EAAA,eAAA,EAAe;;AAGnB;AACA;AACA;AAEA;;AAEG;AACG,SAAU,wBAAwB,CAAC,MAIxC,EAAA;AACG,EAAA,MAAA;AACA,IAAA,eAAa;IAEb;YACQ;AAAkB,EAAA,MAAA,IAAA,GAAA,8BAAY,IAAA,OAAA;sBACrB,EAAA;AAAQ,IAAA,IAAA,IAAA,KAAA,OAAY,EAAC,OAAA,IAAA;QAClC,IAAA,KAAA,MAAA,EAAA,OAAwB,KAAA;AACxB;AACA,IAAA,MAAA,aAAK,GAAa,WAAA,CAAA,IAAA,CAAA,KAAA,IAAA,KAAA,CAAA,UAAA,CAAA;AAAE,IAAA,IAAA,CAAA,eAAY,OAAA,IAAA;AAChC,IAAA,OAAA,gBAAmB,CAAA,KAAM,SAAS,CAAC,UAAM,IAAA,KAAU,CAAI,OAAM,CAAA;;AAGjE,EAAA,OAAA,gBAAmB,CAAA,SAAW,KAAK,CAAA,UAAM,IAAU,aAAU,CAAA;AACjE;AAEA;;;AAGG;AACG,SAAU,yBAAyB,CAAC,MAMzC,EAAA;QACG,iBAAM,GAAiB,wBAAG,CAAA;mBACtB,EAAA,MAAiB,CAAA,eAAO;eACxB,EAAA,MAAa,CAAA,WAAO;2BACpB,EAAA,MAAyB,CAAA;AAC5B,GAAA,CAAA;AAED,EAAA,MAAA,WAAM,GAAW,MAAG,CAAA,iBAAO,IAAiB,MAAI,CAAA,iBAAO,IAAiB,CAAA,iBAAK;AAC7E,EAAA,OAAA;AACJ,IAAC,iBAAA;;;"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface IConversationContext {
|
|
2
|
+
/** Explicit conversation label override */
|
|
3
|
+
conversationLabel?: string;
|
|
4
|
+
/** Thread label */
|
|
5
|
+
threadLabel?: string;
|
|
6
|
+
/** Chat type (direct, group, channel, thread) */
|
|
7
|
+
chatType?: string;
|
|
8
|
+
/** Sender name */
|
|
9
|
+
senderName?: string;
|
|
10
|
+
/** From identifier */
|
|
11
|
+
from?: string;
|
|
12
|
+
/** Group channel name */
|
|
13
|
+
groupChannel?: string;
|
|
14
|
+
/** Group subject */
|
|
15
|
+
groupSubject?: string;
|
|
16
|
+
/** Channel title */
|
|
17
|
+
channelTitle?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Resolves a human-readable conversation label from context
|
|
21
|
+
* (mirrors openclaw's resolveConversationLabel)
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolveConversationLabel(ctx: IConversationContext): string | undefined;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {normalizeChatType}from'./types.js';/**
|
|
2
|
+
* Conversation label resolution - inspired by openclaw's conversation-label,
|
|
3
|
+
* adapted to messenger-box's domain model.
|
|
4
|
+
*
|
|
5
|
+
* Resolves human-readable labels for conversations from channel/post context,
|
|
6
|
+
* handling direct messages, groups, threads, and public channels.
|
|
7
|
+
*/
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Label Resolution
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
function extractConversationId(from) {
|
|
12
|
+
const trimmed = from?.trim();
|
|
13
|
+
if (!trimmed) return undefined;
|
|
14
|
+
const parts = trimmed.split(':').filter(Boolean);
|
|
15
|
+
return parts.length > 0 ? parts[parts.length - 1] : trimmed;
|
|
16
|
+
}
|
|
17
|
+
function shouldAppendId(id) {
|
|
18
|
+
// Append numeric IDs or special identifiers
|
|
19
|
+
if (/^[0-9]+$/.test(id)) return true;
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Resolves a human-readable conversation label from context
|
|
24
|
+
* (mirrors openclaw's resolveConversationLabel)
|
|
25
|
+
*/
|
|
26
|
+
function resolveConversationLabel(ctx) {
|
|
27
|
+
const explicit = ctx.conversationLabel?.trim();
|
|
28
|
+
if (explicit) return explicit;
|
|
29
|
+
const threadLabel = ctx.threadLabel?.trim();
|
|
30
|
+
if (threadLabel) return threadLabel;
|
|
31
|
+
const chatType = normalizeChatType(ctx.chatType);
|
|
32
|
+
if (chatType === 'direct') {
|
|
33
|
+
return ctx.senderName?.trim() || ctx.from?.trim() || undefined;
|
|
34
|
+
}
|
|
35
|
+
const base = ctx.groupChannel?.trim() || ctx.groupSubject?.trim() || ctx.channelTitle?.trim() || ctx.from?.trim() || '';
|
|
36
|
+
if (!base) return undefined;
|
|
37
|
+
const id = extractConversationId(ctx.from);
|
|
38
|
+
if (!id) return base;
|
|
39
|
+
if (!shouldAppendId(id)) return base;
|
|
40
|
+
if (base === id) return base;
|
|
41
|
+
if (base.includes(id)) return base;
|
|
42
|
+
return `${base} id:${id}`;
|
|
43
|
+
}export{resolveConversationLabel};//# sourceMappingURL=conversation-label.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-label.js","sources":["../../src/channels/conversation-label.ts"],"sourcesContent":[null],"names":[],"mappings":"2CAAA;;;;;;AAMG;AA0BH;AACA;AACA;AAEA,SAAS,qBAAqB,CAAC,IAAa,EAAA;AACxC,EAAA,MAAA,UAAa,IAAG,EAAI,IAAE,EAAI;AAC1B,EAAA,IAAA,CAAA,OAAK,EAAO,OAAA,SAAA;AAAE,EAAA,MAAA,KAAA,WAAgB,KAAC,CAAA,GAAA,CAAA,CAAA,MAAA,CAAA,OAAA,CAAA;AAC/B,EAAA,OAAA,KAAM,CAAK,MAAG,GAAA,CAAO,GAAC,KAAM,CAAA,KAAK,CAAA,MAAO,GAAA,CAAA,CAAO,GAAE,OAAA;;AAErD,SAAC,cAAA,CAAA,EAAA,EAAA;AAED;MACI,UAAA,CAAA,IAAA,CAAA,EAAA,CAAA,EAAA,OAAA,IAAA;AACA,EAAA,OAAI,KAAA;AAAqB;AACzB;AACJ;AAEA;;;AAGG,EAAA,MAAA,QAAA,GAAA,GAAA,CAAA,iBAAA,EAAA,IAAA,EAAA;AACH,EAAA,IAAM,QAAA,EAAU,OAAA,QAAA;QACZ,cAAiB,GAAI,kBAAiB,EAAE;AACxC,EAAA,IAAA,WAAY,EAAA,OAAA,WAAA;AAAE,EAAA,MAAA,4BAAgB,CAAA,GAAA,CAAA,QAAA,CAAA;MAE9B,QAAM,KAAA,QAAiB;AACvB,IAAA,OAAI,GAAA,CAAA,UAAW,EAAA,IAAA,EAAA,IAAA,GAAA,CAAA,IAAA,EAAA,IAAA,EAAA,IAAA,SAAA;AAAE,EAAA;QAEjB,IAAM,GAAA,GAAQ,aAAG,EAAA,IAAA,EAAkB,IAAI,GAAA,CAAA,YAAU,EAAA,IAAA,EAAA,IAAA,GAAA,CAAA,YAAA,EAAA,IAAA,EAAA,IAAA,GAAA,CAAA,IAAA,EAAA,IAAA,EAAA,IAAA,EAAA;AACjD,EAAA,IAAA,CAAA,IAAI,EAAA,OAAQ,SAAa;AACrB,EAAA,MAAA,EAAA,GAAA,sBAA2B,GAAE,CAAA,IAAI,CAAG;MACvC,CAAA,EAAA,EAAA,OAAA,IAAA;AAED,EAAA,IAAA,CAAA,cACQ,CAAA,EAAA,CAAA,EAAA,OAAY,IAAE;AACtB,EAAA,IAAA,IAAK,KAAI,EAAA,EAAA,OAAA,IAAA;AAAE,EAAA,IAAA,IAAA,CAAA,cAAiB,OAAA,IAAA;SAE5B,CAAM,EAAE,IAAG,CAAA,IAAA,EAAA,EAAA,CAAA,CAAA;AACX"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Channels module - barrel export
|
|
3
|
+
*
|
|
4
|
+
* Provides openclaw-inspired channel features adapted to
|
|
5
|
+
* messenger-box's Props architecture. All channel-related
|
|
6
|
+
* types, utilities, and configuration are exported from here.
|
|
7
|
+
*/
|
|
8
|
+
export * from './types';
|
|
9
|
+
export * from './registry';
|
|
10
|
+
export * from './typing';
|
|
11
|
+
export * from './ack-reactions';
|
|
12
|
+
export * from './conversation-label';
|
|
13
|
+
export * from './sender-identity';
|
|
14
|
+
export * from './command-gating';
|
|
15
|
+
export * from './allowlist-match';
|
|
16
|
+
export * from './mention-gating';
|
|
17
|
+
export * from './session';
|
|
18
|
+
export * from './channel-config';
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mention gating - inspired by openclaw's mention-gating,
|
|
3
|
+
* adapted to messenger-box's Props architecture.
|
|
4
|
+
*
|
|
5
|
+
* Controls how @mentions interact with message routing in group channels,
|
|
6
|
+
* supporting require-mention, bypass, and detection logic.
|
|
7
|
+
*/
|
|
8
|
+
export interface IMentionGatingProps {
|
|
9
|
+
/** Whether @mention is required in groups for message processing */
|
|
10
|
+
requireMentionInGroups: boolean;
|
|
11
|
+
/** Whether to strip mentions from message text before processing */
|
|
12
|
+
stripMentions: boolean;
|
|
13
|
+
/** Patterns to strip from mentions (regex strings) */
|
|
14
|
+
stripPatterns: string[];
|
|
15
|
+
/** Whether unmentioned group messages are silently ignored */
|
|
16
|
+
silentIgnoreUnmentioned: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare const DEFAULT_MENTION_GATING_PROPS: IMentionGatingProps;
|
|
19
|
+
export interface IMentionCheckParams {
|
|
20
|
+
/** The message text */
|
|
21
|
+
messageText: string;
|
|
22
|
+
/** Self user ID to check mentions against */
|
|
23
|
+
selfUserId?: string;
|
|
24
|
+
/** Self username to check mentions against */
|
|
25
|
+
selfUsername?: string;
|
|
26
|
+
/** Additional patterns to match as mentions */
|
|
27
|
+
additionalPatterns?: string[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Checks whether the current user was mentioned in the message
|
|
31
|
+
*/
|
|
32
|
+
export declare function wasMentioned(params: IMentionCheckParams): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Strips mention patterns from message text
|
|
35
|
+
*/
|
|
36
|
+
export declare function stripMentionsFromText(text: string, patterns: string[]): string;
|
|
37
|
+
export interface IMentionGateParams {
|
|
38
|
+
/** Whether group mention is required */
|
|
39
|
+
requireMention: boolean;
|
|
40
|
+
/** Whether the current context is a group */
|
|
41
|
+
isGroup: boolean;
|
|
42
|
+
/** Whether mention was detected */
|
|
43
|
+
wasMentioned: boolean;
|
|
44
|
+
/** Whether to bypass mention requirement */
|
|
45
|
+
bypassMention?: boolean;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Determines whether a message should be processed based on mention gating
|
|
49
|
+
*/
|
|
50
|
+
export declare function shouldProcessMessage(params: IMentionGateParams): boolean;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mention gating - inspired by openclaw's mention-gating,
|
|
3
|
+
* adapted to messenger-box's Props architecture.
|
|
4
|
+
*
|
|
5
|
+
* Controls how @mentions interact with message routing in group channels,
|
|
6
|
+
* supporting require-mention, bypass, and detection logic.
|
|
7
|
+
*/
|
|
8
|
+
const DEFAULT_MENTION_GATING_PROPS = {
|
|
9
|
+
requireMentionInGroups: true,
|
|
10
|
+
stripMentions: true,
|
|
11
|
+
stripPatterns: [],
|
|
12
|
+
silentIgnoreUnmentioned: true
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Checks whether the current user was mentioned in the message
|
|
16
|
+
*/
|
|
17
|
+
function wasMentioned(params) {
|
|
18
|
+
const {
|
|
19
|
+
messageText,
|
|
20
|
+
selfUserId,
|
|
21
|
+
selfUsername,
|
|
22
|
+
additionalPatterns
|
|
23
|
+
} = params;
|
|
24
|
+
if (!messageText) return false;
|
|
25
|
+
const text = messageText.toLowerCase();
|
|
26
|
+
// Check for @userId mention
|
|
27
|
+
if (selfUserId && text.includes(`@${selfUserId.toLowerCase()}`)) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
// Check for @username mention
|
|
31
|
+
if (selfUsername && text.includes(`@${selfUsername.toLowerCase()}`)) {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
// Check additional patterns
|
|
35
|
+
if (additionalPatterns) {
|
|
36
|
+
for (const pattern of additionalPatterns) {
|
|
37
|
+
try {
|
|
38
|
+
const regex = new RegExp(pattern, 'i');
|
|
39
|
+
if (regex.test(messageText)) return true;
|
|
40
|
+
} catch {
|
|
41
|
+
// Skip invalid patterns
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Strips mention patterns from message text
|
|
49
|
+
*/
|
|
50
|
+
function stripMentionsFromText(text, patterns) {
|
|
51
|
+
let result = text;
|
|
52
|
+
for (const pattern of patterns) {
|
|
53
|
+
try {
|
|
54
|
+
const regex = new RegExp(pattern, 'gi');
|
|
55
|
+
result = result.replace(regex, '').trim();
|
|
56
|
+
} catch {
|
|
57
|
+
// Skip invalid patterns
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return result.replace(/\s+/g, ' ').trim();
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Determines whether a message should be processed based on mention gating
|
|
64
|
+
*/
|
|
65
|
+
function shouldProcessMessage(params) {
|
|
66
|
+
// Non-group messages always proceed
|
|
67
|
+
if (!params.isGroup) return true;
|
|
68
|
+
// If mentions aren't required, always proceed
|
|
69
|
+
if (!params.requireMention) return true;
|
|
70
|
+
// If mentioned or bypassed, proceed
|
|
71
|
+
return params.wasMentioned || params.bypassMention === true;
|
|
72
|
+
}export{DEFAULT_MENTION_GATING_PROPS,shouldProcessMessage,stripMentionsFromText,wasMentioned};//# sourceMappingURL=mention-gating.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mention-gating.js","sources":["../../src/channels/mention-gating.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA;;;;;;AAMG;AAiBI,MAAM,4BAA4B,GAAwB;AAC7D,EAAA,sBAAA,EAAsB,IAAE;AACxB,EAAA,aAAA,EAAa,IAAE;AACf,EAAA,aAAA,EAAa,EAAE;AACf,EAAA,uBAAA,EAAuB;;AAkB3B;;AAEG;AACG,SAAU,YAAY,CAAC,MAA2B,EAAA;QACpD;AACA,IAAA,WAAK;AAAa,IAAA,UAAA;AAElB,IAAA,YAAU;IAEV;AACA,GAAA,GAAA,MAAI;AACA,EAAA,IAAA,CAAA,aAAY,OAAA,KAAA;QACf,IAAA,GAAA,WAAA,CAAA,WAAA,EAAA;;AAGD,EAAA,IAAA,UAAI,IAAY,IAAI,CAAA,aAAc,UAAI,CAAA,WAAa,EAAA,CAAA,CAAA,CAAA,EAAW;AAC1D,IAAA,OAAA,IAAO;;;MAIX,YAAI,IAAA,IAAkB,SAAG,CAAA,CAAA,CAAA,EAAA,YAAA,CAAA,WAAA,EAAA,CAAA,CAAA,CAAA,EAAA;AACrB,IAAA,OAAA,IAAK;AACD,EAAA;;AAEI,EAAA,IAAA,kBAAI,EAAM;AAAmB,IAAA,KAAA,MAAA,OAAA,IAAA,kBAAY,EAAA;;AAC3C,QAAA,MAAA,KAAO,GAAA,IAAA,MAAA,CAAA,OAAA,EAAA,GAAA,CAAA;iBACL,CAAA,IAAA,CAAA,WAAA,CAAA,EAAA,OAAwB,IAAA;cAC3B;;MAER;AAED,IAAA;AACJ,EAAC;AAED,EAAA,OAAA,KAAA;;AAEG;AACH;;AAEI,SAAW,qBAAsB,CAAA,IAAA,EAAA,QAAA,EAAA;AAC7B,EAAA,IAAA,MAAI,GAAC,IAAA;aACD,OAAM,YAAY,EAAA;AAClB,IAAA,IAAA;YACH,KAAA,GAAA,IAAA,MAAA,CAAA,OAAA,EAAA,IAAA,CAAA;AAAC,MAAA,MAAA,GAAO,MAAA,CAAA,OAAA,CAAA,KAAA,EAAA,EAAA,CAAA,CAAA,IAAA,EAAA;YACL;;IAER;;AAEJ,EAAC,OAAA,MAAA,CAAA,OAAA,CAAA,MAAA,EAAA,GAAA,CAAA,CAAA,IAAA,EAAA;AAiBD;;AAEG;AACH;AACI,SAAA,oBAAA,CAAA,MAAoC,EAAA;;AACf,EAAA,IAAA,CAAA,MAAA,CAAA,OAAY,EAAA,OAAA,IAAA;;MAGjC,CAAA,MAAK,CAAA,cAAO,EAAc,OAAA,IAAA;AAAE;SAE5B,MAAA,CAAA,YAAA,IAAA,MAAA,CAAA,aAAoC,KAAA,IAAA;"}
|